17

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

4

5 回答 5

8

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

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;
}
于 2014-02-24T17:58:48.107 回答
4

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

但这只会给你关键点。您可以将其用作初始搜索以查找所需的 blob,然后可能使用 findContours 算法围绕最可能的 blob。

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

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

于 2013-05-25T21:16:03.777 回答
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);
于 2013-06-01T20:39:23.567 回答
1

由于没有人发布完整的 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()
于 2020-01-31T03:35:31.093 回答
0

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;
}
于 2014-09-15T16:47:08.793 回答