一、运动物体轮廓椭圆拟合及中心
1 #include "opencv2/opencv.hpp" 2 #include<iostream> 3 4 using namespace std; 5 using namespace cv; 6 7 Mat MoveDetect(Mat frame1, Mat frame2) 8 { 9 Mat result = frame2.clone(); 10 Mat gray1, gray2; 11 cvtColor(frame1, gray1, CV_BGR2GRAY); 12 cvtColor(frame2, gray2, CV_BGR2GRAY); 13 14 Mat diff; 15 absdiff(gray1, gray2, diff); 16 imshow("absdiss", diff); 17 threshold(diff, diff, 45, 255, CV_THRESH_BINARY); 18 imshow("threshold", diff); 19 20 Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); 21 Mat element2 = getStructuringElement(MORPH_RECT, Size(25, 25)); 22 erode(diff, diff, element); 23 imshow("erode", diff); 24 25 dilate(diff, diff, element2); 26 imshow("dilate", diff); 27 28 vector<vector<Point>> contours; 29 vector<Vec4i> hierarcy; 30 //画椭圆及中心 31 findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); 32 cout<<"num="<<contours.size()<<endl; 33 vector<RotatedRect> box(contours.size()); 34 for(int i=0; i<contours.size(); i++) 35 { 36 box[i] = fitEllipse(Mat(contours[i])); 37 ellipse(result, box[i], Scalar(0, 255, 0), 2, 8); 38 circle(result, box[i].center, 3, Scalar(0, 0, 255), -1, 8); 39 } 40 return result; 41 } 42 int main() 43 { 44 VideoCapture cap("E://man.avi"); 45 if(!cap.isOpened()) //检查打开是否成功 46 return; 47 Mat frame; 48 Mat result; 49 Mat background; 50 int count=0; 51 while(1) 52 { 53 cap>>frame; 54 if(frame.empty()) 55 break; 56 else{ 57 count++; 58 if(count==1) 59 background = frame.clone(); //提取第一帧为背景帧 60 imshow("video", frame); 61 result = MoveDetect(background, frame); 62 imshow("result", result); 63 if(waitKey(50)==27) 64 break; 65 } 66 } 67 cap.release(); 68 return 0; 69 }
二、滤波方法去除噪声
1、中值滤波去除噪声
1 //二值化后使用中值滤波+膨胀 2 Mat element = getStructuringElement(MORPH_RECT, Size(11, 11)); 3 medianBlur(diff, diff, 5);//中值滤波 4 imshow("medianBlur", diff); 5 dilate(diff, diff, element); 6 imshow("dilate", diff);
2、均值滤波去除噪声
1 #include "opencv2/opencv.hpp" 2 #include<iostream> 3 4 using namespace std; 5 using namespace cv; 6 7 //int to string helper function 8 string intToString(int number) 9 { 10 stringstream ss; 11 ss << number; 12 return ss.str(); 13 } 14 15 Mat MoveDetect(Mat background, Mat img) 16 { 17 Mat result = img.clone(); 18 Mat gray1, gray2; 19 cvtColor(background, gray1, CV_BGR2GRAY); 20 cvtColor(img, gray2, CV_BGR2GRAY); 21 22 Mat diff; 23 absdiff(gray1, gray2, diff); 24 threshold(diff, diff, 20, 255, CV_THRESH_BINARY); 25 imshow("threshold", diff); 26 blur(diff, diff, Size(10, 10));//均值滤波 27 imshow("blur", diff); 28 29 vector<vector<Point>> contours; 30 vector<Vec4i> hierarcy; 31 findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓 32 vector<Rect> boundRect(contours.size()); //定义外接矩形集合 33 //drawContours(img2, contours, -1, Scalar(0, 0, 255), 1, 8); //绘制轮廓 34 int x0=0, y0=0, w0=0, h0=0; 35 for(int i=0; i<contours.size(); i++) 36 { 37 boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形 38 39 x0 = boundRect[i].x; //获得第i个外接矩形的左上角的x坐标 40 y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标 41 w0 = boundRect[i].width; //获得第i个外接矩形的宽度 42 h0 = boundRect[i].height; //获得第i个外接矩形的高度 43 //rectangle(result, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形 44 circle(result, Point(x0+w0/2, y0+h0/2), 15, Scalar(0, 255, 0), 2, 8); 45 line(result, Point(x0+w0/2-15, y0+h0/2), Point(x0+w0/2+15, y0+h0/2), Scalar(0, 255, 0), 2, 8); 46 line(result, Point(x0+w0/2, y0+h0/2-10), Point(x0+w0/2, y0+h0/2+15), Scalar(0, 255, 0), 2, 8); 47 putText(result,"(" + intToString(x0+w0/2)+","+intToString(y0+h0/2)+")",Point(x0+w0/2+15, y0+h0/2), 1, 1,Scalar(255,0,0),2); 48 } 49 return result; 50 } 51 52 int main() 53 { 54 VideoCapture cap("E://ball.avi"); 55 if(!cap.isOpened()) //检查打开是否成功 56 return; 57 Mat frame; 58 Mat result; 59 Mat background; 60 int count=0; 61 while(1) 62 { 63 cap>>frame; 64 if(frame.empty()) 65 break; 66 else{ 67 count++; 68 if(count==1) 69 background = frame.clone(); //提取第一帧为背景帧 70 imshow("video", frame); 71 result = MoveDetect(background, frame); 72 imshow("result", result); 73 if(waitKey(50)==27) 74 break; 75 } 76 } 77 cap.release(); 78 return 0; 79 }
三、轮廓筛选去除噪声
1 //其余代码相同 2 int x0=0, y0=0, w0=0, h0=0; 3 for(int i=0; i<contours.size(); i++) 4 { 5 boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形 6 7 x0 = boundRect[i].x; //获得第i个外接矩形的左上角的x坐标 8 y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标 9 w0 = boundRect[i].width; //获得第i个外接矩形的宽度 10 h0 = boundRect[i].height; //获得第i个外接矩形的高度 11 //筛选 12 if(w0>30 && h0>30) 13 rectangle(result, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形 14 }
四、运动轨迹绘制
1 #include "opencv2/opencv.hpp" 2 #include<iostream> 3 using namespace std; 4 using namespace cv; 5 6 Point center; 7 Point fre_center;//存储前一帧中心坐标 8 int num=0; 9 vector<Point> points; 10 11 Mat MoveDetect(Mat background, Mat img) 12 { 13 Mat result = img.clone(); 14 Mat gray1, gray2; 15 cvtColor(background, gray1, CV_BGR2GRAY); 16 cvtColor(img, gray2, CV_BGR2GRAY); 17 18 Mat diff; 19 absdiff(gray1, gray2, diff); 20 imshow("absdiss", diff); 21 threshold(diff, diff, 45, 255, CV_THRESH_BINARY); 22 imshow("threshold", diff); 23 24 Mat element = getStructuringElement(MORPH_RECT, Size(1, 1)); 25 Mat element2 = getStructuringElement(MORPH_RECT, Size(9, 9)); 26 erode(diff, diff, element); 27 imshow("erode", diff); 28 dilate(diff, diff, element2); 29 imshow("dilate", diff); 30 31 vector<vector<Point>> contours; 32 vector<Vec4i> hierarcy; 33 findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓 34 vector<Rect> boundRect(contours.size()); //定义外接矩形集合 35 //drawContours(img2, contours, -1, Scalar(0, 0, 255), 1, 8); //绘制轮廓 36 vector<RotatedRect> box(contours.size()); 37 int x0=0, y0=0, w0=0, h0=0; 38 for(int i=0; i<contours.size(); i++) 39 { 40 boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形 41 42 x0 = boundRect[i].x; //获得第i个外接矩形的左上角的x坐标 43 y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标 44 w0 = boundRect[i].width; //获得第i个外接矩形的宽度 45 h0 = boundRect[i].height; //获得第i个外接矩形的高度 46 if(w0>30 && h0>30)//筛选长宽大于30的轮廓 47 { 48 num++; 49 //rectangle(result, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形 50 box[i] = fitEllipse(Mat(contours[i])); 51 ellipse(result, box[i], Scalar(255, 0, 0), 2, 8); //椭圆轮廓 52 circle(result, box[i].center, 3, Scalar(0, 0, 255), -1, 8); //画中心 53 center = box[i].center;//当前帧的中心坐标 54 points.push_back(center);//中心塞进points向量集 55 if(num !=1) 56 { 57 //line(result, fre_center, center, Scalar(255, 0, 0), 2, 8); 58 for(int j=0; j<points.size()-1; j++) 59 line(result, points[j], points[j+1], Scalar(0, 255, 0), 2, 8); 60 } 61 //fre_center = center; 62 } 63 } 64 return result; 65 } 66 67 int main() 68 { 69 VideoCapture cap("E://man.avi"); 70 if(!cap.isOpened()) //检查打开是否成功 71 return; 72 Mat frame; 73 Mat background; 74 Mat result; 75 int count=0; 76 while(1) 77 { 78 cap>>frame; 79 if(!frame.empty()) 80 { 81 count++; 82 if(count==1) 83 background = frame.clone(); //提取第一帧为背景帧 84 imshow("video", frame); 85 result = MoveDetect(background, frame); 86 imshow("result", result); 87 if(waitKey(30)==27) 88 break; 89 } 90 else 91 break; 92 } 93 cap.release(); 94 return 0; 95 }
五、车辆数量检测
1.帧差法检测运动目标
2.预处理:a.转灰度图,绝对值做差 b.二值化,腐蚀,中值滤波,膨胀 c.查找轮廓,筛选轮廓,绘制外接矩形,计数,输出
1 #include "opencv2/opencv.hpp" 2 #include<iostream> 3 4 using namespace std; 5 using namespace cv; 6 7 int CarNum = 0; 8 //int to string helper function 9 string intToString(int number) 10 { 11 //this function has a number input and string output 12 stringstream ss; 13 ss << number; 14 return ss.str(); 15 } 16 17 Mat MoveDetect(Mat frame1, Mat frame2) { 18 Mat result = frame2.clone(); 19 Mat gray1, gray2; 20 cvtColor(frame1, gray1, CV_BGR2GRAY); 21 cvtColor(frame2, gray2, CV_BGR2GRAY); 22 23 Mat diff; 24 absdiff(gray1, gray2, diff); 25 //imshow("absdiss", diff); 26 threshold(diff, diff, 25, 255, CV_THRESH_BINARY); 27 imshow("threshold", diff); 28 29 Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); 30 Mat element2 = getStructuringElement(MORPH_RECT, Size(19, 19)); 31 erode(diff, diff, element); 32 //imshow("erode", dst); 33 medianBlur(diff, diff, 3); 34 imshow("medianBlur", diff); 35 dilate(diff, diff, element2); 36 imshow("dilate", diff); 37 38 vector<vector<Point>> contours; 39 vector<Vec4i> hierarcy; 40 findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));//查找轮廓 41 vector<vector<Point>>contours_poly(contours.size()); 42 vector<Rect> boundRect(contours.size()); //定义外接矩形集合 43 //drawContours(img2, contours, -1, Scalar(0, 0, 255), 1, 8); //绘制轮廓 44 int x0 = 0, y0 = 0, w0 = 0, h0 = 0; 45 for (int i = 0; i<contours.size(); i++) 46 { 47 approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);//对图像轮廓点进行多边形拟合:轮廓点组成的点集,输出的多边形点集,精度(即两个轮廓点之间的距离),输出多边形是否封闭 48 boundRect[i] = boundingRect(Mat(contours_poly[i])); 49 if (boundRect[i].width>55 && boundRect[i].width<180 && boundRect[i].height>55 && boundRect[i].height<180) {//轮廓筛选 50 x0 = boundRect[i].x; 51 y0 = boundRect[i].y; 52 w0 = boundRect[i].width; 53 h0 = boundRect[i].height; 54 55 rectangle(result, Point(x0, y0), Point(x0 + w0, y0 + h0), Scalar(0, 255, 0), 2, 8, 0); 56 if ((y0 + h0 / 2 + 1) >= 138 && (y0 + h0 / 2 - 1) <= 142) {//经过这条线(区间),车辆数量+1 57 CarNum++; 58 } 59 } 60 line(result, Point(0, 140), Point(568, 140), Scalar(0, 0, 255), 1, 8);//画红线 61 Point org(0, 35); 62 putText(result, "CarNum=" + intToString(CarNum), org, CV_FONT_HERSHEY_SIMPLEX, 0.8f, Scalar(0, 255, 0), 2); 63 } 64 return result; 65 } 66 67 int main() 68 { 69 VideoCapture cap("E://2.avi"); 70 if (!cap.isOpened()) //检查打开是否成功 71 return; 72 Mat frame; 73 Mat tmp; 74 Mat result; 75 int count = 0; 76 while (1) 77 { 78 cap >> frame; 79 if(frame.empty())//检查视频是否结束 80 break; 81 else{ 82 count++; 83 if (count == 1) 84 result = MoveDetect(frame, frame); 85 else result = MoveDetect(tmp, frame); 86 imshow("video", frame); 87 imshow("result", result); 88 tmp = frame.clone(); 89 if (waitKey(20) == 27) 90 break; 91 } 92 } 93 cap.release(); 94 return 0; 95 }