如何使用 OpenCV 识别夜空照片中的星星?
Posted
技术标签:
【中文标题】如何使用 OpenCV 识别夜空照片中的星星?【英文标题】:How to recognize the stars in the photo of the night sky using OpenCV? 【发布时间】:2019-11-18 00:59:44 【问题描述】:我想编写一个程序来识别夜空照片中的星星并标记它们。我是 DSP 的新手,想问一下如何实现这一点。我草拟了一个代码草案:
#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;
因此,我得到以下图像(左侧 - 初始图像,右侧 - 最终图像):
但我想突出显示星星,例如,在灰度图像上用黄色圆圈。我该怎么做?
【问题讨论】:
为什么要专门应用这两个过滤器?你希望从他们那里得到什么?我会尝试对输入图像进行简单的局部最大值搜索。 Nico Schertler,我使用 filter2D 函数来锐化图像,然后尝试使用标记星星的东西。但在我看来,这个任务不需要接下来的两个过滤器(sobel、minMaxloc)。 你试过local maximum search吗? 还有一个叫做H-maxima
的方法。本地马克西可以给你一些误报,但当谈到明星时,它不会那么痛苦。 skimage 网站上有很好的文档。此外,如果您不熟悉图像处理,我建议您使用python
+ scikit-image
。 opencv
文档相当令人失望。
【参考方案1】:
这是一个 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 个小时...
结果:
MATLAB 有丰富的文档,因此您可以通过 Google 搜索了解每个操作。
【讨论】:
以上是关于如何使用 OpenCV 识别夜空照片中的星星?的主要内容,如果未能解决你的问题,请参考以下文章
基于OpenCV修复表格缺失的轮廓--如何识别和修复表格识别中的虚线