如何使用OpenCV识别夜空照片中的星星?

3

我希望能编写一个程序,在夜空照片中识别出星星并加以标记。因为我对数字信号处理还不是很了解,所以想问一下如何实现这个想法。我已经勾画了一份代码草稿:

#include "main.hpp"

using namespace std;
//using namespace cv;

int main(int argc, char *argv[])
{
    const char *imageName = (argc >= 2) ?   argv[1] : "4.jpg";
    int64_t processTime;
    cv::Mat imageSource, result1, result2, grayScaledImage;

    /// Create and initialize the kerenel matrix
    cv::Mat kernelMatrix = (cv::Mat_<char>(3, 3) << 0, -1, 0,
                                                -1, 5, -1,
                                                0, -1, 0);

    cout << "Start..." << endl;

    if ((argc == 3) && !(strcmp("G", argv[2])))     imageSource = cv::imread(cv::samples::findFile(imageName), cv::IMREAD_GRAYSCALE);
    else                                            imageSource = cv::imread(cv::samples::findFile(imageName), cv::IMREAD_COLOR);

    /// Check for errors while open
    if (imageSource.empty())
    {
        cerr << "Can't open image [" << imageName << "]" << endl;
        exit(EXIT_FAILURE);
    }

    processTime = cv::getTickCount();                                           /// Start timer
    //img_proc::sharpening(imageSource, result1);                                 /// Process image
    cv::cvtColor(imageSource, grayScaledImage, cv::COLOR_BGR2GRAY);
    cv::filter2D(grayScaledImage, result1, imageSource.depth(), kernelMatrix);      /// Process image
    processTime = (cv::getTickCount() - processTime) / cv::getTickFrequency();  /// Stop timer and fix the process time

    /// Create windows for pictures
    cv::namedWindow("Source image", cv::WINDOW_AUTOSIZE);
    cv::namedWindow("Result image (1)", cv::WINDOW_AUTOSIZE);
    /// Show images
    cv::imshow("Source image", imageSource);
    cv::imshow("Result image (1)", result1);
    cv::waitKey(0);

    /// The second method
    processTime = cv::getTickCount();                                           /// Start timer
    cv::Sobel(result1, result2, CV_32F, 1, 0);                                  /// S
    processTime = (cv::getTickCount() - processTime) / cv::getTickFrequency();  /// Stop timer and fix the process time

    cv::namedWindow("Result image (2)", cv::WINDOW_AUTOSIZE);
    cv::imshow("Result image (2)", result2);
    cv::waitKey();

    double minVal, maxVal;
    cv::Mat newMat;
    cv::minMaxLoc(result2, &minVal, &maxVal);
    result2.convertTo(newMat, CV_8U, (255.0 / (maxVal - minVal)), (-minVal * 255.0 / (maxVal - minVal)));

    cv::namedWindow("newmat", cv::WINDOW_AUTOSIZE);
    cv::imshow("newmat", newMat);
    cv::waitKey();


    return 0;
}

因此,我得到了以下图像(左边是初始图像,右边是最终图像):result images 但是,例如,我想在灰度图像上用黄色圆圈突出显示星星。 我应该如何做?

2
你为什么特别选择了这两个滤镜?你希望从中得到什么?我建议在输入图像上尝试一个简单的局部最大值搜索。 - Nico Schertler
Nico Schertler,我使用了filter2D函数来锐化图像,然后尝试使用一些标记星星的东西。但在我看来,接下来的两个滤波器(sobel、minMaxloc)对于这个任务并不需要。 - Ruslan
你尝试过局部最大值搜索吗? - Nico Schertler
还有一种叫做H-maxima的方法。局部极大值可能会给出一些误报,但是对于星星来说,这并不会带来太多痛苦。skimage网站上有很好的文档。此外,如果您是图像处理新手,我建议您选择使用python + scikit-imageopencv文档相当令人失望。 - Piotr Rarus
1个回答

2
这里是一个MATLAB解决方案:
I = imread('Stars.jpg'); %Read image from file
I = I(:, 1:floor(size(I,2)/2-40), :); %Crop the relevant part (left side).
J = rgb2gray(I); %Convert RGB to Grayscale.
BW = imbinarize(I); %Convert to binary image (you have the option to manually select the threshold).
BW2 = bwmorph(BW2, 'shrink', Inf); %Shrink clusters until single pixel is left.

%The shrink operation wasn't good enough, fill hols, and shrink again.
BW3 = bwfill(BW2, 'holes');
BW4 = bwmorph(BW3, 'shrink', Inf);

%Find coordinates where pixel value is 1
[Y, X] =  find(BW4);

%Mark each coordinate with yellow circle.
K = insertMarker(I, [X Y], 'o', 'size', 5, 'color', 'yellow');
figure;imshow(K); %Display result.

很抱歉使用MATLAB,但是如果使用OpenCV将需要100个小时...

结果:
enter image description here

MATLAB有深入的文档,您可以通过谷歌搜索了解每个操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接