zoukankan      html  css  js  c++  java
  • 使用CvStartfindcontours画出轮廓。

    //用于提取轮廓,同时要挑选最大轮廓画出
    			scanner=cvStartFindContours(pFrImg,storage,sizeof(CvContour),CV_RETR_CCOMP,CV_CHAIN_APPROX_NONE,cvPoint(0,0));
    			int aera;
    			while (contour=cvFindNextContour(scanner))
    			{   //比较面积大小
    				aera=fabs(cvContourArea(contour));
    				if (aera>1000)
    				{
    					CvRect rect=cvBoundingRect(contour,0);
    					cvRectangle(pFrame,cvPoint(rect.x+rect.width,rect.y),cvPoint(rect.x,rect.y+rect.height),CV_RGB(255,0,0),4,8,0);
    
    				}
    			}
    			// 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对象,里面包含了围线的点   

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


    #include <highgui.h>
    #include <cv.h>
    #include <iostream>
    #include <cvaux.h>
    #include <stdio.h>
    #include <Windows.h>
    int count=0;
    int main(int argc,char *argv)
    {   cvNamedWindow("video");
       //cvNamedWindow("video1");
      CvMemStorage *storage=cvCreateMemStorage();
      CvSeq *contour=0;
      CvSeq *contmax=0;
      CvContourScanner scanner;
    	IplImage* pFrame = NULL; 
    	IplImage* pFrImg = NULL;
    	IplImage* pBkImg = NULL;
    
    	CvMat* pFrameMat = NULL;
    	CvMat* pFrMat = NULL;
    	CvMat* pBkMat = NULL;
    	int nFrmNum = 0;
    
    	//创建窗口
    	cvNamedWindow("video", 1);
    	cvNamedWindow("background",1);
    	cvNamedWindow("foreground",1);
    	//使窗口有序排列
    	cvMoveWindow("video", 30, 0);
    	cvMoveWindow("background", 360, 0);
    	cvMoveWindow("foreground", 690, 0);
    
    
    
    	CvCapture *capture=cvCaptureFromAVI("E:\\自己编写的程序\\测试视频\\test3.avi");
    	CvGaussBGModel* bg_model=NULL;
    	while(1)
    	{
    		pFrame=cvQueryFrame(capture);
    		nFrmNum++;
    
    		//如果是第一帧,需要申请内存,并初始化
    		if(nFrmNum == 1)
    		{
    			pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,3);   
    			pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);     
    
    
    			//高斯背景建模,pFrame可以是多通道图像也可以是单通道图像
    			//cvCreateGaussianBGModel函数返回值为CvBGStatModel*,
    			//需要强制转换成CvGaussBGModel*
    			bg_model = (CvGaussBGModel*)cvCreateGaussianBGModel(pFrame, 0);
    
    		}
    		else
    		{
    			cvUpdateBGStatModel(pFrame, (CvBGStatModel *)bg_model );
    
    			//pFrImg为前景图像,只能为单通道
    			//pBkImg为背景图像,可以为单通道或与pFrame通道数相同
    			cvCopy(bg_model->foreground,pFrImg,0);
    			cvCopy(bg_model->background,pBkImg,0);
    
    			//把图像正过来
    			pBkImg->origin=1;
    			//用于提取轮廓,同时要挑选最大轮廓画出
    			scanner=cvStartFindContours(pFrImg,storage,sizeof(CvContour),CV_RETR_CCOMP,CV_CHAIN_APPROX_NONE,cvPoint(0,0));
    			int aera;
    			while (contour=cvFindNextContour(scanner))
    			{   //比较面积大小
    				aera=fabs(cvContourArea(contour));
    				if (aera>1000)
    				{
    					CvRect rect=cvBoundingRect(contour,0);
    					cvRectangle(pFrame,cvPoint(rect.x+rect.width,rect.y),cvPoint(rect.x,rect.y+rect.height),CV_RGB(255,0,0),4,8,0);
    
    				}
    			}
    			// pFrImg->origin=1;  // 这个不需要翻转(实验结果得知)
    
    			cvShowImage("video", pFrame);    
    			cvShowImage("background", pBkImg);    
    			cvShowImage("foreground", pFrImg);       
    			if( cvWaitKey(33) >= 0 )      
    				break;     
    
    
    
    		}
    	}
    
    
    	//销毁窗口
    	cvReleaseBGStatModel((CvBGStatModel**)&bg_model);
    
    	cvDestroyWindow("video");
    	cvDestroyWindow("background");
    	cvDestroyWindow("foreground");
    
    	//释放图像和矩阵
    // 	cvReleaseImage(&pFrImg);
    // 	cvReleaseImage(&pBkImg);
    
    	cvReleaseMat(&pFrameMat);
    	cvReleaseMat(&pFrMat);
    	cvReleaseMat(&pBkMat);
    
    	cvReleaseCapture(&capture);
    
    	return 0;
    
    }


  • 相关阅读:
    python和搜索
    Flask---ajax(jquery)交互
    Flask--修改默认的static文件夹的方法
    Flask设计带认证token的RESTful API接口[翻译]
    Python 和 Flask实现RESTful services
    等差数列偶数被除2删除后的恢复问题(2018小马智行秋招计算机视觉第三道编程题)
    Leetcode 140 单词拆分II: 字符串s在字典wordDict中有多少种拆分方法。
    LeetCode 139 单词拆分:字符串s能否分割为字符串数组words(wordDict)中字符串的组合?(某未来公司面试题目)
    ROS时间概念总结:ros::Time、ros::Duration、定时器ros::Timer&ros::Rate
    ++i、i++、i+=1、i=i+1的区别
  • 原文地址:https://www.cnblogs.com/polly333/p/4498436.html
Copyright © 2011-2022 走看看