Shiyu
Shiyu

Reputation: 455

How to remove false detections?

I am using OpenCV to detect ellipses in a binary image as shown below. In the image, there are eight ellipses to be detected. I can use findContours to obtain a lot of contours including the eight ellipses. The problem is: how can I judge and which one is ellipse which one is not? How to remove all the other false detections?

enter image description here enter image description here

Upvotes: 7

Views: 4353

Answers (4)

Throwback1986
Throwback1986

Reputation: 6005

Although another answer has been previously accepted, there are several options to be explored, so I'll add another answer. Assuming that a Hough method is fast enough for your application, here are some interesting alternatives:

  1. Ellipse detection with OpenCV
  2. http://toyhouse.cc/profiles/blogs/modified-hough-ellipse-transform-detecting-ellipse-in-an-accurate
  3. http://www.codeforge.com/article/131943
  4. And the paper I added in the comments above: http://www.bmva.org/bmvc/1988/avc-88-041.pdf

I might also add that Hough is likely to be the "right" way to proceed in reliably detecting ellipses, but you may run into additional challenges. You indicate that Hough circles is fast enough on your desktop, but how well does the performance of the desktop match that embedded system? Does the embedded system have a floating point unit? If not, don't be too alarmed by the performance exhibited by software-emulated floating point. You may still be able to implement the Hough algorithm satisfactorily using fixed-point math, lookup-tables, etc.

Upvotes: 1

Shiyu
Shiyu

Reputation: 455

Now I think I have successfully solve the problem using my own algo. Just post it for future reference.

As shown below, all the ellipses can be accurately located. And false detections are successfully removed. On the other hand, the algo is very time efficient: 0.03s for all image processing on my normal desktop. Image size: 448x336 pixel

Procedure of the algo:

  1. detect contours from the binary image using function findContours
  2. remove too small ones by setting a threshold of the minimum size of a contour
  3. detect ellipses using the function fitEllipse
  4. compare the contour with the corresponding ellipse. Specifically, substitute all the contour points into the general ellipse equation (see http://www.maa.org/joma/volume8/kalman/general.html). Then compute the algebraic error. If the error is smaller than a threshold, then exclude that contour.

enter image description here

EDIT: Comments on George Profenza and karlphillip's answers. Thank George Profenza and karlphillip for their answers. However, their answers can not solve the problem well. The first idea given by George Profenza is to set threshold for the size of the contours. In fact, I have used that in my algo. But obviously that is an preliminary step of the algo. There are many false detections of "good" size. The second idea of George Profenza is to use HoughCircles, which is also proposed by karlphillip. The problem of HoughCircles is: (a) it is slow, while I need to implement the algo in real time in embedded systems. (b) it can only detect circles but not ellipses. Of course, when the ellipse is close to a circle, it also works. But for general cases, it doesn't. Moreover, my method above cannot detect the "figure 8". It is a big problem and I am still working on it.

Upvotes: 1

karlphillip
karlphillip

Reputation: 93468

In this specific case, the Hough Circle Transform is probably the easiest solution.

Copy the code from the tutorial and change the parameters of cv::HoughCircles() to:

/// Apply the Hough Transform to find the circles
HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 1, 10, 40, 30, 0, 0 );

Output:

enter image description here

But I loved @George's idea, go with it, it's more robust than specifying hardcoded constants. My approach works great for this image, but if you have images with different sizes of circles and stuff, you want to use cv::minEnclosingCircle().

Upvotes: 8

George Profenza
George Profenza

Reputation: 51867

One option is a bit hacky: On top of findContours use minEnclosingCircle and filter contours by min. enclosing radius based on a threshold value (remove smaller than radius A (remove tiny blobs) and greater than radius B( remove huge blobs)). You can also try minAreaRect and check width/height ratio to look for uniform blobs rather than tall/wide ones.

The less hacky solution is to use Hough transforms. Have a look at the hough circle and the tutorial

Upvotes: 7

Related Questions