Ask Your Question

fill contour with drawContours

asked 2013-09-29 21:48:10 -0500

nakano gravatar image


I have a question concerning the drawContours function.

I've searched on the internet and on the openCV forum but without any success.

What I'm looking for is when I have a square contour, fill the inside of this contour using a specific color.

So far when I draw the contour, the border is red and the inside is filled with white :

cv::drawContours(targetMat, contours, maxAreaIdx, cv::Scalar(255,0,0),CV_FILLED);

What can I do for filling the inside with a specific color (if possible using RGBA)?

I've tried using cvRectangle function but I don't know how to convert a cv::Mat to CVArr (I'm not sure this function will help btw).

I really thank you for your help

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted

answered 2013-09-30 01:25:03 -0500

Michael Burdinov gravatar image

updated 2013-09-30 02:54:00 -0500

First, don't use functions starting with cvSomething. Those functions belong to C interface of OpenCV 1.0 and will be deprecated in future (maybe even near future). Use C++ interface of those functions. In your case it will be:

rectangle(targetMat, yourRect, Scalar(255,0,0), CV_FILLED);

Second, it is weird that you are getting red or white colors. I checked the function and got blue rectangle, as it is supposed to be (don't forget that OpenCV works with BGR color scheme so Scalar(255,0,0) means blue color). Are there any other draw functions you apply to the same image?

Edit (to answer the comments):

I afraid there some sort of problem with almost every line of your code. Lets discuss them one by one:

  1. Are you completely sure that you really have/need alpha channel? Working with 3 channels (RGB) is more common.

  2. You are using Canny edge detection with equal lower and higher thresholds. It will work but this is sort of waste of capabilities of Canny.

  3. Output of Canny is binary image. Value 255 for edges and value 0 for non-edges. Applying Gaussian smoothing is legal (you can apply it to any image) but it is not "correct". Maybe you want to apply smoothing prior to edge detection, are you? findContours that you use after smoothing treats every non-zero pixel as edge so the effect of Gaussian smoothing in this case is dilation of polygons. If dilation was indeed your intention you should use dilate function instead.

  4. Are you sure that one of the contours you extracted by findContours is whole rectangle? Consider for example that one of the pixels along the edge of rectangle wasn't considered "edge" by Canny because its gradient was too low, i.e. edges are not continuous. Than the object that will be found by findContours will be thin long "snake" along the edge of rectangle. If you will try to draw it by drawContours, it will draw thin red object along the boundary of rectangle. I guess this may be the source of your problem. If yes, you may consider using convexHull function on output of findContours.

  5. You don't need to copy contours to other vectors (temp_contour) in order to find their area. Just run over original vector:

    for(int i=0; i < contours.size(); i++) if (contourArea(contour) > maxArea) // do something

  6. You are trying to draw on image that is not empty to begin with (it is copy of original image). Instead allocate clean image (of appropriate size and type of course) and draw the polygon on it. This will let you see where the problem lies.

edit flag offensive delete link more


thank you for your reply. I don't think I can use the rectangle function due to the perspective of my rectangle, I get the contour of my image using findContours function. Maybe I did something wrong for filling what is inside the contour:

cv::cvtColor(imgSource, imgSource, CV_BGRA2GRAY);

cv::Canny(imgSource, imgSource, 50, 50);

cv::GaussianBlur(imgSource, imgSource, cv::Size(5,5), 5);

std::vector<std::vector<cv::Point> > contours;

cv::findContours(imgSource, contours, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);

double maxArea = -1;int maxAreaIdx = -1;

std::vector<cv::Point> temp_contour = contours[0];//the largest is at the index 0 for starting point

//get largest contour [...]

cv::drawContours(targetMat, contours, maxAreaIdx, cv::Scalar(255,0,0),CV_FILLED);

nakano gravatar imagenakano ( 2013-09-30 01:37:29 -0500 )edit

I didn't had enough space for writing all I wanted so I continue here :) imgSource and targetMat are both a copy of the original Mat from the ProcessImage (called by video camera manager) Here is the code for copying the original image (my trouble came from here?) cv::Mat targetMat;

cv::cvtColor(originalMat, targetMat, CV_BGRA2RGBA);

cv::Mat imgSource;

cv::cvtColor(originalMat, imgSource, CV_BGRA2RGBA);

I'm using imgSource for getting contours and I display the result in the targetMat

I've tried using rectangle function this morning but due to the image perspective, my rectangle doesn't fill the image contour.

Could you please tell me what I did wrong? PS: just before displaying the Mat image i've inverted color using cv::cvtColor(result, image, CV_BGRA2RGBA);

nakano gravatar imagenakano ( 2013-09-30 01:45:46 -0500 )edit

I really thank you for your comment. I think openCV is really useful and powerful but to be honest I don't really understand how to use it properly :S so far I've almost always took function/ part of source code for other which did the same I'm trying to do so I guess the more I use function of other people the more my source code is not "clean".

In fact what I'm trying to do is: I have a reference image I have to detect when the user is using the camera. the function I'm trying to do is to display a red rectangle with an alpha (in order for the user to be able to see what there is in the rectangle) when a rectangle is detected. Once I have a match between my reference image and the image on the camera, I ...(more)

nakano gravatar imagenakano ( 2013-09-30 03:12:13 -0500 )edit

if It doesn't bother you, could you please show me/explain me how to do it properly? I don't really understand what are the step for detecting properly a rectangle and fill its contents with a specific color ;(

nakano gravatar imagenakano ( 2013-09-30 03:15:27 -0500 )edit

Drawing object in image is pretty trivial (just applying existing functions), but detection of object may be very difficult problem. Solutions of this problem vary greatly in different applications. I recommend you to post new question about detection of object, with complete explanation of prior knowledge the algorithm can rely on and some images as example.

Michael Burdinov gravatar imageMichael Burdinov ( 2013-09-30 05:10:02 -0500 )edit

Question Tools


Asked: 2013-09-29 21:48:10 -0500

Seen: 27,104 times

Last updated: Sep 30 '13