如何正确增加使用 cv::findContours 找到的矩形的大小

Posted

技术标签:

【中文标题】如何正确增加使用 cv::findContours 找到的矩形的大小【英文标题】:How to correctly increase the size of rectangle found with cv::findContours 【发布时间】:2014-08-14 14:15:19 【问题描述】:

我有一个函数,它使用cv::findContours 在一个或多个检测到的对象周围创建矩形,然后我想用它来存储每个对象的裁剪图像。我的问题是cv::findContours 在对象周围绘制矩形,但由于我还需要对象周围的部分背景,所以我想增加每个矩形的大小。

这可以通过rectangleVector[i] += cv::Size(10, 10) 之类的方式轻松完成。但问题在于,如果检测到的对象正好在图像的一角,并且我增加了矩形大小,然后使用矩形裁剪检测到的对象的图像,程序将崩溃,因为矩形不在图像区域了。

我需要以某种方式检查矩形的位置,然后仅在生成的矩形不会超出范围时才增加其大小。

请在下面找到我的功能。

void ActualRec::objectDetection()
    Mat temp;
    thresholdedImage.copyTo(temp);
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    findContours( temp, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

    if (contours.size()<5)    
        vector<vector<Point>> contours_poly( contours.size() );
        vector<Rect> boundRect( contours.size() );
        for( int i = 0; i < contours.size(); i++ )
            approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
            boundRect[i] = boundingRect( Mat(contours_poly[i]) );
        


        for( int i = 0; i< contours.size(); i++ )
            //won't do the job..
            Point BRx = boundRect[i].br();
            Point TLy = boundRect[i].tl();
            if(BRx.x-10 > 0) BRx.x-=10;
            if(BRx.y-10 > 0) BRx.y-=10;
            if(TLy.x+10 < thresholdedImage.cols-1) TLy.x+=10;
            if(TLy.y+10 < thresholdedImage.rows-1) TLy.y+=10;
            Rect finalRect(BRx,TLy);

            //store cropped images            
            vecCropped.push_back(originalImage(finalRect));
            vecCroppedTresh.push_back(thresholdedImage(finalRect));

        

    

如您所见,我尝试实现一种方法来检查矩形的位置,然后相应地增加其大小。不幸的是,它没有做我想要的,只会给我留下非常小的裁剪图像。实现这一目标的正确方法是什么?

【问题讨论】:

【参考方案1】:

以下函数旨在使用特定的“填充”放大一个矩形,除非它比它来自的 Mat 大。在这种情况下,它会将其缩放得更小。

/*!
 * \brief Enlarge an ROI rectangle by a specific amount if possible 
 * \param frm The image the ROI will be set on
 * \param boundingBox The current boundingBox
 * \param padding The amount of padding around the boundingbox
 * \return The enlarged ROI as far as possible
 */
Rect enlargeROI(Mat frm, Rect boundingBox, int padding) 
    Rect returnRect = Rect(boundingBox.x - padding, boundingBox.y - padding, boundingBox.width + (padding * 2), boundingBox.height + (padding * 2));
    if (returnRect.x < 0)returnRect.x = 0;
    if (returnRect.y < 0)returnRect.y = 0;
    if (returnRect.x+returnRect.width >= frm.cols)returnRect.width = frm.cols-returnRect.x;
    if (returnRect.y+returnRect.height >= frm.rows)returnRect.height = frm.rows-returnRect.y;
    return returnRect;

【讨论】:

正是我想做的。谢谢!【参考方案2】:

你可以先增加矩形。 之后你可以测试边框:

// just increase your rect
cv::Rect yourIncreasedRect = ...;

// rect of the image borders
cv::Rect imageRect = cv::Rect(0,0,imageWidth,imageHeight);

// rect that contains all that is in BOTH rects:
cv::Rect fittingRect = yourIncreasedRect & imageRect;

希望对你有帮助

这里有更多来自http://docs.opencv.org/modules/core/doc/basic_structures.html#rect的矩形运算符

rect = rect +/- point (shifting a rectangle by a certain offset)
rect = rect +/- size (expanding or shrinking a rectangle by a certain amount)
rect += point, rect -= point, rect += size, rect -= size (augmenting operations)

rect = rect1 & rect2 (rectangle intersection)
rect = rect1 | rect2 (minimum area rectangle containing rect2 and rect3 )
rect &= rect1, rect |= rect1 (and the corresponding augmenting operations)

rect == rect1, rect != rect1 (rectangle comparison)

【讨论】:

这太棒了,我不知道! 我也不知道可以使用 & 运算符,谢谢!

以上是关于如何正确增加使用 cv::findContours 找到的矩形的大小的主要内容,如果未能解决你的问题,请参考以下文章

使用cv2.findContours函数传入参数的数据类型问题

OpenCV cv::findcontours *** 异常

调用 cv2.findContours 解包的值太多

【python】opencv库中cv2.findContours()和cv2.drawContours()函数

OpenCV-寻找轮廓cv::findContours&绘制轮廓cv::drawContours

OpenCV计算机图像处理 —— 凸性缺陷 + 点多边形测试 + 形状匹配 + 轮廓分层与cv.findContours()