utilizar regionprops extent example como c++ matlab opencv image-processing opencv-contour

c++ - extent - regionprops()



openCV 2.4.10 bwlabel-componentes conectados (1)

  1. He pensado que el etiquetado se hace para conectar 4-8 objetos. ¿Puedes explicar qué es realmente el etiquetado? Yo tomaría cualquier enlace.

La demostración más clara de lo que hace el etiquetado es en la documentación de Matlab para bwlabel . Si compara la matriz original BW con la matriz resultante L , verá que toma una imagen binaria y asigna etiquetas únicas a cada grupo conectado de 1 :

L = 1 1 1 0 0 0 0 0 1 1 1 0 2 2 0 0 1 1 1 0 2 2 0 0 1 1 1 0 0 0 3 0 1 1 1 0 0 0 3 0 1 1 1 0 0 0 3 0 1 1 1 0 0 3 3 0 1 1 1 0 0 0 0 0

Aquí hay tres componentes etiquetados. Este ejemplo busca componentes con 4 conexiones; se considera que un píxel está conectado al píxel actual si está a la izquierda, derecha, arriba o debajo de él. Los objetos conectados 8 incluyen las diagonales, lo que daría como resultado que las etiquetas 2 y 3 se fusionen para la matriz anterior, ya que la esquina inferior derecha del objeto 2 y la parte superior del objeto 3 están conectadas diagonalmente. El algoritmo de etiquetado de componentes conectados se describe en la Wikipedia aquí .

2. componentes conectados en OpenCV en este artículo algunas personas están hablando de CVblob y algunos sobre cvContourArea de la opep, ¿puede explicar la diferencia? y ¿cuál será más adecuado para mi caso de uso?

OpenCV 3.0 está fuera de beta y tiene dos nuevos métodos: connectedComponents y connectedComponentsWithStats ( documentación ). Si intentas replicar la bwlabel la bwlabel de Matlab, este es el camino a seguir.

Escribí un programa de prueba para probar connectedComponentsWithStats (complete el código a continuación) usando esto como mi imagen de prueba:

(En realidad, esta imagen se reduce de 800x600 a 400x300, pero el código para generarlo se incluye a continuación).

Genere la imagen etiquetada usando:

int nLabels = connectedComponentsWithStats(src, labels, stats, centroids, 8, CV_32S);

El valor devuelto en nLabels es 5 . Recuerde que este método considera que el fondo es la etiqueta 0 .

Para ver cuáles son las áreas etiquetadas, puede escalar los valores de escala de grises de [0..nLabels-1] a [0..255] , o puede asignar valores aleatorios RGB y crear una imagen en color. Para esta prueba, simplemente imprimí los valores en un par de ubicaciones que sabía que estaban en diferentes componentes.

cout << "Show label values:" << endl; // Middle of square at top-left int component1Pixel = labels.at<int>(150,150); cout << "pixel at(150,150) = " << component1Pixel << endl; // Middle of rectangle at far right int component2Pixel = labels.at<int>(300,550); cout << "pixel at(300,550) = " << component2Pixel << endl << endl; Show label values: pixel at(150,150) = 1 pixel at(300,550) = 2

Las stats son 5 x nLabels Tapetes que contienen left, top, width, height, and area para cada componente (incluido el fondo). Para esta imagen:

stats: (left,top,width,height,area) [0, 0, 800, 600, 421697; 100, 100, 101, 101, 10201; 500, 150, 101, 301, 30401; 350, 246, 10, 10, 36; 225, 325, 151, 151, 17665]

Notarás que el componente 0 es el ancho / alto completo de la imagen. Al sumar todas las áreas, obtienes 480,000 = 800x600 . Los primeros 4 elementos se pueden usar para crear un rectángulo delimitador:

Rect(Point(left,top), Size(width,height))

centroids es una estera de 2 x nLabels contiene las coordenadas x, y del centro de gravedad de cada componente:

centroids: (x, y) [398.8575636060963, 298.8746232484461; 150, 150; 550, 300; 354.5, 250.5; 300, 400]

Finalmente, en algún momento es probable que desee realizar un procesamiento adicional en uno de los componentes individualmente. Aquí uso compare para generar un nuevo Mat only2 que solo contenga píxeles de labels que marquen 2 .

compare(labels, 2, only2, CMP_EQ);

compare útilmente establece estos píxeles a un valor de 255 en la nueva imagen para que pueda ver los resultados:

Aquí está el código completo:

