使用CvStartfindcontours画出轮廓。

[html] view plaincopyprint?

  1. <div><span style="font-family:Arial;color:#333333;"><span style="font-size: 14px; line-height: 26px;">  
  2. </span></span></div>  

[html] view plaincopyprint?

  1. //用于提取轮廓,同时要挑选最大轮廓画出  
  2.             scanner=cvStartFindContours(pFrImg,storage,sizeof(CvContour),CV_RETR_CCOMP,CV_CHAIN_APPROX_NONE,cvPoint(0,0));  
  3.             int aera;  
  4.             while (contour=cvFindNextContour(scanner))  
  5.             {   //比较面积大小  
  6.                 aera=fabs(cvContourArea(contour));  
  7.                 if (aera>1000)  
  8.                 {  
  9.                     CvRect rect=cvBoundingRect(contour,0);  
  10.                     cvRectangle(pFrame,cvPoint(rect.x+rect.width,rect.y),cvPoint(rect.x,rect.y+rect.height),CV_RGB(255,0,0),4,8,0);  
  11.   
  12.                 }  
  13.             }  
  14.             // pFrImg->origin=1;  // 这个不需要翻转(实验结果得知)  

当然也可用CvFindContours查找特征点实现轮廓画出。以下是在高斯混合建模的基础上将运动目标检测,并标出来。主要函数是       cvFindContours(tour_buf,storage,&contour,sizeof(CvContour),                                    CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);                   

 tour_buf 是需要查找轮廓的单通道灰度图像 ,storage 是临时存储区 ,                 

   contour是存储轮廓点的CvSeq实例,                  

  CV_RECT_EXTERNAL 只查找外围轮廓,还有CV_RECT_TREE                        

  正确调用查找函数后,就是从contour提取轮廓点了           

         contour可能是空指针,提取前最好判断一下   

                 在提取之前还可以调用一个函数:   

                 contour = cvApproxPoly( contour, sizeof(CvContour), storage, CV_POLY_APPROX_DP, 3, 1 );                    可能是拟合,有这一句找出的轮廓线更直。                       

                 contour里面包含了很多个轮廓,每个轮廓是单独存放的   

                 要通过一个迭代器遍历里面每一个轮廓,教程里面都没提到,还是看了源代码学来的   

                CvTreeNodeIterator iterator;   

                cvInitTreeNodeIterator(&iterator,contour,3);   

                 //把所有轮廓的点收集起来   

                CvSeq* allpointsSeq = cvCreateSeq(CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour),   

                                            sizeof(CvPoint), storage);   

                 while( 0 != (contour = (CvSeq*)cvNextTreeNode(&iterator)) ){    

                     //找到一个轮廓就可以用for循环提取里面的点了   

                     //这里遍历CvSeq里面的元素的方法很怪异   

                     onetourlength = contour->total;   

                     //给点数组分配空间,记得释放   

                     CvPoint *points = (CvPoint *)malloc(sizeof(CvPoint) * onetourlength);    

                     //printf("seqlength:%d/n",seqlength);   

                     CvSeqReader reader;   

                     CvPoint pt = cvPoint(0,0);   

                     cvStartReadSeq(contour,&reader);   

                     //开始提取   

                     for(int i = 0 ;i < onetourlength; i++){   

                         CV_READ_SEQ_ELEM(pt,reader);   

                         points[i] = pt;   

                         cvSeqPush(allpointsSeq,&pt);   

                     }     

                     //把这个轮廓点找出后,就可以用这些点画个封闭线  

                    cvPolyLine(image,&points,&onetourlength,1,0,CV_RGB(0,255,0),2,8,0);   

                        

                 }   

                    

                 //刚刚已经画出了找出的每个轮廓,还收集了所有轮廓点,   

                 //因此还可以将这些点用一个围线包围起来,即把所有轮廓包围起来   

                 //这里要用到新的函数   

                 CvSeq* hull;   

               hull = cvConvexHull2(allpointsSeq,0,CV_CLOCKWISE,0);   

                 cvConvexHull2返回一个hull对象,里面包含了围线的点   

                 可以用上面的方法将点取出,然后画出来

 

 

