Ask Your Question
4

How to resize a contour?

asked 2014-10-16 10:28:16 -0600

thdrksdfthmn gravatar image

updated 2020-11-28 06:42:49 -0600

I have an application that detects an object by finding its contour. Because the image where I search for the object may be at a very big scale is affecting my detection because the contour can be too long and I skip the contours longer than a threshold. For fixing this, I have thought of resizing the image larger than a maximum size to that maw size. Doing so, I am detecting the object in the smaller image, and when drawing the contour on the initial image, I am getting a "wrong detection". Is there a possibility to resize the contour?

edit retag flag offensive close merge delete

Comments

Hmm afaik contours are actually for visualisation purposes and for creating masks. Resizing them will not be that easy. How about the following approach

  1. Use the contour to make a binary mask.
  2. Apply a resize operation on that binary mask, which is possible since it is a data matrix.
  3. Now use findContours again on that binary image to change it back to an active contour.

Would this suit your needs?

StevenPuttemans gravatar imageStevenPuttemans ( 2014-10-17 04:33:51 -0600 )edit
1

If I just do the (x, y) -> (resizer * x, resizer * y) is not correct? Actually I am trying to test this. (x and y are both positive)

thdrksdfthmn gravatar imagethdrksdfthmn ( 2014-10-17 05:02:20 -0600 )edit
1

That was my first tought. But I am not sure if this will actually work for each point. You should test and report back :)

StevenPuttemans gravatar imageStevenPuttemans ( 2014-10-17 05:48:25 -0600 )edit

Great! Yeah my approach suffers from artefacts ... hadn't thought on that...

StevenPuttemans gravatar imageStevenPuttemans ( 2014-10-17 08:36:22 -0600 )edit

2 answers

Sort by ยป oldest newest most voted
3

answered 2014-10-17 08:21:25 -0600

thdrksdfthmn gravatar image

updated 2015-10-05 14:06:23 -0600

Nice, it is working, and it is working very nice. More, your idea of resizing the mask is introducing errors, because the cv::fillPoly is introducing errors (small "stairs") and resizing it is just making the errors to appear in the new contour, and they are even bigger.

Sample code :

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"

using namespace cv;

int main( int argc, char** argv )
{
    vector<vector<Point> > contours;
    Mat img = Mat::zeros( 500, 500, CV_8UC1 );

    circle( img, Point(250,250), 100, Scalar(255) );

    findContours( img, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);

    fillConvexPoly( img, Mat( contours[0] ) / 2, Scalar(255)); // draws contour resized 1x/2

    polylines( img, Mat( contours[0] ) * 2, true, Scalar(255)); // draws contour resized 2x

    imshow("result",img);
    waitKey();

    return 0;
}

result image:

image description

edit flag offensive delete link more
5

answered 2018-04-13 10:06:26 -0600

updated 2018-08-30 19:24:08 -0600

You can use the following method to resize the contour by keeping the contour center like the morphology operation.

    void contourOffset(const std::vector<cv::Point>& src, std::vector<cv::Point>& dst, const cv::Point& offset) {
    dst.clear();
    dst.resize(src.size());
    for (int j = 0; j < src.size(); j++)
        dst[j] = src[j] + offset;

}
void scaleContour(const std::vector<cv::Point>& src, std::vector<cv::Point>& dst, float scale)
{
    cv::Rect rct = cv::boundingRect(src);

    std::vector<cv::Point> dc_contour;
    cv::Point rct_offset(-rct.tl().x, -rct.tl().y);
    contourOffset(src, dc_contour, rct_offset);

    std::vector<cv::Point> dc_contour_scale(dc_contour.size());

    for (int i = 0; i < dc_contour.size(); i++)
        dc_contour_scale[i] = dc_contour[i] * scale;

    cv::Rect rct_scale = cv::boundingRect(dc_contour_scale);

    cv::Point offset((rct.width - rct_scale.width) / 2, (rct.height - rct_scale.height) / 2);
    offset -= rct_offset;
    dst.clear();
    dst.resize(dc_contour_scale.size());
    for (int i = 0; i < dc_contour_scale.size(); i++)
        dst[i] = dc_contour_scale[i] + offset;
    }

void scaleContours(const std::vector<std::vector<cv::Point>>& src, std::vector<std::vector<cv::Point>>& dst, float scale)
{
    dst.clear();
    dst.resize(src.size());
    for (int i = 0; i < src.size(); i++)
        scaleContour(src[i], dst[i], scale);
}
        void main(){
            std::vector<std::vector<cv::Point>> src,dst;
            scaleContours(src,dst,0.95);
         }

In the sample below, the green contour is main contour and the red contour is scaled contour with a coefficient of 0.95. image description

edit flag offensive delete link more

Comments

1

nice to have you back here ;)

berak gravatar imageberak ( 2018-04-13 10:11:17 -0600 )edit

Is there an equivalent python code for this? If not would be very grateful if you could please explain the process on the code above.

fzuffer gravatar imagefzuffer ( 2018-06-09 03:07:26 -0600 )edit

i don't think, we have a python example,but the algorithm is:

  • find the center of the contour (moments() or getBoundingRect())
  • subtract it from each point in the contour
  • multiply contour points x,y by a scale factor
  • add the center again to each point
berak gravatar imageberak ( 2018-06-09 03:14:31 -0600 )edit
1

Thank You very much for the quick response.. Appreciate it a lot.

fzuffer gravatar imagefzuffer ( 2018-06-09 04:03:15 -0600 )edit

Question Tools

Stats

Asked: 2014-10-16 10:28:16 -0600

Seen: 21,426 times

Last updated: Dec 05 '18