Как обнаружить Солнце с космического неба в OpenCv? - PullRequest
10 голосов
/ 22 ноября 2011

Мне нужно обнаружить Солнце с космического неба.

Вот примеры входных изображений:

image image

У меня естьтакие результаты после морфологической фильтрации (операция open дважды)

image image

Вот код алгоритма этой обработки:

// 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);

Isn 'Не слишком ли сложная обработка для такой простой задачи?А как найти центр Солнца?Если я найду белые точки, то найду белые точки большой Земли (левый верхний угол на первом примере изображения)

Пожалуйста, посоветуйте мне, пожалуйста, мои дальнейшие действия по обнаружению Солнца.

ОБНОВЛЕНИЕ 1:

Попытка алгоритма получения centroid по формуле: {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);

А где на фотографии Земля, я получил такой результат:image

Итак, центроид находится на Земле.: (

ОБНОВЛЕНИЕ 2:

Попытка 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 ); 
}

image image

Перваяпример: бинго, но второй - нет; (

Я пробовал другую конфигурацию cvHoughCircles() - не смог найти конфигурацию, подходящую для каждого моего примера фотографии.

UPDATE3:

matchTemplate подход работал для меня (ответ mevatron). Он работал с большим количеством тестов.

Ответы [ 3 ]

9 голосов
/ 22 ноября 2011

Как насчет попытки простого matchTemplate подхода.Я использовал этот шаблон изображения:
enter image description here

И он обнаружил 3 из 3 изображений солнца, которые я пробовал: enter image description here enter image description here enter image description here

Это должно работать из-за того факта, что круги (в вашем случае солнце) вращательно инвариантны, и, поскольку вы находитесь очень далеко от солнца, они также должны быть примерно масштабно инвариантны.Итак, сопоставление с шаблоном здесь будет работать очень хорошо.

Наконец, вот код, который я использовал для этого:

#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;
}

Надеюсь, вы найдете это полезным!

2 голосов
/ 22 ноября 2011

Простое дополнение к вашему коду - отфильтровать объекты по размеру.Если вы всегда ожидаете, что Земля будет намного больше Солнца или Солнце будет иметь почти одинаковую площадь на каждом снимке, вы можете отфильтровать ее по площади.

Попробуйте Детектор BLOB-объектов дляэто задание.

И обратите внимание, что может быть полезно применить морфологическое открытие / закрытие вместо простой эрозии или расширения, так что ваше солнце будет иметь почти одинаковую площадь до и после обработки.

2 голосов
/ 22 ноября 2011

Подход к сегментации цвета

Выполните цветовую сегментацию изображений, чтобы идентифицировать объекты на черном фоне.Вы можете идентифицировать солнце в соответствии с его областью (учитывая, что оно однозначно идентифицирует его, и, соответственно, не меняется в значительной степени по изображениям).Более сложный подход может вычислить моменты изображения, например, моменты объектов.См. эту страницу для этих функций.

Используйте алгоритм классификации по вашему выбору, чтобы выполнить фактическую классификацию найденных объектов.Самый простой подход заключается в ручном указании порогов, соответственно.диапазоны значений, которые работают для всех (большинства) комбинаций вашего объекта / изображения.

Вы можете вычислить фактическую позицию из необработанных моментов, например для круглого солнца: позиция равнацентр масс

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

Подход к Edge Map

Другим вариантом будет преобразование окружности, если будет выполнено преобразование карты ребер, которое, мы надеемся, вернет некоторые подходящие круги.(по положению и радиусу).Вы можете выбрать солнечный круг в соответствии с ожидаемым радиусом (если вам повезет, он не больше одного).

...