How to correctly increase the size of rectangle found with cv::findContours

﹥>﹥吖頭↗ 提交于 2021-01-21 11:21:22

问题


I have a function that uses cv::findContours to create rectangles around one or many detected objects which I then want to use to store a cropped image of each object. My problem is that cv::findContours draws its rectangle right around the object but since I also need parts of the background around the object I want to increase each rectangles size.

This could be easily done with something like rectangleVector[i] += cv::Size(10, 10). The problem with this though is that if the detected object is right on the corner of the image and I increase the rectangles size and then use the rectangle to crop an image of just the detected object the program will crash since the rectangle is not within the images area anymore.

I need to somehow check where the rectangle is and then only increase its size if the resulting rectangle will not be out of bounds.

Please find below my function.

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

        }

    }
}

As you can see I tried to implement a way to check the position of the rectangle and then increase its size accordingly. Unfortunately it doesn't do what I want and only leaves me with really small cropped images. Whats the correct way to achieve this?


回答1:


The following function is meant to enlarge a rect with a certain "padding", unless it's bigger than the Mat it came from. In that case it scales it smaller.

/*!
 * \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:


you can first just increase the rect. after that you can test for borders:

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

hope this helps

here are some more rectangle operators from 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)


来源:https://stackoverflow.com/questions/25310342/how-to-correctly-increase-the-size-of-rectangle-found-with-cvfindcontours

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!