hough findcontours explained canny algoritmo c++ opencv edge-detection

c++ - findcontours - ¿Cómo detectar el Sol desde el cielo del espacio en OpenCv?



sobel opencv (3)

Necesito detectar el Sol desde el cielo del espacio.

Estos son ejemplos de las imágenes de entrada:

Tengo tales resultados después del filtrado morfológico (operación open para dos veces)

Aquí está el código del algoritmo de este procesamiento:

// Color to Gray cvCvtColor(image, gray, CV_RGB2GRAY); // color threshold cvThreshold(gray,gray,150,255,CV_THRESH_BINARY); // Morphologic open for 2 times cvMorphologyEx( gray, dst, NULL, CV_SHAPE_RECT, CV_MOP_OPEN, 2);

¿No es un proceso demasiado pesado para una tarea tan simple? ¿Y cómo encontrar el centro del sol? Si encuentro puntos blancos, entonces encontraré puntos blancos de gran Tierra (esquina superior izquierda en la primera imagen de ejemplo)

Por favor, avíseme, por favor, mis medidas adicionales para detectar el sol.

ACTUALIZACIÓN 1:

Algoritmo de {x,y} = {M10/M00, M01/M00} de obtener centroid por fórmula: {x,y} = {M10/M00, M01/M00}

CvMoments moments; cvMoments(dst, &moments, 1); double m00, m10, m01; m00 = cvGetSpatialMoment(&moments, 0,0); m10 = cvGetSpatialMoment(&moments, 1,0); m01 = cvGetSpatialMoment(&moments, 0,1); // calculating centroid float centroid_x = m10/m00; float centroid_y = m01/m00; cvCircle( image, cvPoint(cvRound(centroid_x), cvRound(centroid_y)), 50, CV_RGB(125,125,0), 4, 8,0);

Y donde está la Tierra en la foto, obtuve tal resultado:

Entonces, el centroide está en la Tierra. :(

ACTUALIZACIÓN 2:

Probando cvHoughCircles :

CvMemStorage* storage = cvCreateMemStorage(0); CvSeq* circles = cvHoughCircles(dst, storage, CV_HOUGH_GRADIENT, 12, dst->width/2, 255, 100, 0, 35); if ( circles->total > 0 ) { // getting first found circle float* circle = (float*)cvGetSeqElem( circles, 0 ); // Drawing: // green center dot cvCircle( image, cvPoint(cvRound(circle[0]),cvRound(circle[1])), 3, CV_RGB(0,255,0), -1, 8, 0 ); // wrapping red circle cvCircle( image, cvPoint(cvRound(circle[0]),cvRound(circle[1])), cvRound(circle[2]), CV_RGB(255,0,0), 3, 8, 0 ); }

Primer ejemplo: bingo, pero el segundo - no; (

He intentado con una configuración diferente de cvHoughCircles() : no he podido encontrar la configuración para que se ajuste a todas mis fotos de ejemplo.

ACTUALIZACIÓN3:

matchTemplate enfoque de matchTemplate funcionó para mí (respuesta de mevatron ). Funcionó con una gran cantidad de pruebas.


Enfoque de segmentación de color

Haga una segmentación de color en las imágenes para identificar objetos en el fondo negro. Puede identificar el sol de acuerdo con su área (dado que esto lo identifica de manera única, o no varía en gran medida a través de las imágenes). Un enfoque más sofisticado podría calcular los momentos de la imagen, por ejemplo, los momentos hu de los objetos. Vea esta página para estas características.

Use un algoritmo de clasificación de su elección para hacer la clasificación real de los objetos encontrados. El enfoque más simple es especificar manualmente los umbrales, resp. rangos de valores que funcionan para todas (la mayoría) de las combinaciones de objeto / imagen.

Puede calcular la posición real a partir de los momentos crudos, ya que para el sol circular la posición es igual al centro de masa

Centroid: {x, y } = { M10/M00, M01/M00 }

Enfoque de mapa de borde

Otra opción sería una transformación circular del mapa de borde, con suerte devolverá algunos círculos candidatos (por posición y radio). Puede seleccionar el círculo solar de acuerdo con el radio que espera (si tiene suerte, hay como máximo uno).


¿Qué tal si matchTemplate enfoque simple de matchTemplate ? Usé esta imagen de plantilla:

Y detectó 3 de cada 3 imágenes de sol que probé:

Esto debería funcionar debido al hecho de que los círculos (en su caso, el sol) son invariantes de forma rotatoria, y dado que está tan lejos del sol, también debería ser invariable a escala general. Entonces, la coincidencia de plantillas funcionará muy bien aquí.

Finalmente, aquí está el código que solía hacer esto:

#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> using namespace cv; using namespace std; int main(int argc, char* argv[]) { /// Load image and template string inputName = "sun2.png"; string outputName = "sun2_detect.png"; Mat img = imread( inputName, 1 ); Mat templ = imread( "sun_templ.png", 1 ); /// Create the result matrix int result_cols = img.cols - templ.cols + 1; int result_rows = img.rows - templ.rows + 1; Mat result( result_cols, result_rows, CV_32FC1 ); /// Do the Matching and Normalize matchTemplate(img, templ, result, CV_TM_CCOEFF); normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat()); Point maxLoc; minMaxLoc(result, NULL, NULL, NULL, &maxLoc); rectangle(img, maxLoc, Point( maxLoc.x + templ.cols , maxLoc.y + templ.rows ), Scalar(0, 255, 0), 2); rectangle(result, maxLoc, Point( maxLoc.x + templ.cols , maxLoc.y + templ.rows ), Scalar(0, 255, 0), 2); imshow("img", img); imshow("result", result); imwrite(outputName, img); waitKey(0); return 0; }

Espero que encuentres útil!


Una simple adición a su código es filtrar los objetos en función de su tamaño. Si siempre espera que la Tierra sea mucho más grande que el Sol, o que el Sol tenga casi la misma área en cada imagen, puede filtrarla por área.

Pruebe el detector de blobs para esta tarea.

Y tenga en cuenta que puede ser útil aplicar una apertura / cierre morfológico en lugar de simplemente erosionar o dilatar, por lo que su sol tendrá casi la misma área antes y después del procesamiento.