2011-11-21 178 views
7

我需要从太空中探测太阳。如何在OpenCv中检测太空中的太阳?

这些输入图像的例子:

我有形态学滤波后,这样的结果

这里的(两次open操作)该处理的算法代码:

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

对于这么简单的任务来说不是太重吗?以及如何找到太阳的中心?如果我发现白点,我会发现大地球的白点(第一个示例图像上的左上角)

请告诉我,我的进一步行动,检测太阳。

更新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); 

在哪里地球的照片,我得到了这样的结果:

所以,质心在地球上。 :(

更新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); 
} 

第一个例子:宾果游戏,但第二 - 无;(

I”已经尝试了的不同配置- 无法找到适合每个示例照片的配置。

UPDATE3:

matchTemplate办法为我工作(的mevatron响应)。它与大量测试一起工作。

回答

8

如何尝试简单的matchTemplate方法。我用这个模板图像:
enter image description here

而且,它检测到的3出的太阳图像我试过3: enter image description hereenter image description hereenter 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

实际上,其工作原因与上述不同。对于初学者来说,这些图片中的任何地方都没有使用过类似的模板。而且,这比初始形态学方法慢几倍。 – mmgp

+1

好点:)然而,因为我假设太空船是在我们的太阳系,我相信可以肯定地说只有一个太阳会出现:D – mevatron

+0

我想这会失败,如果任何部分的HUD(飞行员用户界面)在阳光之上。除非模板匹配能够对比赛的优异程度进行评分,那么您可以将最好的结果设定为阈值,并且可能会有一些障碍。 –

2

颜色分割方法

请在图像的色彩分割,以确定在黑色的背景对象。你可以根据它的面积来识别太阳(因为它可以唯一地识别它,因此在图像上不会发生很大的变化)。更复杂的方法可以计算图像时刻,例如,胡子的时刻。请参阅this page了解这些功能。

使用您选择的分类算法对找到的对象进行实际分类。最简单的方法是手动指定阈值,值范围最终适用于所有(大部分)对象/图像组合。

您可以计算从原始时刻的实际位置,for the circular sun the position is equal to the center of mass

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

边缘MAP方法

另一种选择是边缘图的圆霍夫变换,这将有望回归一些候选圆圈(按位置和半径)。您可以根据您期望的半径选择太阳圆(如果幸运的话最多只有一个)。

+0

我认为与图像时刻它不会工作。如果屏幕上只有太阳 - 比太阳的中心是'Centroid'点。但是如果地球需要一些屏幕的一部分(比如在图像#1的左上角),那么比这部分比太阳“更重”,质心将会移动。 我试过CircleHough,它不适用于我的所有示例照片... –

+0

我更新了我的问题 - 已添加示例 –

2

对代码的简单添加是根据对象的大小过滤掉对象。如果您总是期望地球比太阳大得多,或者太阳在每张照片中的面积几乎相同,则可以按面积进行过滤。

尝试Blob detector为此任务。

请注意,应用形态开启/关闭而不是简单侵蚀或扩张可能会很好,所以在加工前后,您的太阳将具有几乎相同的面积。

+0

thanx,我认为这将是有用的,但我的openCv构建没有blob检测器,我是新手在C + +(我将无法编译最新版本) –

+0

从sourceforge取得最新的OpenCV http://sourceforge.net/projects/opencvlibrary/并使用它与增量运算符一样简单:)它已经被编译。而且..你添加使用命名空间简历?你怎么没有斑点探测器? – Sam