问题 OpenCV - 在二进制图像中找到最大blob的边界框


使用OpenCV查找二进制图像中最大blob的边界框的最有效方法是什么?不幸的是,OpenCV没有特定的blob检测功能。我应该使用 findContours() 并搜索列表中最大的?


8739
2018-05-25 04:40


起源

这取决于你之后想要用blob做什么,但你的方法是有效的:) - Quentin Geissmann
如果您说出您正在使用的语言,您可能会得到更具体的答案。 - Geoff
我刚读了一下这个。如果您已有二进制图像,则听起来像使用铃木的方法(findContours)是一个非常合适的人选。你也可以逐步找到第一个白色像素,然后使用 floodFill 找到该地区的其余部分,等等。但我不确定会更快。 - Geoff
我只是想找到blob的边界框。我正在使用OpenCV for Android,但所有版本的OpenCV都具有相同的功能。 - 1''


答案:


如果要使用OpenCV库,请查看OpenCVs SimpleBlobDetector。这是另一个堆栈溢出,显示了它的一个小教程: 如何使用OpenCV SimpleBlobDetector

这只会给你关键点。你可以使用它作为初始搜索来找到你想要的blob,然后可能在最可能的blob周围使用findContours算法。

此外,您了解有关blob的更多信息,您可以提供参数来过滤掉您不想要的blob。您可能想要测试SimpleBlobDetector的区域参数。可能可以基于图像区域的大小计算面积,然后如果算法没有检测到任何斑点则迭代地允许更小的斑点。

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


3
2018-05-25 21:16



感谢您的链接,这看起来是一个很好的替代品 findContours。不幸的是,它不在OpenCV4Android中,所以我会坚持原来的计划。 - 1''


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

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;
}

6
2018-02-24 17:58



这不是我自己答案的重复吗? - 1''
不,我的答案是用C ++编写的,这是OpenCV的核心语言。正如我所说,这是懒惰的。 - TimZaman
@TimZaman你能帮助我使用java等效的drawContours()吗? - Prasanna Aarthi


为了找到最大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);

2
2018-06-01 20:39



如果该轮廓内有一个洞,我们想要最大面积的斑点怎么办? - Koray


可能最有效的方法是使用CvBlobsLib。 你可以在下载它    http://sourceforge.net/projects/cvblobslib/?source=dlp


0
2018-05-25 08:50



对不起,我宁愿不使用第三方库。 - 1''


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;
}

0
2017-09-15 16:47