C++ Opencv孔检测

C++ Opencv孔检测,c++,image,opencv,C++,Image,Opencv,我有一个图像,我想检测我的对象内的孔(使用它来计算每个孔的面积)。这是我使用opencv操作后的图像 问题是背景和孔的颜色相同 所以我不知道该怎么做才能把它们分开,也不知道该用什么算法来检测这些洞 cv::threshold(channel[1], channel[1], 190, 255, CV_THRESH_BINARY); cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); cv::mo

我有一个图像,我想检测我的对象内的孔(使用它来计算每个孔的面积)。这是我使用opencv操作后的图像

问题是背景和孔的颜色相同

所以我不知道该怎么做才能把它们分开,也不知道该用什么算法来检测这些洞

cv::threshold(channel[1], channel[1], 190, 255, CV_THRESH_BINARY);
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
cv::morphologyEx(channel[1], channel[1], cv::MORPH_OPEN, element);
cv::dilate(channel[1], channel[1], element);
cv::bitwise_not(channel[1], channel[1]);
cv::imwrite("green_after.bmp", channel[1]);

cv::Mat dist;
cv::distanceTransform(channel[1], dist, CV_DIST_L2, 3);
cv::imwrite("dist.bmp", dist);
cv::normalize(dist, dist, 0, 1., cv::NORM_MINMAX);
cv::imwrite("dist2.bmp", dist);
cv::threshold(dist, dist, .1, 1., cv::THRESH_BINARY);
cv::imwrite("dist3.bmp", dist);
cv::normalize(dist, dist, 0.0, 255.0, cv::NORM_MINMAX);
cv::imwrite("dist4.bmp", dist);

cv::Mat invSrc = cv::Scalar::all(255) - dist;
cv::imwrite("dist5.bmp", invSrc);

下一步该怎么做?

你可以做模板匹配——图像处理中互相关的一种应用——非常简单

如果您碰巧有上面图像的模板(即预期图像没有孔或任何间隙)。您可以执行Xcorrelation,即模板匹配,以确定是否存在任何孔。如果没有洞,你应该得到一个完美的匹配,否则没有匹配。正如@Hans在下面评论的那样,背景仍然是白色的——这使得它有点棘手

看看这个-

我可以考虑的解决方案之一是:

1) 从相同大小的全黑背景图像中减去图像,即白色图像的所有像素值应对应于所有白色


2) 看看这些指数。这些是实际图像中的孔。

第一步是二值化和反转。通过这些步骤,您将得到一个具有黑色背景、白色对象和黑洞的二值图像

接下来,我将为您提供使用参数CV_RETR_CCOMP(或CV_RETR_TREE)的findContour方法:

此方法使用CV_RETR_CCOMP参数查找所有白色对象的外部轮廓,并确定每个孔的内部轮廓。它检索所有轮廓并将其组织成两级层次结构。在顶层,有组件的外部边界。在第二层,有孔的边界。如果连接组件的孔内有另一个轮廓,它仍然放在顶层

如果在层次结构中有孔的轮廓,则可以通过矩计算、边界矩形计算等继续图像处理()

findContour方法的用法写在这个问题上:


谢谢您的回复。但问题是我没有一个没有空白的图像模板。事实上,你所说的模板是我想从我的图像中得到的,在我进行孔检测之前。检查更新的答案,看看我是否触及了正确的基础!第1点:如果你只是翻转颜色,你根本没有改善情况,因为洞和背景仍然有相同的颜色。@Hannesovren我正在尝试提出一些想法,如果你有更好的解决方案,那将是一件好事-同时我更新了我的答案,承认背景是一个困难的问题。“洞”的定义有点不清楚。在黑色的大斑点中有一些相当大的白色区域。这些是背景还是空洞?我会把它们看成是完整的,它需要完全自动地工作,或者你可以手动交互(点击图像)?