Cálculo de los defectos de convexidad con OpenCV 2.4 en c ++

Estoy usando OpenCV 2.4 para calcular el casco convexo de una imagen.

También estoy procesando algo para eliminar el ruido de la imagen, que no es realmente relevante para la pregunta.

El código para calcular convexHull es el siguiente:

... cv::Mat sourceImage; // assume something is already here please cv::vector hierarchy; std::vector<std::vector > contours; cv::findContours( sourceImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE,cv::Point(0, 0)); // Find the convex hull object for each contour vector<cv::vector >hull( contours.size() ); for (int i = 0; i < contours.size(); i++) { convexHull( contours[i], hull[i], false ); } ... 

Teniendo tanto el casco convexo como los contornos, ahora quiero calcular los defectos de convexidad del casco (s), que al mirar la documentación de OpenCV pensé que sería así:

 cv::Vec4i defects; convexityDefects(cv::Mat(contours), hull, defects); 

Al hacer esto, recibo este error:

 OpenCV Error: Assertion failed (ptnum > 3) in convexityDefects, file ./opencv/opencv/modules/imgproc/src/contours.cpp, line 1969 

¿Alguna idea sobre lo que estoy haciendo mal cuando uso convexityDefects?

Documentación de Opencv convexityDefects

Gracias por adelantado.

ACTUALIZAR

Gracias a la respuesta de Innuendo, actualicé el código del bucle principal a:

 std::vector defects; vector<cv::vector >hull( contours.size() ); for (int i = 0; i < contours.size(); i++) { convexHull( contours[i], hull[i], false ); convexityDefects(contours[i], hull[i], defects[i]); } 

Usando esto, el error que ahora obtengo es:

 OpenCV Error: Assertion failed (hull.checkVector(1, CV_32S) > 2) in convexityDefects 

Desde la wiki de openCV:

Encuentra los defectos de convexidad de un contorno.

Entonces deberías incluirlo en tu ciclo.

 std::vector defects; vector >hull( contours.size() ); for (int i = 0; i < contours.size(); i++) { convexHull( contours[i], hull[i], false ); convexityDefects(contours[i], hull[i], defects[i]); } 

Además, como mencionaste, en wiki se dice:

casco - Casco convexo de salida. Es un vector entero de índices o un vector de puntos. En el primer caso, los elementos del casco son índices basados ​​en 0 de los puntos convexos del casco en el conjunto original (dado que el conjunto de puntos convexos del casco es un subconjunto del conjunto de puntos original). En el segundo caso, los elementos del casco son los mismos puntos convexos del casco.

Para aquellos que no leen los comentarios o no lo vieron, la solución es usar:

vector >hull;

para crear el casco en lugar de:

vector >hull;

como convexityDefects solo funciona en cascos almacenados como una serie de índices en lugar de una serie de puntos.

Tristemente, esto da otro problema ya que drawContours solo dibuja contornos almacenados como una serie de puntos y no como una serie de índices. Entonces, si desea dibujar sus cascos en una etapa posterior, es posible que desee crear 2 almacenes cuando encuentre los cascos, uno para dibujar y otro para encontrar defectos. Algo en la línea de los siguientes trabajos:

  // create storage space vector > hullsI(contours.size()); vector > hullsP(contours.size()); vector > defects(contours.size()); for(int i = 0; i  

Puede ser más eficiente usar un método diferente para dibujar los cascos en lugar de calcularlos dos veces, pero esta fue la forma más elegante que vi de hacerlo.

También sigo using namespace cv C / C ++ (tipo Java) pero creo que si agregas el using namespace cv a la parte superior del código puedes ahorrar tener que tener cv :: en todo tu código.

Espero no haber pisado los dedos Innuendo, no es mi intención en absoluto si lo tengo.

He estado teniendo el mismo error por un tiempo hasta que me presentaron la solución. Simplemente verifique el tamaño de los contours[i] antes de llamar a convexityDefects

 /// Find the convex hull object for each contour vector > hullsI(contours.size()); vector > hullsP(contours.size()); vector > defects(contours.size()); for(int i = 0; i 3 ) { convexityDefects(contours[i], hullsI[i], defects[i]); } } 

Espero eso ayude 🙂

tuve problemas como los mencionados anteriormente, pero finalmente escribí el correcto 🙂

 vector> hull( contours.size() ); vector > hullsI(contours.size()); vector> convdefect(contours.size()); for( int i = 0; i < contours.size(); i++ ) { convexHull( Mat(contours[i]), hull[i], false); convexHull( Mat(contours[i]), hullsI[i], false); if(hullsI[i].size() > 3 ) convexityDefects(contours[i],hullsI[i],convdefect[i]); } /// Draw contours + hull results Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 ); for( int i = 0; i< contours.size(); i++ ) { size_t count = contours[i].size(); if( count <300 ) continue; //Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255)); drawContours( drawing, contours, i, Scalar(255,0,0), 1, 8, vector(), 0, Point()); drawContours( drawing, hull, i, Scalar(0,0,255), 1, 8, vector(), 0, Point()); } /// Draw convexityDefects for( int i = 0; i< contours.size(); i++ ) { size_t count = contours[i].size(); if( count <300 ) continue; vector::iterator d=convdefect[i].begin(); while( d!=convdefect[i].end() ) { Vec4i& v=(*d); int startidx=v[0]; Point ptStart( contours[i][startidx] ); int endidx=v[1]; Point ptEnd( contours[i][endidx] ); int faridx=v[2]; Point ptFar( contours[i][faridx] ); float depth = v[3] / 256; line( drawing, ptStart, ptEnd, Scalar(0,255,0), 1 ); line( drawing, ptStart, ptFar, Scalar(0,255,0), 1 ); line( drawing, ptEnd, ptFar, Scalar(0,255,0), 1 ); circle( drawing, ptFar, 4, Scalar(0,255,0), 2 ); d++; } }