圆及椭圆拟合

       在opencv学习中,圆和椭圆的拟合是必不可少的,下面我就用一个简单的例子介绍一下我们如何用opencv来拟合。

      实验描述:

                     输入:图像文件seal1.jpg、seal2.jpg、coin1.jpg 

                     任务: 尝试将上述三个图像中圆或椭圆信息提取出来

    输出要求    1、拟合相应的圆以及椭圆 
2.  每个拟合圆或椭圆的中心坐标,半径或长短轴长度; 
3.  将主要的中间结果及最终拟合结果用OpenCV的cvShowImage显示出来。

               编程工具:Visual C++/Visual Studio,OpenCV

               提示(可能用到的处理方法,不一定全部用到):二值化 
形态学操作 
Canny边缘检测 
轮廓提取 
椭圆拟合 
Hough圆检测


好了,废话不多说,还是直接上代码吧,其中的注释已经写得非常详细了,大家应该看了就能懂了

程序说明:本程序首先读取图像和图像预处理,将读入的图像转换为灰度图,在对它进行二值化,接着抽取图像中对象的轮廓属性,然后进行图像拟合,最后输出结果。在这里,主要输出拟合后的图像,原来读入的图像,方便人对前后结果进行比较,还输出了每个拟合圆或椭圆的中心坐标,半径或长短轴长度,用数字来说话,一目了然。最后记得释放资源销毁窗口。




#include "stdafx.h"
#include 
#include 
#include 
#include 
#include 

int main( int argc, char** argv ) 
 {
    /****************1.读取图像和图像预处理****************/


   argv[1]="seal1.jpg";  /*读入图像,分别输入seal1,seal2和coin1,并更改下列两处参数值*/

   IplImage* image = cvLoadImage(argv[1]);
   IplImage* gray;/*保存灰度图*/
   IplImage* result;/*保存结果*/

   gray=cvCreateImage(cvSize(image->width,image->height),IPL_DEPTH_8U,1);  /*创建输出图像,位无符号深度,通道*/
   result=cvCreateImage(cvSize(image->width,image->height),IPL_DEPTH_8U,1);  /*创建输出图像,位无符号深度,通道*/

   cvZero(result);

   CvMemStorage* storage=cvCreateMemStorage(0);
   CvSeq *contour; 
 
   int count;
   CvPoint *PointArray;
   CvPoint center;
   CvPoint2D32f *PointArray2D32f;

      /* 创建动态结构序列*/
   storage = cvCreateMemStorage(0);
   contour = cvCreateSeq(CV_SEQ_ELTYPE_POINT,sizeof(CvSeq),sizeof(CvPoint),storage);
   CvBox2D *box;
   CvSize size;



    /****************2.将图像转换为二值图像****************/


   cvCvtColor(image,gray,CV_BGR2GRAY);      /*把image转换成灰度放到gray中*/
   cvSmooth(gray,gray);
   cvThreshold( gray, gray, 195, 255, CV_THRESH_BINARY );      /*将灰度图像二值化,需要针对输入图像进行调整,seal1时对应(195, 255),seal2时对应(190, 255),coin1时对应(70, 200)*/

    /****************3.抽取图像中对象的轮廓属性****************/

   cvFindContours( gray, storage, &contour, sizeof(CvContour),CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);  /*找轮廓*/
            /*遍历每个轮廓*/
       for(;contour;contour=contour->h_next){
	       count=contour->total;
	       if(count<250)        /*去掉轮廓小于一定数值的圆,要根据输入图像进行调整,seal1时对应250,seal2时对应160,coin1时对应75*/
		       continue;
            // Alloc memory for contour point set.  
	        PointArray = (CvPoint*)malloc( count*sizeof(CvPoint) );
            PointArray2D32f= (CvPoint2D32f*)malloc( count*sizeof(CvPoint2D32f) );

			// Alloc memory for ellipse data.
            box = (CvBox2D32f*)malloc(sizeof(CvBox2D32f));
            /*格式转化,contour -- PointArray -- PointArray2D32f*/
	        cvCvtSeqToArray(contour, PointArray, CV_WHOLE_SEQ); 
              for(int i=0;icenter.x);     /*确定椭圆box的值center、size、angle*/
        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;


        cvDrawContours(gray,contour,CV_RGB(255,255,255),CV_RGB(255,255,255),0,1,8,cvPoint(0,0)); /*画轮廓*/
        cvEllipse(result,center,size,box->angle,0,360,CV_RGB(0,0,255),1,CV_AA,0);   /*画椭圆到result*/



    /****************5.输出结果*********************/


		printf("中心位置:x=%d,y=%d\n",center.x,center.y);  /*输出中心位置*/
		printf("半径或长短轴长度:w=%d,h=%d\n",size.width,size.height);  /*输出半径或长短轴长度*/
		printf("---------------------------------------------------------------------\n");/*不同圆或椭圆数据输出分割线*/
        /*释放空间*/  
        free(PointArray);
        free(PointArray2D32f);
        free(box);
 }
                                    /*图像输出*/
	                     cvNamedWindow("原图",1);
						 cvShowImage("原图",image);
                           cvSaveImage( "拟合.jpg", result );/*将图片保存到本地*/
                           cvNamedWindow( "拟合", 1 );/*窗口命名*/
                           cvShowImage( "拟合", result );/*显示图片*/
                     
			 // Wait for a key stroke; the same function arranges events processing   
						    cvWaitKey(0);
					  cvReleaseImage(&image);//释放图片资源
					cvReleaseImage(&result);

				 cvDestroyWindow("原图");//销毁窗口
				 cvDestroyWindow("拟合");
                           return 0; 
 }

seal图片(原图):






seal1图片处理后结果:



相关数据输出:



你可能感兴趣的:(opencv)