#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace std; using namespace cv; int main(int argc, const char * argv[]) { // Create an image const int color_white = 255; Mat src = Mat::zeros(600, 800, CV_8UC1); rectangle(src, Point(100, 100), Point(200, 200), color_white, CV_FILLED); rectangle(src, Point(500, 150), Point(600, 450), color_white, CV_FILLED); rectangle(src, Point(350,250), Point(359,251), color_white, CV_FILLED); rectangle(src, Point(354,246), Point(355,255), color_white, CV_FILLED); circle(src, Point(300, 400), 75, color_white, CV_FILLED); imshow("Original", src); // Get connected components and stats const int connectivity_8 = 8; Mat labels, stats, centroids; int nLabels = connectedComponentsWithStats(src, labels, stats, centroids, connectivity_8, CV_32S); cout << "Number of connected components = " << nLabels << endl << endl; cout << "Show label values:" << endl; int component1Pixel = labels.at<int>(150,150); cout << "pixel at(150,150) = " << component1Pixel << endl; int component2Pixel = labels.at<int>(300,550); cout << "pixel at(300,550) = " << component2Pixel << endl << endl; // Statistics cout << "Show statistics and centroids:" << endl; cout << "stats:" << endl << "(left,top,width,height,area)" << endl << stats << endl << endl; cout << "centroids:" << endl << "(x, y)" << endl << centroids << endl << endl; // Print individual stats for component 1 (component 0 is background) cout << "Component 1 stats:" << endl; cout << "CC_STAT_LEFT = " << stats.at<int>(1,CC_STAT_LEFT) << endl; cout << "CC_STAT_TOP = " << stats.at<int>(1,CC_STAT_TOP) << endl; cout << "CC_STAT_WIDTH = " << stats.at<int>(1,CC_STAT_WIDTH) << endl; cout << "CC_STAT_HEIGHT = " << stats.at<int>(1,CC_STAT_HEIGHT) << endl; cout << "CC_STAT_AREA = " << stats.at<int>(1,CC_STAT_AREA) << endl; // Create image with only component 2 Mat only2; compare(labels, 2, only2, CMP_EQ); imshow("Component 2", only2); waitKey(0); }

Aquí está el código original de matlab:

% Calculate each separated object area cDist=regionprops(bwImg, ''Area''); cDist=[cDist.Area]; % Label each object [bwImgLabeled, ~]=bwlabel(bwImg); % Calculate min and max object size based on assumptions on the color % checker size maxLabelSize = prod(size(imageData)./[4 6]); minLabelSize = prod(size(imageData)./[4 6]./10); % Find label indices for objects that are too large or too small remInd = find(cDist > maxLabelSize); remInd = [remInd find(cDist < minLabelSize)]; % Remove over/undersized objects for n=1:length(remInd) ri = bwImgLabeled == remInd(n); bwImgLabeled(ri) = 0;

Aquí está mi código usando openCV

//regionprops(bwImg, ''Area''); // cDist=[cDist.Area] //cv::FileStorage file("C://Users//gdarmon//Desktop//gili.txt", cv::FileStorage::WRITE); // //file << dst; dst.convertTo(dst,CV_8U); cv::vector<cv::vector<cv::Point> > contours; cv::vector<cv::Vec4i> hierarchy; cv::findContours(dst,contours,hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE); std::vector<cv::Moments> mu(contours.size()); for (int i = 0; i < contours.size(); i++) { mu[i] = cv::moments(contours[i],false); } vector<cv::Point2f> mc( contours.size() ); for( int i = 0; i < contours.size(); i++ ) { mc[i] = cv::Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); }

Desde ahora tengo los contornos, me gustaría utilizar la función bwlabel
1. He pensado que el etiquetado se hace para conectar 4-8 objetos. ¿Puedes explicar qué es realmente el etiquetado? Yo tomaría cualquier enlace.
2. componentes conectados en OpenCV en este artículo. Algunas personas están hablando de CVblob y otras sobre cvContourArea de la opep, ¿puede explicar la diferencia? y ¿cuál será más adecuado para mi caso de uso?

Actualización: aquí es lo que he intentado usar cvBlobs

IplImage* img_bw = new IplImage(dst); CBlobResult blobs; CBlob *currentBlob; blobs = CBlobResult(img_bw, NULL, 0); // Exclude all white blobs smaller than the given value (80) // The bigger the last parameter, the bigger the blobs need // to be for inclusion blobs.Filter( blobs, B_EXCLUDE, CBlobGetArea(), B_LESS, 80 ); // Get the number of blobs discovered int num_blobs = blobs.GetNumBlobs(); // Display the filtered blobs IplImage* filtered = cvCreateImage( cvGetSize( img_bw ), IPL_DEPTH_8U, 3 ); cvMerge( img_bw, img_bw, img_bw, NULL, filtered ); for ( int i = 0; i < num_blobs; i++ ) { currentBlob = blobs.GetBlob( i ); currentBlob->FillBlob( filtered, CV_RGB(255,0,0)); } // Display the input / output windows and images cvNamedWindow( "input" ); cvNamedWindow( "output" ); cvShowImage("input", img_bw ); cvShowImage("output", filtered); cv::waitKey(0); /*% Calculate min and max object size based on assumptions on the color % checker size maxLabelSize = prod(size(imageData)./[4 6]); minLabelSize = prod(size(imageData)./[4 6]./10);*/ double maxLabelSize = (dst.rows/4.0) * (dst.cols/6.0); double minLabelSize = ((dst.rows/40.0) * (dst.cols/60.0));