Problem when calculating the fitted ellipse
I need to extract contour of shapes in images, and get the fitted ellipse. However, when I use the following code, the result is not very satisfying.
#include "stdafx.h"
#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <fstream>
using namespace std;
using namespace cv;
extern void Threshold(Mat gray, Mat& binary);
extern void Not(Mat& im);
// Calculate the contour of connected region
// erease the image that is too large or too small
void getSizeContours(vector<vector<Point>> &contours)
{
int cmin = 10; // min contour length
int cmax = 10000; // max contour length
vector<vector<Point>>::const_iterator itc = contours.begin();
while(itc != contours.end())
{
if((itc->size()) < cmin || (itc->size()) > cmax)
{
itc = contours.erase(itc);
}
else ++ itc;
}
}
// Calculate min convex oval
void MinConvexOval(Mat gray, vector<vector<Point>> &contours, vector<Mat> oval_result)
{
Mat oval(gray.rows*3,gray.cols*3,CV_8UC3);
vector<vector<Point>>::const_iterator itc=contours.begin();
while(itc != contours.end())
{
double perimeter=arcLength(*itc,true);
double area= contourArea(*itc,false);
Rect rect=boundingRect(*itc);
CvBox2D box=minAreaRect(*itc);
Point pt1, pt2;
pt1.x=rect.x;
pt1.y=rect.y;
pt2.x=rect.x+rect.width;
pt2.y=rect.y+rect.height;
RotatedRect box2=fitEllipse(*itc);
ellipse(oval, box2, Scalar(255,0,255), 1, 8);
Point2f vertices[4];
box2.points(vertices);
for (int i = 0; i < 4; i++)
line(oval, vertices[i], vertices[(i+1)%4], Scalar(0,255,0));
++itc;
}
drawContours(oval,contours,-1, Scalar(0,255,255), 1);
imshow("oval",oval);
waitKey(0);
}
void cvText(Mat img, const char* text, int x, int y)
{
CvFont font;
double hscale = 1.0;
double vscale = 1.0;
int linewidth = 2;
cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX |CV_FONT_ITALIC,hscale,vscale,0,linewidth);
Scalar textColor =Scalar(0,255,255);
Point textPos =Point(x, y);
putText(img, text, textPos, CV_FONT_HERSHEY_COMPLEX, 1,textColor);
}
void GetContour(Mat grayim)
{
Mat binaryim;
Threshold(grayim, binaryim); // binaryzation
vector<vector<Point>> contours;
//CV_CHAIN_APPROX_NONE Get all of the pixels of the contours
findContours(binaryim, contours, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, cvPoint(0,0));
getSizeContours(contours);
vector<Mat> oval_result;
MinConvexOval(grayim,contours,oval_result);
}
Testing image:
Result image:
The fitting result of the right-down shape is wrong, could anyone help me, please? Thanks a lot!
Sorry, the problem is with the fitting of the last contour (bottom right one)... it is strange... What is also strange is that the ellipses do not really encapsulate the whole contour... is it ok that?
Absolutely, would you please explain the reason?
I am not sure, can you post the code that is computing the contours? And by the way,what version do you use?
I posted all the codes, plz help me to check it, my opencv version is 2.4.11.
The code start from the GetContour() function.
I made some tests and it appears the right bottom banana like shape can't be fitted. Imho this issue has already been fixed in OpenCV 3.0, see https://github.com/Itseez/opencv/pull... . Maybe you can try it with OpenCV 3.0 again?
I will try to help too. "Why the ellipses do not really encapsulate the whole contour". I think that the reason is the function fits the point in a "least-squares sense" by minimizing the overall distance error between the real points and the best fitted ellipse.
Maybe it is a bug, I may be wrong but I think that the problem is due to the method used to fit the ellipse (Fitzgibbon95) with some specific set of points.
Another example of bad ellipse fitting here.