1 #include "opencv2/opencv.hpp" 2 #include<iostream> 3 using namespace std; 4 using namespace cv; 5 6 Mat MoveDetect(Mat frame1, Mat frame2) 7 { 8 Mat result = frame2.clone(); 9 Mat gray1, gray2; 10 cvtColor(frame1, gray1, CV_BGR2GRAY); 11 cvtColor(frame2, gray2, CV_BGR2GRAY); 12 13 Mat diff; 14 absdiff(gray1, gray2, diff); 15 imshow("absdiss", diff); 16 threshold(diff, diff, 45, 255, CV_THRESH_BINARY); 17 imshow("threshold", diff); 18 19 Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); 20 Mat element2 = getStructuringElement(MORPH_RECT, Size(25, 25)); 21 erode(diff, diff, element); 22 imshow("erode", diff); 23 24 dilate(diff, diff, element2); 25 imshow("dilate", diff); 26 27 vector<vector<Point>> contours; 28 vector<Vec4i> hierarcy; 29 //畫橢圓及中心 30 findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); 31 cout<<"num="<<contours.size()<<endl; 32 vector<RotatedRect> box(contours.size()); 33 for(int i=0; i<contours.size(); i++) 34 { 35 box[i] = fitEllipse(Mat(contours[i])); 36 ellipse(result, box[i], Scalar(0, 255, 0), 2, 8); 37 circle(result, box[i].center, 3, Scalar(0, 0, 255), -1, 8); 38 } 39 return result; 40 } 41 42 void 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 }
和上一篇文章代碼的不一樣點在30-38行,天台行人視頻適合用背景減法處理,自行車視頻適合幀差法處理ios
上篇文章中使用腐蝕膨脹消除噪聲,此次使用濾波方法去除噪聲app
//二值化後使用中值濾波+膨脹
Mat element = getStructuringElement(MORPH_RECT, Size(11, 11)); medianBlur(diff, diff, 5);//中值濾波 imshow("medianBlur", diff); dilate(diff, diff, element); imshow("dilate", diff);
#include "opencv2/opencv.hpp" #include<iostream> using namespace std; using namespace cv; //int to string helper function string intToString(int number) { stringstream ss; ss << number; return ss.str(); } Mat MoveDetect(Mat background, Mat img) { Mat result = img.clone(); Mat gray1, gray2; cvtColor(background, gray1, CV_BGR2GRAY); cvtColor(img, gray2, CV_BGR2GRAY); Mat diff; absdiff(gray1, gray2, diff); threshold(diff, diff, 20, 255, CV_THRESH_BINARY); imshow("threshold", diff); blur(diff, diff, Size(10, 10));//均值濾波 imshow("blur", diff); vector<vector<Point>> contours; vector<Vec4i> hierarcy; findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找輪廓 vector<Rect> boundRect(contours.size()); //定義外接矩形集合 //drawContours(img2, contours, -1, Scalar(0, 0, 255), 1, 8); //繪製輪廓 int x0=0, y0=0, w0=0, h0=0; for(int i=0; i<contours.size(); i++) { boundRect[i] = boundingRect((Mat)contours[i]); //查找每一個輪廓的外接矩形 x0 = boundRect[i].x; //得到第i個外接矩形的左上角的x座標 y0 = boundRect[i].y; //得到第i個外接矩形的左上角的y座標 w0 = boundRect[i].width; //得到第i個外接矩形的寬度 h0 = boundRect[i].height; //得到第i個外接矩形的高度 //rectangle(result, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //繪製第i個外接矩形 circle(result, Point(x0+w0/2, y0+h0/2), 15, Scalar(0, 255, 0), 2, 8); line(result, Point(x0+w0/2-15, y0+h0/2), Point(x0+w0/2+15, y0+h0/2), Scalar(0, 255, 0), 2, 8); line(result, Point(x0+w0/2, y0+h0/2-10), Point(x0+w0/2, y0+h0/2+15), Scalar(0, 255, 0), 2, 8); 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); } return result; } void main() { VideoCapture cap("E://ball.avi"); if(!cap.isOpened()) //檢查打開是否成功 return; Mat frame; Mat result; Mat background; int count=0; while(1) { cap>>frame; if(frame.empty()) break; else{ count++; if(count==1) background = frame.clone(); //提取第一幀爲背景幀 imshow("video", frame); result = MoveDetect(background, frame); imshow("result", result); if(waitKey(50)==27) break; } } cap.release(); }
//其他代碼相同 int x0=0, y0=0, w0=0, h0=0; for(int i=0; i<contours.size(); i++) { boundRect[i] = boundingRect((Mat)contours[i]); //查找每一個輪廓的外接矩形 x0 = boundRect[i].x; //得到第i個外接矩形的左上角的x座標 y0 = boundRect[i].y; //得到第i個外接矩形的左上角的y座標 w0 = boundRect[i].width; //得到第i個外接矩形的寬度 h0 = boundRect[i].height; //得到第i個外接矩形的高度 //篩選 if(w0>30 && h0>30) rectangle(result, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //繪製第i個外接矩形 }
#include "opencv2/opencv.hpp" #include<iostream> using namespace std; using namespace cv; Point center; Point fre_center;//存儲前一幀中心座標 int num=0; vector<Point> points; Mat MoveDetect(Mat background, Mat img) { Mat result = img.clone(); Mat gray1, gray2; cvtColor(background, gray1, CV_BGR2GRAY); cvtColor(img, gray2, CV_BGR2GRAY); Mat diff; absdiff(gray1, gray2, diff); imshow("absdiss", diff); threshold(diff, diff, 45, 255, CV_THRESH_BINARY); imshow("threshold", diff); Mat element = getStructuringElement(MORPH_RECT, Size(1, 1)); Mat element2 = getStructuringElement(MORPH_RECT, Size(9, 9)); erode(diff, diff, element); imshow("erode", diff); dilate(diff, diff, element2); imshow("dilate", diff); vector<vector<Point>> contours; vector<Vec4i> hierarcy; findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找輪廓 vector<Rect> boundRect(contours.size()); //定義外接矩形集合 //drawContours(img2, contours, -1, Scalar(0, 0, 255), 1, 8); //繪製輪廓 vector<RotatedRect> box(contours.size()); int x0=0, y0=0, w0=0, h0=0; for(int i=0; i<contours.size(); i++) { boundRect[i] = boundingRect((Mat)contours[i]); //查找每一個輪廓的外接矩形 x0 = boundRect[i].x; //得到第i個外接矩形的左上角的x座標 y0 = boundRect[i].y; //得到第i個外接矩形的左上角的y座標 w0 = boundRect[i].width; //得到第i個外接矩形的寬度 h0 = boundRect[i].height; //得到第i個外接矩形的高度 if(w0>30 && h0>30)//篩選長寬大於30的輪廓 { num++; //rectangle(result, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //繪製第i個外接矩形 box[i] = fitEllipse(Mat(contours[i])); ellipse(result, box[i], Scalar(255, 0, 0), 2, 8); //橢圓輪廓 circle(result, box[i].center, 3, Scalar(0, 0, 255), -1, 8); //畫中心 center = box[i].center;//當前幀的中心座標 points.push_back(center);//中心塞進points向量集 if(num !=1) { //line(result, fre_center, center, Scalar(255, 0, 0), 2, 8); for(int j=0; j<points.size()-1; j++) line(result, points[j], points[j+1], Scalar(0, 255, 0), 2, 8); } //fre_center = center; } } return result; } void main() { VideoCapture cap("E://man.avi"); if(!cap.isOpened()) //檢查打開是否成功 return; Mat frame; Mat background; Mat result; int count=0; while(1) { cap>>frame; if(!frame.empty()) { count++; if(count==1) background = frame.clone(); //提取第一幀爲背景幀 imshow("video", frame); result = MoveDetect(background, frame); imshow("result", result); if(waitKey(30)==27) break; } else break; } cap.release(); }
1.幀差法檢測運動目標ide
2.預處理:a.轉灰度圖,絕對值作差 b.二值化,腐蝕,中值濾波,膨脹 c.查找輪廓,篩選輪廓,繪製外接矩形,計數,輸出this
1 #include "opencv2/opencv.hpp" 2 #include<iostream> 3 using namespace std; 4 using namespace cv; 5 6 int CarNum = 0; 7 //int to string helper function 8 string intToString(int number) 9 { 10 //this function has a number input and string output 11 stringstream ss; 12 ss << number; 13 return ss.str(); 14 } 15 16 Mat MoveDetect(Mat frame1, Mat frame2) { 17 Mat result = frame2.clone(); 18 Mat gray1, gray2; 19 cvtColor(frame1, gray1, CV_BGR2GRAY); 20 cvtColor(frame2, gray2, CV_BGR2GRAY); 21 22 Mat diff; 23 absdiff(gray1, gray2, diff); 24 //imshow("absdiss", diff); 25 threshold(diff, diff, 25, 255, CV_THRESH_BINARY); 26 imshow("threshold", diff); 27 28 Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); 29 Mat element2 = getStructuringElement(MORPH_RECT, Size(19, 19)); 30 erode(diff, diff, element); 31 //imshow("erode", dst); 32 medianBlur(diff, diff, 3); 33 imshow("medianBlur", diff); 34 dilate(diff, diff, element2); 35 imshow("dilate", diff); 36 37 vector<vector<Point>> contours; 38 vector<Vec4i> hierarcy; 39 findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));//查找輪廓 40 vector<vector<Point>>contours_poly(contours.size()); 41 vector<Rect> boundRect(contours.size()); //定義外接矩形集合 42 //drawContours(img2, contours, -1, Scalar(0, 0, 255), 1, 8); //繪製輪廓 43 int x0 = 0, y0 = 0, w0 = 0, h0 = 0; 44 for (int i = 0; i<contours.size(); i++) 45 { 46 approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);//對圖像輪廓點進行多邊形擬合:輪廓點組成的點集,輸出的多邊形點集,精度(即兩個輪廓點之間的距離),輸出多邊形是否封閉 47 boundRect[i] = boundingRect(Mat(contours_poly[i])); 48 if (boundRect[i].width>55 && boundRect[i].width<180 && boundRect[i].height>55 && boundRect[i].height<180) {//輪廓篩選 49 x0 = boundRect[i].x; 50 y0 = boundRect[i].y; 51 w0 = boundRect[i].width; 52 h0 = boundRect[i].height; 53 54 rectangle(result, Point(x0, y0), Point(x0 + w0, y0 + h0), Scalar(0, 255, 0), 2, 8, 0); 55 if ((y0 + h0 / 2 + 1) >= 138 && (y0 + h0 / 2 - 1) <= 142) {//通過這條線(區間),車輛數量+1 56 CarNum++; 57 } 58 } 59 line(result, Point(0, 140), Point(568, 140), Scalar(0, 0, 255), 1, 8);//畫紅線 60 Point org(0, 35); 61 putText(result, "CarNum=" + intToString(CarNum), org, CV_FONT_HERSHEY_SIMPLEX, 0.8f, Scalar(0, 255, 0), 2); 62 } 63 return result; 64 } 65 66 void main() 67 { 68 VideoCapture cap("E://2.avi"); 69 if (!cap.isOpened()) //檢查打開是否成功 70 return; 71 Mat frame; 72 Mat tmp; 73 Mat result; 74 int count = 0; 75 while (1) 76 { 77 cap >> frame; 78 if(frame.empty())//檢查視頻是否結束 79 break; 80 else{ 81 count++; 82 if (count == 1) 83 result = MoveDetect(frame, frame); 84 else result = MoveDetect(tmp, frame); 85 imshow("video", frame); 86 imshow("result", result); 87 tmp = frame.clone(); 88 if (waitKey(20) == 27) 89 break; 90 } 91 } 92 cap.release(); 93 }