Ask Your Question
0

How to eliminate small contours in a binary image?

asked 2016-12-28 21:55:53 -0500

hoang anh tuan gravatar image

updated 2016-12-28 21:58:18 -0500

I am currently working on image processing project. I am using Opencv 3.x.x with VC++.

My code:

Mat result;
vector<vector<Point> >contours;
vector<Vec4i>hierarchy;
int savedContour = -1;
double maxArea = 0.0;
// Find the largest contour
findContours(binarayImage, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point());
for (int i = 0; i< contours.size(); i++)
{
    double area = contourArea(contours[i]);
    if (area > maxArea)
    {
        maxArea = area;
        savedContour = i;
    }
}
// Create mask
drawContours(result, contours, savedContour, Scalar(255), CV_FILLED, 8);

The binary image which I obtained :

image description

The result/output image which I want to obtain :

image description

but when I applied the above code, the result was

image description

did not look like I expected.

Help me! Thank you!

P/s: I know this problem is caused by drawContours. But I have no way to fix it.

edit retag flag offensive close merge delete

Comments

Hi, take the biggest contour instead.

Akhilesh gravatar imageAkhilesh ( 2016-12-28 23:27:37 -0500 )edit

Yeah. I took the biggest contour. But when I used drawContours, it looked like the last picture

hoang anh tuan gravatar imagehoang anh tuan ( 2016-12-29 00:46:14 -0500 )edit

2 answers

Sort by ยป oldest newest most voted
4

answered 2016-12-29 05:33:23 -0500

berak gravatar image

you're almost there ! all it needs is to actually apply the mask from drawContours !

(bitwise_and it with your binary image)

Mat result;
vector<vector<Point> >contours;
vector<Vec4i>hierarchy;
int savedContour = -1;
double maxArea = 0.0;
// Find the largest contour
//
//// findContours will "eat" the input image, so clone the binary Mat, we need it later:
//
findContours(binarayImage.clone(), contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point());
for (int i = 0; i< contours.size(); i++)
{
    double area = contourArea(contours[i]);
    if (area > maxArea)
    {
        maxArea = area;
        savedContour = i;
    }
}
// Create mask
drawContours(result, contours, savedContour, Scalar(255), CV_FILLED, 8);

// apply the mask:
binarayImage &= result;
edit flag offensive delete link more
1

answered 2016-12-28 22:42:13 -0500

Tetragramm gravatar image

When you find contours, you only find the boundaries, and each boundary is a separate contour. So when you eliminate the small ones, you eliminate the small contours inside the large one. You either need to explicitly keep all contours that are inside the large one (use the hierarchy output variable), or use connected components instead.

Connected Components might be closer to what you want. It finds all the blobs of white pixels. You simply filter the ones that have too small an area, and it keeps both the inner and outer boundaries.

Which one is best depends on what exactly you're doing with them, but both should work.

edit flag offensive delete link more

Comments

Tks! I'll think...

hoang anh tuan gravatar imagehoang anh tuan ( 2016-12-29 00:48:12 -0500 )edit
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2016-12-28 21:55:53 -0500

Seen: 6,013 times

Last updated: Dec 29 '16