[html] view plaincopyprint?

  1. #include <highgui.h>  
  2. #include <cv.h>  
  3. #include <iostream>  
  4. #include <cvaux.h>  
  5. #include <stdio.h>  
  6. #include <Windows.h>  
  7. int count=0;  
  8. int main(int argc,char *argv)  
  9. {   cvNamedWindow("video");  
  10.    //cvNamedWindow("video1");  
  11.   CvMemStorage *storage=cvCreateMemStorage();  
  12.   CvSeq *contour=0;  
  13.   CvSeq *contmax=0;  
  14.   CvContourScanner scanner;  
  15.     IplImage* pFrame = NULL;   
  16.     IplImage* pFrImg = NULL;  
  17.     IplImage* pBkImg = NULL;  
  18.   
  19.     CvMat* pFrameMat = NULL;  
  20.     CvMat* pFrMat = NULL;  
  21.     CvMat* pBkMat = NULL;  
  22.     int nFrmNum = 0;  
  23.   
  24.     //创建窗口  
  25.     cvNamedWindow("video", 1);  
  26.     cvNamedWindow("background",1);  
  27.     cvNamedWindow("foreground",1);  
  28.     //使窗口有序排列  
  29.     cvMoveWindow("video", 30, 0);  
  30.     cvMoveWindow("background", 360, 0);  
  31.     cvMoveWindow("foreground", 690, 0);  
  32.   
  33.   
  34.   
  35.     CvCapture *capture=cvCaptureFromAVI("E:\\自己编写的程序\\测试视频\\test3.avi");  
  36.     CvGaussBGModel* bg_model=NULL;  
  37.     while(1)  
  38.     {  
  39.         pFrame=cvQueryFrame(capture);  
  40.         nFrmNum++;  
  41.   
  42.         //如果是第一帧,需要申请内存,并初始化  
  43.         if(nFrmNum == 1)  
  44.         {  
  45.             pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,3);     
  46.             pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);       
  47.   
  48.   
  49.             //高斯背景建模,pFrame可以是多通道图像也可以是单通道图像  
  50.             //cvCreateGaussianBGModel函数返回值为CvBGStatModel*,  
  51.             //需要强制转换成CvGaussBGModel*  
  52.             bg_model = (CvGaussBGModel*)cvCreateGaussianBGModel(pFrame, 0);  
  53.   
  54.         }  
  55.         else  
  56.         {  
  57.             cvUpdateBGStatModel(pFrame, (CvBGStatModel *)bg_model );  
  58.   
  59.             //pFrImg为前景图像,只能为单通道  
  60.             //pBkImg为背景图像,可以为单通道或与pFrame通道数相同  
  61.             cvCopy(bg_model->foreground,pFrImg,0);  
  62.             cvCopy(bg_model->background,pBkImg,0);  
  63.   
  64.             //把图像正过来  
  65.             pBkImg->origin=1;  
  66.             //用于提取轮廓,同时要挑选最大轮廓画出  
  67.             scanner=cvStartFindContours(pFrImg,storage,sizeof(CvContour),CV_RETR_CCOMP,CV_CHAIN_APPROX_NONE,cvPoint(0,0));  
  68.             int aera;  
  69.             while (contour=cvFindNextContour(scanner))  
  70.             {   //比较面积大小  
  71.                 aera=fabs(cvContourArea(contour));  
  72.                 if (aera>1000)  
  73.                 {  
  74.                     CvRect rect=cvBoundingRect(contour,0);  
  75.                     cvRectangle(pFrame,cvPoint(rect.x+rect.width,rect.y),cvPoint(rect.x,rect.y+rect.height),CV_RGB(255,0,0),4,8,0);  
  76.   
  77.                 }  
  78.             }  
  79.             // pFrImg->origin=1;  // 这个不需要翻转(实验结果得知)  
  80.   
  81.             cvShowImage("video", pFrame);      
  82.             cvShowImage("background", pBkImg);      
  83.             cvShowImage("foreground", pFrImg);         
  84.             if( cvWaitKey(33) >= 0 )        
  85.                 break;       
  86.   
  87.   
  88.   
  89.         }  
  90.     }  
  91.   
  92.   
  93.     //销毁窗口  
  94.     cvReleaseBGStatModel((CvBGStatModel**)&bg_model);  
  95.   
  96.     cvDestroyWindow("video");  
  97.     cvDestroyWindow("background");  
  98.     cvDestroyWindow("foreground");  
  99.   
  100.     //释放图像和矩阵  
  101. //  cvReleaseImage(&pFrImg);  
  102. //  cvReleaseImage(&pBkImg);  
  103.   
  104.     cvReleaseMat(&pFrameMat);  
  105.     cvReleaseMat(&pFrMat);  
  106.     cvReleaseMat(&pBkMat);  
  107.   
  108.     cvReleaseCapture(&capture);  
  109.   
  110.     return 0;  
  111.   
  112. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值