1

I'm trying to remove the noise in this image:

enter image description here

aiming to isolate the triangle.

Actually i have a lot of picture like that (triangle with some noise) and i don't know how can i remove noise. I want to have a great triangle without noise in order to process it (detect interest points).

I have tried erode and all theses stuff but without success. Do you have an idea about how i can improve this result?

karlphillip
  • 92,053
  • 36
  • 243
  • 426
lilouch
  • 1,054
  • 4
  • 23
  • 43
  • Since there is no real difference between "wanted" and "noisy" elements a generic processing step will not succeed, whatever you try. You will have to implement some specific filter that detects if an element is "triangular like" or not, I am afraid... – arkascha Apr 02 '14 at 20:59
  • Thank you,I'm actually a beginner in openCV. So they don't have any method...How can i detect triangle with this sort of picture..it seems to me a bit hard. – lilouch Apr 02 '14 at 21:01
  • This is not a limitation of opencv, it is a general problem: the task you ask is not solvable using generic algorithms whatever graphics toolkit you use. Implementing a filter certainly is not straight forward for someone with little experience in image processing. – arkascha Apr 02 '14 at 21:03
  • Okey,so i have to find how can i could do that...Thank you – lilouch Apr 02 '14 at 21:05

1 Answers1

2

Eroding with subsequent dilation will distort the shape of your triangles. You can use connected components (CC) or even better a floodFill and remove (fill with zeros) based on the area (floodFill outputs the area of every CC it finds). Of course if you are sure that what you want to preserve is always triangles you can add an extra step to verify a triangular shape before erasing noise. The code below finds the largest segment and outlines its contour in red. Verification of triangle shape is indicated by green circles and can be further explored by a looking at a polygonal approximation in approx vector.

vector<vector<Point> > contours;
Mat hierarchy, I Icol; 
Icol = imread("triang.png");
cvtColor(Icol, I, CV_BGR2GRAY);

// Find connected components (CC)
findContours(I.clone(), contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

// Select the largest CC 
int ncontours = contours.size();
int max_sz = 0, max_idx;
for (int i=0; i<ncontours; i++) {
    int sz = contours[i].size();
    if (max_sz<sz) {
        max_sz = sz;
        max_idx = i;
    }
}
for (int i=0; i<max_sz; i++) {
    Point pt = contours[max_idx][i];
    Icol.at<Vec3b>(pt.y, pt.x) = Vec3b(0, 0, 255);
}

// Verify triangle
vector<Point> approx;
approxPolyDP(contours[max_idx], approx, 10, true);
cout<<Mat(approx)<<endl;
for (int i=0; i<approx.size(); i++) {
    Point pt = approx[i];
    circle(Icol, pt, 3, Scalar(0, 255, 0), 2);
}
imshow("largest", Icol); imwrite("triangle.png", Icol);
waitKey(-1);

enter image description here

Vlad
  • 4,425
  • 1
  • 30
  • 39
  • Thank you for this solution ! I didn't know that i could do it in this way... In order to know if i got it well,you're trying to find in the picture the contour and on this contour the biggest line (in order to éeliminate" the noise) and after you verify if it's a triangle (i have to check the method because i don't know how the method AproxPolyDp can detect a triangle..) – lilouch Apr 03 '14 at 17:46
  • Yes, you got it. ApproxPolyDp detects a simple polygon approximation of the contour but, of course, when you see that this polygon has only three vertices it can only be a triangle. So you can just count vertices of the polygon in the returned vector. Please, note, that while your contour is not exactly a triangle, ApproxPolyDp uses a tolerance parameter to fit a simpler polygon up to this tolerance. If you set the tolerance too low you may get more a complex polygon than a triangle. I experimentally found that tolerance=10 works well for your image. There are many other solutions, of course. – Vlad Apr 03 '14 at 18:42