Reputation: 4718
I am using code based off of this example and wonder if there is any way to find out how 'good' the ellipse fit is. I have some ellipses which only very generally fit my data and I want to get rid of them while some of the ellipses are almost perfect.
I'd like to keep on the very good fits and get rid of the poor fits. How can I do this in opencv
?
Upvotes: 4
Views: 1885
Reputation: 41765
There are several method you can find in literature, for example:
check Dilip K. Prasad, Maylor K.H. Leung and Siu-Yeung Cho, “Edge curvature and convexity based ellipse detection method,” Pattern Recognition, 2012. at Section 4.2
check Fornaciari, Michele, Andrea Prati, and Rita Cucchiara. "A fast and effective ellipse detector for embedded vision applications." Pattern Recognition 47.11 (2014): 3693-3708. at Section 3.3.1
However, a very simple method can be the number of pixel that belong both to the contour and the ellipse. You can compute this, for example, drawing the contour and the ellipse on two separate black-initialized images, and counting the number of intersections, i.e. the number of white pixel of the logic AND of the two images.
To be more robust, you can draw both the contour and the ellipse with a line width of 2. This will account for slightly misaligned estimations, but still perceptually correct.
For example, given this input image:
You can see that good ellipses are toward green color, while bad results are toward red color:
Code:
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
// Load image
Mat3b img = imread("path_to_image");
// Convert to grayscale. Binarize if needed
Mat1b bin;
cvtColor(img, bin, COLOR_BGR2GRAY);
// Find contours
vector<vector<Point>> contours;
findContours(bin.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
// For each contour
for (int i = 0; i < contours.size(); ++i)
{
// Find ellipse
RotatedRect ell = fitEllipse(contours[i]);
// Draw contour
Mat1b maskContour(img.rows, img.cols, uchar(0));
drawContours(maskContour, contours, i, Scalar(255), 2);
// Draw ellips
Mat1b maskEllipse(img.rows, img.cols, uchar(0));
ellipse(maskEllipse, ell, Scalar(255), 2);
// Intersect
Mat1b intersection = maskContour & maskEllipse;
// Count amount of intersection
float cnz = countNonZero(intersection);
// Count number of pixels in the drawn contour
float n = countNonZero(maskContour);
// Compute your measure
float measure = cnz / n;
// Draw, color coded: good -> gree, bad -> red
ellipse(img, ell, Scalar(0, measure*255, 255 - measure*255), 3);
}
imshow("Result", img);
waitKey();
return 0;
}
Upvotes: 5