一、运动物体轮廓椭圆拟合及中心
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 }