Ask Your Question
1

How to remove the small blobs?

asked 2017-03-05 22:34:23 -0600

hoang anh tuan gravatar image

updated 2020-10-10 22:06:01 -0600

I want to erase the small white spots areas to keep the largest area (white colour) in the picture:

Before

Before

I used findContours and found the largest area then used drawContours. I got the following result:

After

My code

findContours(image, vtContours, vtHierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

for (int i = 0; i < vtContours.size(); i++)
{
    double area = contourArea(vtContours[i]);

    if (area <= 100) {
        continue;
    }

    // Get only one
    if (area > dMaxArea)
    {
        dMaxArea = area;
        nSavedContour = i;
    }

}

if (nSavedContour == -1)
{
    return false;
}

image = Scalar::all(0);
drawContours(image, vtContours, nSavedContour, Scalar(255), CV_FILLED, 8);

Can you show me the other idea or my fault? Thank for supporting!

edit retag flag offensive close merge delete

3 answers

Sort by ยป oldest newest most voted
1

answered 2017-03-05 23:30:01 -0600

LBerger gravatar image

updated 2017-03-06 03:27:38 -0600

You can use morphological operators like erode dilate or closing opening.

If you want to draw hole in your surface you have to use RETR_TREE instead of CV_RETR_EXTERNAL in findContours

About hierarchy : Original image is :

image description

Contours with hierarchy are

0 = [-1, -1, 1, -1] // contour 0 :-1 no next contour,-1  no previous contour, 1 contour #1 is a child, -1 no parent contour  
1 = [3, -1, 2, 0]  // contour 1 :-3 next contour,-1  no previous contour, 1 contour #2 is a child, 0 is parent contour  
2 = [-1, -1, -1, 1]
3 = [-1, 1, -1, 0]

image description

program is :

Mat img = imread("C:/Users/Laurent.PC-LAURENT-VISI/Desktop/14887743804853655.jpg", CV_LOAD_IMAGE_GRAYSCALE);
imshow("original", img);
Mat y;
threshold(img, y, 50, 255, THRESH_BINARY);
imshow("threshold", y);
double ccMin, ccMax;
findContours(y, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
Mat c = Mat::zeros(img.size(), CV_8U);
for (int i = 0; i <contours.size(); i++)
{
    cout<<i<<" = "<<hierarchy[i]<<"\n";
}
for (int i = 0; i <contours.size(); i++)
{
    drawContours(c, contours, i, Scalar(255), 1, LINE_8, hierarchy, 0);
    putText(c,format("%d",i),contours[i][0], FONT_HERSHEY_SIMPLEX,0.5,Scalar(255));
}
imshow("ctr",c);
imwrite("c.png",c);
waitKey(0);
edit flag offensive delete link more

Comments

Thank for supporting. I used morphological operators. But I want to use based on findContours. After change RETR_TREE instead of CV_RETR_EXTERNAL, what do I need to do? Tks!

hoang anh tuan gravatar imagehoang anh tuan ( 2017-03-06 00:08:24 -0600 )edit
1

answered 2017-03-06 04:46:55 -0600

I think."OPEN METHOD" can solove you problem. image description

     Mat src = imread("blob.jpg");
     Mat dst;
     Mat element = getStructuringElement(MORPH_ELLIPSE,Size(7,7));
     morphologyEx(src,dst,CV_MOP_OPEN,element);
     imshow("src",src);
     imshow("dst",dst);
     waitKey();
edit flag offensive delete link more
1

answered 2017-03-06 00:26:37 -0600

Brandon212 gravatar image

updated 2017-03-06 00:44:17 -0600

If the problem you're asking for help with is the contour being filled in, probably the easiest way to make it how you want is to use that filled in contour as a mask on your image:

Mat mask = Mat::zeros(image.size(), CV_8U);
Mat newImage;
drawContours(mask, vtContours, nSavedContour, Scalar(255), CV_FILLED, 8);
image.copyTo(newImage, mask);

Then you'll have the contour you want in newImage.

Also if you want the largest contour, it's probably easiest to just sort the vector of contours. This is the function I always use for that:

void sortContours(vector<vector<Point>>& contours)
{
    auto contourComparator = [](vector<Point> a, vector<Point> b) { return contourArea(a) > contourArea(b); };
    sort(contours.begin(), contours.end(), contourComparator);
}

Then the largest one will just be the first one in the vector, so it would just be this to make the mask:

sortContours(vtContours);
drawContours(mask, vtContours, 0, Scalar(255), CV_FILLED, 8);
edit flag offensive delete link more

Comments

My result image is lost the hole. Your answer is similar to my way.

hoang anh tuan gravatar imagehoang anh tuan ( 2017-03-06 00:33:43 -0600 )edit

The hole will still be there if you use the code I provided at the top of the post. Did you imshow newImage?

Brandon212 gravatar imageBrandon212 ( 2017-03-06 00:38:56 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2017-03-05 22:34:23 -0600

Seen: 16,686 times

Last updated: Mar 06 '17