转:https://blog.csdn.net/longwoshixiao/article/details/50341015
一 轮廓检测
二 椭圆拟合
三 程序操作
一 轮廓检测
在进行椭圆拟合时需要先检测出轮廓中的点,这就需要用到cvFindContous命令。
cvFindContours(
CvArr* image,
CvSeq** first_contour,
int header_size CV_DEFAULT(sizeof(CvContour)),
int mode CV_DEFAULT(CV_RETR_LIST),
int method CV_DEFAULT(CV_CHAIN_APPROX_SIMPLE),
CvPoint offset CV_DEFAULT(cvPoint(0,0)))
image: 是一个二值图像,一般由cvThreShold得到
storage: 返回轮廓的容器
first_contour: 输出函数, 指向第一个轮廓的地址
header_size: 序列的尺寸,如果method=CV_CHAIN_CODE, 则
header_size=sizeof(CvChain),否则为sizeof(CvContour)
mode: CV_RETR_EXTERNAL, 只检索最外轮廓
CV_RETR_LIST, 采用横向列表方式检索所用的轮廓
method: CV_CHAIN_CODE - Freeman 链码的输出轮廓. 其它方法输出多边形(定点序列).
CV_CHAIN_APPROX_NONE - 将所有点由链码形式翻译(转化)为点序列形式
CV_CHAIN_APPROX_SIMPLE - 压缩水平、垂直和对角分割,即函数只保留末端的象素点
CV_CHAIN_APPROX_TC89_L1
CV_CHAIN_APPROX_TC89_KCOS - 应用 Teh-Chin 链逼近算法. CV_LINK_RUNS - 通过连接为 1 的水平碎片使用完全不同的轮廓提取算法。仅有 CV_RETR_LIST 提取模式可以在本方法中应用
offset: 偏移量,用于移动所有轮廓点
二 椭圆拟合
cvFitEllipse(
const CvPoint2D32f* points,
int count,
CvBox2D* box )
三 程序操作
CvMemStorage*stor;
CvSeq*cont;
CvFont font;
CvBox2D32f*box;
CvPoint*PointArray;
CvPoint2D32f*PointArray2D32f;
double minarea=10,maxarea=500;
stor=cvCreateMemStorage(0);
cont=cvCreateSeq(CV_SEQ_ELTYPE_POINT,sizeof(CvSeq),sizeof(CvPoint),stor);
cvThreshold(image03,image02,slider_pos,255,CV_THRESH_BINARY);
cvFindContours(image02,stor,&cont,sizeof(CvContour),
CV_RETR_LIST,CV_CHAIN_APPROX_NONE,cvPoint(0,0));
for(;cont;cont=cont->h_next)
{
int i;
int count=cont->total;//轮廓个数
CvPoint center;
CvSize size;
/*个数必须大于6,这是cvFitEllipse_32f的要求*/
if(count<6)
{
continue;
}
double a=abs(cvContourArea(cont));
cvInitFont(&font,CV_FONT_HERSHEY_COMPLEX,0.5f,0.5f,0,1,8); //初始化字体
if (a>=minarea&&a<=maxarea)
{
//分配内存给点集
PointArray=(CvPoint*)malloc(count*sizeof(CvPoint));
PointArray2D32f= (CvPoint2D32f*)malloc(count*sizeof(CvPoint2D32f));
//分配内存给椭圆数据
box=(CvBox2D32f*)malloc(sizeof(CvBox2D32f));
//得到点集
cvCvtSeqToArray(cont,PointArray,CV_WHOLE_SEQ);
//将CvPoint点集转化为CvBox2D32f集合
for(i=0;i<count;i++)
{
PointArray2D32f[i].x=(float)PointArray[i].x;
PointArray2D32f[i].y=(float)PointArray[i].y;
}
//拟合当前轮廓
cvFitEllipse(PointArray2D32f,count,box);
//绘制当前轮廓 cvDrawContours(image04,cont,CV_RGB(255,255,255),CV_RGB(255,255,255),0,1,8,cvPoint(0,0));
//将椭圆数据从浮点转化为整数表示
center.x=cvRound(box->center.x);
center.y=cvRound(box->center.y);
size.width=cvRound(box->size.width*0.5);
size.height=cvRound(box->size.height*0.5);
box->angle=-box->angle;
centerfile<<box->center.x<<" "<<box->center.y<<endl;
//画椭圆
cvEllipse(image04,center,size,box- >angle,0,360,CV_RGB(0,0,255),1,CV_AA,0);
free(PointArray);
free(PointArray2D32f);
free(box);
}
}