在精明边缘的结果周围绘制矩形

Posted

技术标签:

【中文标题】在精明边缘的结果周围绘制矩形【英文标题】:Draw Rect around result of canny edge 【发布时间】:2016-01-06 10:59:10 【问题描述】:

我想在检测到的精巧边缘周围绘制矩形。我有这张图像是眼睛检测、形态学操作和精明边缘的结果。

我尝试使用轮廓通过 rect 对其进行边界,但结果不准确。

我怎样才能得到类似这张图片的东西?

我正在使用这个函数来绘制轮廓:

void find_contour(Mat image)

    Mat src_mat, gray_mat, canny_mat;
    Mat contour_mat;
    Mat bounding_mat;

    contour_mat = image.clone();
    bounding_mat = image.clone();

    cvtColor(image, gray_mat, CV_GRAY2BGR);

    // apply canny edge detection

    Canny(gray_mat, canny_mat, 30, 128, 3, false);

    //3. Find & process the contours
    //3.1 find contours on the edge image.

    vector< vector< cv::Point> > contours;
    findContours(canny_mat, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

    //3.2 draw contours & property value on the source image.

    int largest_area = 0;
    int largest_contour_index = 0;
    Rect bounding_rect;

    for (size_t i = 0; i< contours.size(); i++) // iterate through each contour.
    
        double area = contourArea(contours[i]);  //  Find the area of contour

        if (area > largest_area)
        
            largest_area = area;
            largest_contour_index = i;               //Store the index of largest contour
            bounding_rect = boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
        
    

    drawContours(image, contours, largest_contour_index, Scalar(0, 255, 0), 2);

    imshow("Bounding ", image);

【问题讨论】:

boundingRect() 创建的边界矩形“不准确”?是对的吗?如果您想要更小的界限,您可以尝试cv::minAreaRect() 以获得可能更小的RotatedRect。但是,如果您绘制 bounding_rect 例如,您的示例就是您所得到的。使用cv::line()。你能举个“不准确”的例子并解释问题出在哪里吗? 这个 postimg.org/image/ursfkojs5 是 boundRect 使用轮廓的输出,它没有像我想要的那样在上图中绘制 在 imshow 之前使用 cv::rectangle(image, bounding_rect, cv::Scalar(255,255,255));。但这只会绘制一个(最大的)轮廓的边界框,所以如果你想要 ALL,你必须对每个矩形使用调用它,而不仅仅是最大的轮廓。 轮廓是vector&lt;vector&lt;Point&gt; &gt;,因此只需将一只眼睛的所有轮廓的所有点放入vector&lt;Point&gt;bounding_rect() 将生成可以使用cv::rectangle() 绘制的框。 【参考方案1】:

在您的代码中,您根本没有绘制边界矩形。试试这个:

void find_contour(Mat image)

Mat src_mat, gray_mat, canny_mat;
Mat contour_mat;
Mat bounding_mat;

contour_mat = image.clone();
bounding_mat = image.clone();

cvtColor(image, gray_mat, CV_GRAY2BGR);

// apply canny edge detection

Canny(gray_mat, canny_mat, 30, 128, 3, false);

//3. Find & process the contours
//3.1 find contours on the edge image.

vector< vector< cv::Point> > contours;
findContours(canny_mat, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

//3.2 draw contours & property value on the source image.

int largest_area = 0;
int largest_contour_index = 0;
Rect bounding_rect;

for (size_t i = 0; i< contours.size(); i++) // iterate through each contour.

    // draw rectangle around the contour:
    cv::Rect boundingBox = boundingRect(contours[i]);
    cv::rectangle(image, boundingBox, cv::Scalar(255,0,255)); // if you want read and "image" is color image, use cv::Scalar(0,0,255) instead

    // you aren't using the largest contour at all? no need to compute it...
    /*
    double area = contourArea(contours[i]);  //  Find the area of contour

    if (area > largest_area)
    
        largest_area = area;
        largest_contour_index = i;               //Store the index of largest contour
        bounding_rect = boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
    
    */


//drawContours(image, contours, largest_contour_index, Scalar(0, 255, 0), 2);

imshow("Bounding ", image);

【讨论】:

HI @Micka 感谢您的帮助,这是输出仍然不准确postimg.org/image/4odd9xjix 眼睛周围可能有矩形 看起来你的轮廓不太好?如果实际上仅绘制最大轮廓就足够了(如果您只想提取最大轮廓),您是否可以通过调整我的代码示例来绘制它? 我已经更新了您的代码,但没有改变该区域周围许多 Rects 的相同结果 我可以使用 Blob 吗?【参考方案2】:

你也可以这样做,

findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
vector<RotatedRect> minRect( contours.size() );

/// Draw contours
Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )

     Scalar color = Scalar(255, 255, 255);
     cv::Rect boundingBox = cv::boundingRect(cv::Mat(contours[i]));
     minRect[i] = minAreaRect(Mat(contours[i]));
     drawContours( drawing, contours, i, color, 1, 8, hierarchy, 0, Point() );

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

     // rotated rectangle
     Point2f rect_points[4]; minRect[i].points( rect_points );
     for( int j = 0; j < 4; j++ )
     line( drawing, rect_points[j], rect_points[(j+1)%4], Scalar(0,0,255), 1, 8 );

【讨论】:

以上是关于在精明边缘的结果周围绘制矩形的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV - 精明的边缘检测无法正常工作

如何在 R 树状图中正确着色边缘或绘制矩形?

OpenCV:Canny 边缘检测器获取 minEnclosureCircle

画一个圆的半径和点周围的边缘

使用xml android在雅虎摘要新闻应用程序中绘制倾斜的矩形上边缘形状

将标签绘制为带有边缘而不是圆角的矩形