OpenCV - 在二进制图像中找到最大斑点的边界框

Posted

技术标签:

【中文标题】OpenCV - 在二进制图像中找到最大斑点的边界框【英文标题】:OpenCV - find bounding box of largest blob in binary image 【发布时间】:2013-05-20 17:37:00 【问题描述】:

使用 OpenCV 在二值图像中找到最大 blob 的边界框的最有效方法是什么?不幸的是,OpenCV 没有专门的斑点检测功能。我应该只使用findContours() 并搜索列表中最大的吗?

【问题讨论】:

这取决于你想对 blob 做什么,但你的方法是有效的 :) 如果您说出您使用的语言,您可能会得到更具体的答案。 我刚刚阅读了一些关于此的内容。如果您已经有了二值图像,听起来使用 Suzuki 的方法 (findContours) 非常适合。您还可以逐步找到第一个白色像素,然后使用floodFill 找到该区域的其余部分,依此类推。但我不确定这会更快。 我只想找到blob的边界框。我正在使用适用于 android 的 OpenCV,但所有版本的 OpenCV 都具有几乎相同的功能。 【参考方案1】:

如果您想使用 OpenCV 库,请查看 OpenCVs SimpleBlobDetector。这是另一个堆栈溢出的小教程:How to use OpenCV SimpleBlobDetector

不过,这只会为您提供关键点。您可以将其用作初始搜索以找到所需的 blob,然后可能使用 findContours 算法围绕最可能的 blob。

此外,您对 blob 的了解越多,您可以提供参数来过滤掉您不想要的 blob。您可能想要测试 SimpleBlobDetector 的区域参数。可能可以根据图像区域的大小计算区域,然后如果算法未检测到任何斑点,则迭代地允许更小的斑点。

这里是主要 OpenCV 文档的链接:http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_feature_detectors.html#simpleblobdetector

【讨论】:

感谢您的链接,这看起来是 findContours 的不错替代品。不幸的是它不在 OpenCV4Android 中,所以我会坚持我原来的计划。【参考方案2】:

为了找到最大 blob 的边界框,我使用了findContours,然后是以下代码:

double maxArea = 0;
for (MatOfPoint contour : contours) 
    double area = Imgproc.contourArea(contour);
    if (area > maxArea) 
        maxArea = area;
        largestContour = contour;
    

Rect boundingRect = Imgproc.boundingRect(largestContour);

【讨论】:

如果轮廓内有一个洞,我们想要面积最大的斑点怎么办?【参考方案3】:

这里。它。是。 (仅供参考:尽量不要偷懒,弄清楚下面我的函数会发生什么。

cv::Mat findBiggestBlob(cv::Mat & matImage)
    int largest_area=0;
    int largest_contour_index=0;

    vector< vector<Point> > contours; // Vector for storing contour
    vector<Vec4i> hierarchy;

    findContours( matImage, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); // Find the contours in the image

    for( int i = 0; i< contours.size(); i++ ) // iterate through each contour. 
        double a=contourArea( contours[i],false);  //  Find the area of contour
        if(a>largest_area)
            largest_area=a;
            largest_contour_index=i;                //Store the index of largest contour
            //bounding_rect=boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
        
    

    drawContours( matImage, contours, largest_contour_index, Scalar(255), CV_FILLED, 8, hierarchy ); // Draw the largest contour using previously stored index.
    return matImage;

【讨论】:

这不是我自己的答案的重复吗? 不,我的答案是 C++,这是 OpenCV 的核心语言。正如我所说,这是为懒惰的人准备的。 @TimZaman 你能帮我处理一下drawContours()的java等价物吗【参考方案4】:

TimZaman,您的代码有错误,但我无法发表评论,所以我开始一个新的正确答案。 这是我基于 1" 和 TimZaman 的想法的解决方案:

Mat measure::findBiggestBlob(cv::Mat &src)
int largest_area=0;
int largest_contour_index=0;
Mat temp(src.rows,src.cols,CV_8UC1);
Mat dst(src.rows,src.cols,CV_8UC1,Scalar::all(0));
src.copyTo(temp);

vector<vector<Point>> contours; // storing contour
vector<Vec4i> hierarchy;

findContours( temp, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

for( int i = 0; i< contours.size(); i++ ) // iterate

    double a=contourArea( contours[i],false);  //Find the largest area of contour
    if(a>largest_area)
    
        largest_area=a;
        largest_contour_index=i;
    



drawContours( dst, contours,largest_contour_index, Scalar(255), CV_FILLED, 8, hierarchy ); 
// Draw the largest contour
return dst;

【讨论】:

【参考方案5】:

由于没有人发布完整的OpenCV解决方案,这里有一个使用阈值+轮廓区域过滤的简单方法


输入图像

以绿色突出显示的最大斑点/轮廓

import cv2

# Load image, grayscale, Gaussian blur, and Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Find contours and sort using contour area
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
for c in cnts:
    # Highlight largest contour
    cv2.drawContours(image, [c], -1, (36,255,12), 3)
    break

cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey()

【讨论】:

以上是关于OpenCV - 在二进制图像中找到最大斑点的边界框的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV中的斑点提取

从blob OpenCV侵蚀文本

如何在 C++ 中使用 OpenCV 4.2 计算二进制图像的周长

使用OpenCV(Python)找到具有最大封闭区域的轮廓

OpenCV blob(斑点)特征,SimpleBlobDetector

python使用opencv对图像添加(高斯/椒盐/泊松/斑点)噪声