Ask Your Question
0

Why a contour can't always be drawn filled?

asked 2016-02-02 14:34:53 -0600

PlapPlop gravatar image

updated 2016-02-03 10:25:00 -0600

Hello,

Sometimes when I find the contours of an image, I ask for it to be drawn with CV_FILLED, sometimes (most of the time), it doesn't fill properly the contour, but sometimes it does, why can explain this and how could I make sure it is filled everytime? In blue I plotted the first and the last Points of the contour.

Many thanks

Heberger image

Heberger image

Edit:

A minimal code would be the following:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;

int main(int argc, char** argv)
{
    int lowThreshold = 50;
    int max_lowThreshold = 100;
    int ratio = 3;
    int kernel_size = 3;
    Mat src1 = imread("/path/to/img1.jpg");
    Mat src2 = imread("/path/to/img2.jpg");
    Mat src_gray1;
    Mat src_gray2;
    cvtColor(src1, src_gray1, CV_BGR2GRAY);
    cvtColor(src2, src_gray2, CV_BGR2GRAY);
    Mat edge1;
    Mat edge2;
    Mat dst1;
    Mat dst2;
    Mat detected_edges1;
    Mat detected_edges2;
    std::vector<std::vector<Point> > contours1, contours2;
    std::vector<Vec4i> hierarchy1, hierarchy2;
    edge1.create(src1.size(), src1.type());
    edge2.create(src2.size(), src2.type());
    dst1.create(src1.size(), src1.type());
    dst2.create(src2.size(), src2.type());
    blur(src_gray1, detected_edges1, Size(3,3));
    blur(src_gray2, detected_edges2, Size(3,3));
    Canny(detected_edges1, detected_edges1, lowThreshold, lowThreshold * ratio, kernel_size);
    Canny(detected_edges2, detected_edges2, lowThreshold, lowThreshold * ratio, kernel_size);
    findContours(detected_edges1, contours1, hierarchy1, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
    findContours(detected_edges2, contours2, hierarchy2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
    drawContours(edge1, contours1, 0, Scalar(0, 0, 255), CV_FILLED, 8, hierarchy1);
    drawContours(edge2, contours2, 0, Scalar(0, 0, 255), CV_FILLED, 8, hierarchy2);
    imwrite("result1.jpg", edge1);
    imwrite("result2.jpg", edge2);
    return 0;
}

where the files "img1.jpg" and "img2.jpg" can be downloaded from here: http://hpics.li/ecb8b7a http://hpics.li/f1672f0

edit retag flag offensive close merge delete

Comments

Could it be because the contour is not always surrounding the area, but its contour?

thdrksdfthmn gravatar imagethdrksdfthmn ( 2016-02-03 03:42:29 -0600 )edit

Thanks for the reply. Actually, I'm not sure I understand what you suggested. I don't really know how drawContours works internally.

PlapPlop gravatar imagePlapPlop ( 2016-02-03 03:46:00 -0600 )edit

What I try to say s that in your firs image, the contour is just around the red area, that is your contour is just around a region that is a contour, like a gradient, so the white is just a line around the object, while in the second one the contour is around the whole object

thdrksdfthmn gravatar imagethdrksdfthmn ( 2016-02-03 04:32:09 -0600 )edit
1

could you show a real example image and your code.

sturkmen gravatar imagesturkmen ( 2016-02-03 06:54:57 -0600 )edit

I edited the question with more details. I should have done that earlier, thanks for the suggestion.

PlapPlop gravatar imagePlapPlop ( 2016-02-03 10:25:46 -0600 )edit
1

The reason of failure is due to the fact that there is no closed contour of the object and thus the edge gets a closed loop around the edge itself from inside to outside. You should have a closed blob for the contours to work like you are expecting. This behaviour is perfectly normal.

StevenPuttemans gravatar imageStevenPuttemans ( 2016-02-04 05:01:16 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
2

answered 2016-02-03 11:26:54 -0600

you should use cv::threshold instead of cv::Canny

take a look at my update on your code

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;

int main(int argc, char** argv)
{
    int lowThreshold = 40;
    int max_lowThreshold = 255;

    Mat src1 = imread("img1.jpg");
    Mat src2 = imread("img2.jpg");
    Mat src_gray1;
    Mat src_gray2;
    cvtColor(src1, src_gray1, CV_BGR2GRAY);
    cvtColor(src2, src_gray2, CV_BGR2GRAY);
    Mat edge1;
    Mat edge2;
    Mat dst1;
    Mat dst2;
    Mat detected_edges1;
    Mat detected_edges2;
    std::vector<std::vector<Point> > contours1, contours2;
    std::vector<Vec4i> hierarchy1, hierarchy2;
    edge1.create(src1.size(), src1.type());
    edge2.create(src2.size(), src2.type());
    dst1.create(src1.size(), src1.type());
    dst2.create(src2.size(), src2.type());
    blur(src_gray1, detected_edges1, Size(3,3));
    blur(src_gray2, detected_edges2, Size(3,3));

    threshold(detected_edges1, detected_edges1, lowThreshold, lowThreshold, THRESH_BINARY );
    threshold(detected_edges2, detected_edges2, lowThreshold, lowThreshold, THRESH_BINARY );

    findContours(detected_edges1, contours1, hierarchy1, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
    findContours(detected_edges2, contours2, hierarchy2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
    drawContours(edge1, contours1, 0, Scalar(0, 0, 255), CV_FILLED);
    drawContours(edge2, contours2, 0, Scalar(0, 0, 255), CV_FILLED);
    imwrite("result1.jpg", edge1);
    imwrite("result2.jpg", edge2);
    return 0;
}
edit flag offensive delete link more

Comments

Forgot to reply but I tested it and it worked great, thanks a lot.

PlapPlop gravatar imagePlapPlop ( 2016-02-04 08:07:00 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-02-02 14:34:53 -0600

Seen: 1,319 times

Last updated: Feb 03 '16