0

I want to draw Rect around detected canny edges. I have this image which is result of eye detection, morphological operations and canny edge.

enter image description here

I tried using contours to bound it by rect but result was not accurate.

How can I get some thing like this image?

required image result

I'm using this function to draw contours:

void find_contour(Mat image)
{
    Mat src_mat, gray_mat, canny_mat;
    Mat contour_mat;
    Mat bounding_mat;

    contour_mat = image.clone();
    bounding_mat = image.clone();

    cvtColor(image, gray_mat, CV_GRAY2BGR);

    // apply canny edge detection

    Canny(gray_mat, canny_mat, 30, 128, 3, false);

    //3. Find & process the contours
    //3.1 find contours on the edge image.

    vector< vector< cv::Point> > contours;
    findContours(canny_mat, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

    //3.2 draw contours & property value on the source image.

    int largest_area = 0;
    int largest_contour_index = 0;
    Rect bounding_rect;

    for (size_t i = 0; i< contours.size(); i++) // iterate through each contour.
    {
        double area = contourArea(contours[i]);  //  Find the area of contour

        if (area > largest_area)
        {
            largest_area = area;
            largest_contour_index = i;               //Store the index of largest contour
            bounding_rect = boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
        }
    }

    drawContours(image, contours, largest_contour_index, Scalar(0, 255, 0), 2);

    imshow("Bounding ", image);
}
RAM
  • 2,257
  • 2
  • 19
  • 41
musta
  • 11
  • 3
  • 5
  • The bounding rect created by `boundingRect()` is "not accurate"? Is that right? If you want a smaller bound you can try `cv::minAreaRect()` for getting a `RotatedRect` that may be smaller. But your example is what you get if you plot the `bounding_rect` e.g. using `cv::line()`. Could you give the "not accurate" example and explain where the problem ist? – Kellerspeicher Jan 06 '16 at 11:28
  • This http://postimg.org/image/ursfkojs5/ is output of boundRect using contours , it is not drawing as I want in the image above – musta Jan 06 '16 at 11:34
  • use `cv::rectangle(image, bounding_rect, cv::Scalar(255,255,255));` before imshow. But this will only draw one (the biggest) contour's bounding box, so if you want ALL you'll have to use call that for each rect and not only for the biggest contour's one. – Micka Jan 06 '16 at 13:05
  • contour is a `vector >` so just put all points of all contours of one eye into a `vector` and `bounding_rect()`will make the box that can be plotted using `cv::rectangle()`. – Kellerspeicher Jan 06 '16 at 13:53

2 Answers2

1

in your code you aren't drawing the bounding rectangle at all. Try this:

void find_contour(Mat image)
{
Mat src_mat, gray_mat, canny_mat;
Mat contour_mat;
Mat bounding_mat;

contour_mat = image.clone();
bounding_mat = image.clone();

cvtColor(image, gray_mat, CV_GRAY2BGR);

// apply canny edge detection

Canny(gray_mat, canny_mat, 30, 128, 3, false);

//3. Find & process the contours
//3.1 find contours on the edge image.

vector< vector< cv::Point> > contours;
findContours(canny_mat, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

//3.2 draw contours & property value on the source image.

int largest_area = 0;
int largest_contour_index = 0;
Rect bounding_rect;

for (size_t i = 0; i< contours.size(); i++) // iterate through each contour.
{
    // draw rectangle around the contour:
    cv::Rect boundingBox = boundingRect(contours[i]);
    cv::rectangle(image, boundingBox, cv::Scalar(255,0,255)); // if you want read and "image" is color image, use cv::Scalar(0,0,255) instead

    // you aren't using the largest contour at all? no need to compute it...
    /*
    double area = contourArea(contours[i]);  //  Find the area of contour

    if (area > largest_area)
    {
        largest_area = area;
        largest_contour_index = i;               //Store the index of largest contour
        bounding_rect = boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
    }
    */
}

//drawContours(image, contours, largest_contour_index, Scalar(0, 255, 0), 2);

imshow("Bounding ", image);
}
Micka
  • 19,585
  • 4
  • 56
  • 74
  • HI @Micka thanks for help , this is the output still not accurate http://postimg.org/image/4odd9xjix/ there is may Rect around the eye area – musta Jan 06 '16 at 14:26
  • looks like your contours aren't so good? If it in fact is enough to just draw the biggest contour (if you only want to extract the biggest contour) are you able to draw it by adapting my code sample? – Micka Jan 06 '16 at 14:28
  • I have updated your code , but nothing changed the same result of many Rects around the area – musta Jan 06 '16 at 15:06
  • Can I use Blob for this ? – musta Jan 06 '16 at 21:11
0

You can do it like this also,

findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
vector<RotatedRect> minRect( contours.size() );

/// Draw contours
Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
     Scalar color = Scalar(255, 255, 255);
     cv::Rect boundingBox = cv::boundingRect(cv::Mat(contours[i]));
     minRect[i] = minAreaRect(Mat(contours[i]));
     drawContours( drawing, contours, i, color, 1, 8, hierarchy, 0, Point() );
}
for( int i = 0; i< contours.size(); i++ )
{
     // rotated rectangle
     Point2f rect_points[4]; minRect[i].points( rect_points );
     for( int j = 0; j < 4; j++ )
     line( drawing, rect_points[j], rect_points[(j+1)%4], Scalar(0,0,255), 1, 8 );
}
Sagar Patel
  • 864
  • 1
  • 11
  • 22