opencv学习心得(六)新版本绘制外形轮廓。
最近在研究opencv2.3.1版本函数,因为函数结构使用C++类型的,所以在一些函数调用上有很多差别,但是在运行速度上提高不少,所以还是新版本好用。其实在新版本发布是,会有相关的使用手册,很多例子会在其中找到。这个程序和例程有所不同,只绘制最外侧的轮廓,为后来的提取图像,有很大帮助。
#include <stdio.h> #include <cv.h> #include <cxcore.h> #include <highgui.h> #include <iostream> using namespace cv; using namespace std; vector<vector<Point>> contours; vector<Vec4i> her; int j=0;//用于随后选择哪个外形轮廓 int main() { VideoCapture video; Mat image,frimg,bkimg,frame; namedWindow("video"); //cvNamedWindow("video", 1); namedWindow("background",1); namedWindow("foreground",1); //使窗口有序排列 cvMoveWindow("video", 30, 0); cvMoveWindow("background", 360, 0); cvMoveWindow("foreground", 690, 0); int num=0; video.open("E:\\自己编写的程序\\测试视频\\test3.avi"); if (!video.isOpened()) { cout<<"video open failed!"<<endl; return 0; } while(1) { num++; video>>image; if (num==1) {//开始阶段在于分配空间 frimg.create(image.cols,image.rows,CV_32FC(1)); //frimg(1,) bkimg.create(image.cols,image.rows,CV_32FC(1)); frame.create(image.cols,image.rows,CV_32FC(1)); cvtColor(image,frimg,CV_RGB2GRAY); cvtColor(image,bkimg,CV_RGB2GRAY); } else { cout<<num<<endl; cvtColor(image,frimg,CV_RGB2GRAY); frimg.copyTo(frame); absdiff(frame,bkimg,frame); /// 使用Threshold二值 threshold(frame,frimg,50,255,CV_THRESH_BINARY); /// 找到轮廓 //contours参数为检测的轮廓数组,每一个轮廓用一个point类型的vector表示 //hiararchy参数和轮廓个数相同,每个轮廓contours[ i ]对应4个hierarchy元素hierarchy[ i ][ 0 ] ~hierarchy[ i ][ 3 ], //分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数。 //CV_RETR_TREE:建立一个等级树结构的轮廓 findContours(frimg,contours,her,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE,Point(0,0)); // / 多边形逼近轮廓 + 获取矩形和圆形边界框 // vector<vector<Point> > contours_poly( contours.size() ); //近似后的轮廓点集 vector<Rect> boundRect( contours.size() ); //包围点集的最小矩形vector // vector<Point2f>center( contours.size() ); //包围点集的最小圆形vector // vector<float>radius( contours.size() ); //包围点集的最小圆形半径vector // for( int i = 0; i < contours.size(); i++ ) // { // approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true ); //对多边形曲线做适当近似,contours_poly[i]是输出的近似点集 // boundRect[i] = boundingRect( Mat(contours_poly[i]) ); //计算并返回包围轮廓点集的最小矩形 // minEnclosingCircle( contours_poly[i], center[i], radius[i] ); //计算并返回包围轮廓点集的最小圆形及其半径 // } // /// 画多边形轮廓 + 包围的矩形框 + 圆形框 // //Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 ); // int aeras=0; // for( int i = 0; i< contours.size(); i++ ) // { // //Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) ); //随机颜色 // // drawContours( drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point() ); // //drawContours( image, contours_poly, i, color, 1, 8, her, 0, Point() ); // //根据轮廓点集contours_poly和轮廓结构hierarchy画出轮廓 // //aeras=cvContourArea(contours); // rectangle( image, boundRect[i].tl(), boundRect[i].br(), CV_RGB(255,0,5), 2, 8, 0 ); //画矩形,tl矩形左上角,br右上角 // circle( image, center[i], (int)radius[i], CV_RGB(255,0,5), 2, 8, 0 ); //画圆形 // } //终于研究出来了,只显示一个最大框 int idx = 0, largestComp = 0; double maxArea = 0;double area; for (int i=0;i<contours.size();i++) { area=fabs(contourArea(contours[i])); if (area>maxArea) { maxArea=area; j=i; } } //只有大于100,才显示矩形框。 if (maxArea>100) { Rect rect=boundingRect(contours[j]); rectangle( image, rect.tl(), rect.br(), CV_RGB(255,0,5), 2, 8, 0 ); } } /// 显示在一个窗口 imshow("video",image); imshow("foreground",frimg); imshow("background",bkimg); char c=waitKey(33); if (c==27) { break; } } return 0; }