------------------------------------2014年4月26日编辑--------------------
opencv中的椭圆拟合函数是:
C++: fitEllipse
C : cvFitEllipse2
函数原型:
C++: RotatedRect fitEllipse(InputArray points)
C : CvBox2D cvFitEllipse2(const CvArr* points)
对应C++接口,fitEllipse的输入2维点集可以以std::vector<> or Mat形式存储。函数的返回是RotatedRect 类型,它具有3个成员变量:
center(块中心(x,y)), size(宽和高), angle(旋转角),刚好与椭圆具备的5个参数[a,b,x,y,w,h]吻合
类RotatedRect的原型声明:
class CV_EXPORTS RotatedRect
{
public:
//! various constructors
RotatedRect();
RotatedRect(const Point2f& center, const Size2f& size, float angle);
RotatedRect(const CvBox2D& box);
//! returns 4 vertices of the rectangle
void points(Point2f pts[]) const;
//! returns the minimal up-right rectangle containing the rotated rectangle
Rect boundingRect() const;
//! conversion to the old-style CvBox2D structure
operator CvBox2D() const;
Point2f center; //< the rectangle mass center
Size2f size; //< width and height of the rectangle
float angle; //< the rotation angle. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle.
};
3个成员变量:center(块中心(x,y)), size(宽和高), angle(旋转角: 水平轴和第一边的角);3个构造函数
另外,这里还需要提一下,结构体类型CvBox2D ,它原型如下:
typedef struct CvBox2D
{
CvPoint2D32f center; /* Center of the box. */
CvSize2D32f size; /* Box width and length. */
float angle; /* Angle between the horizontal axis */
/* and the first side (i.e. length) in degrees */
}
CvBox2D;
OpenCV在绘制椭圆的时候,有以下函数:
OpenCV中的椭圆拟合事实上就是对Fitzgibbon提出的直接最小二乘拟合算法的实现,这是一种非迭代的椭圆拟合算法,可以参考论文:《Direct least square fitting of ellipses》,它要求拟合的点至少为6个点。
下面是Opencv安装文件下的一个实例:opencv_source_code/samples/cpp/fitellipse.cpp
// opencv学习笔记-椭圆拟合.cpp : 定义控制台应用程序的入口点。
//
/*
*功能:椭圆拟合
*时间:2014-04-19
*/
#include "stdafx.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include
using namespace cv;
using namespace std;
int sliderPos = 70;
Mat image;
//函数声明
void processImage(int, void*);
int main( int argc, char** argv )
{
const char* filename = "stuff.jpg";
//读取图像
image = imread(filename, 0);
if( image.empty() )
{
cout << "Couldn't open image " << endl;
return 0;
}
imshow("source", image);
namedWindow("result", 1);
// Create toolbars. HighGUI use.
// 创建一个滑动块
createTrackbar( "threshold", "result", &sliderPos, 255, processImage );
processImage(0, 0);
// Wait for a key stroke; the same function arranges events processing
waitKey();
return 0;
}
// Define trackbar callback functon. This function find contours,
// draw it and approximate it by ellipses.
void processImage(int /*h*/, void*)
{
vector > contours;
//这句相当于二值化。这个matlab的那句好像: Iwt = Iw>=threshold;
Mat bimage = image >= sliderPos;
//Mat bimage;
//threshold(image, bimage, sliderPos, 255,CV_THRESH_BINARY);
//提取轮廓,相当于matlab中连通区域分析
findContours(bimage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
//我们将在cimage上面绘图
Mat cimage = Mat::zeros(bimage.size(), CV_8UC3);
for(size_t i = 0; i < contours.size(); i++)
{
//轮廓的边缘点个数
size_t count = contours[i].size();
//Fitzgibbon的椭圆拟合方法,要求至少6个点,文献:Direct Least Squares Fitting of Ellipses[1999]
if( count < 6 )
continue;
Mat pointsf;
//将轮廓中的点转换为以Mat形式存储的2维点集(x,y)
Mat(contours[i]).convertTo(pointsf, CV_32F);
//最小二次拟合(Fitzgibbon的方法)
//box包含了椭圆的5个参数:(x,y,w,h,theta)
RotatedRect box = fitEllipse(pointsf);
//把那些长轴与短轴之比很多的那些椭圆剔除。
if( MAX(box.size.width, box.size.height) > MIN(box.size.width, box.size.height)*8 )
continue;
//绘制轮廓
drawContours(cimage, contours, (int)i, Scalar::all(255), 1, 8);
//绘制椭圆
ellipse(cimage, box, Scalar(0,0,255), 1, CV_AA);
//绘制椭圆
// ellipse(cimage, box.center, box.size*0.5f, box.angle, 0, 360, Scalar(0,255,255), 1, CV_AA);
//绘制矩形框
Point2f vtx[4];
//成员函数points 返回 4个矩形的顶点(x,y)
box.points(vtx);
for( int j = 0; j < 4; j++ )
line(cimage, vtx[j], vtx[(j+1)%4], Scalar(0,255,0), 1, CV_AA);
}
imshow("result", cimage);
}
参考:
1.opencv官方文档 fitellipse
2.opencv官方文档 RotatedRect
3.opencv官方文档 ellipse
1.http://blog.sina.com.cn/s/blog_662c785901011i7z.html
2.http://hi.baidu.com/zsb517/item/fd12932d2a82bf0842634a10
3.http://www.cnblogs.com/slysky/archive/2011/10/14/2212227.html