一、简介
运动物体检测顾名思义就是在视频(视频文件/摄像头获取)中检测运动物体(目标)。
OpenCV中常用的运动物体检测方法有背景减法、帧差法、光流法, 运动物体检测广泛应用于视频安全监控、车辆检测等方面。
背景减法: 就是用原图像减去背景模型, 剩下的就是前景图像, 即运动目标
帧差法: 就是利用相邻的两帧或者三帧图像, 利用像素之间的差异性, 判断是否有运动目标
------视频就是一帧一帧图像组成的
二、背景减法
基本步骤:
原图-背景 ---> 阈值处理 ---> 去噪声(腐蚀滤波) ---> 膨胀连通 ---> 查找轮廓 ---> 外接矩形(椭圆/圆)
【示例1】图像的处理
1 //图像的处理 2 #include "opencv2/opencv.hpp" 3 using namespace cv; 4 int main() 5 { 6 Mat img1 = imread("1.bmp"); 7 Mat img2 = imread("5.bmp"); 8 imshow("img1", img1); 9 imshow("img2", img2); 10 11 Mat gray1, gray2; 12 cvtColor(img1, gray1, CV_BGR2GRAY); 13 cvtColor(img2, gray2, CV_BGR2GRAY); 14 15 Mat diff; 16 absdiff(gray1, gray2, diff); 17 imshow("absdiss", diff); 18 threshold(diff, diff, 45, 255, CV_THRESH_BINARY); 19 imshow("threshold", diff); 20 21 Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); 22 Mat element2 = getStructuringElement(MORPH_RECT, Size(11, 11)); 23 erode(diff, diff, element); 24 imshow("erode", diff); 25 dilate(diff, diff, element2); 26 imshow("dilate", diff); 27 28 vector<vector<Point>> contours; 29 vector<Vec4i> hierarcy; 30 findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓 31 vector<Rect> boundRect(contours.size()); //定义外接矩形集合 32 //drawContours(img2, contours, -1, Scalar(0, 0, 255), 1, 8); //绘制轮廓 33 int x0=0, y0=0, w0=0, h0=0; 34 for(int i=0; i<contours.size(); i++) 35 { 36 boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形 37 x0 = boundRect[i].x; //获得第i个外接矩形的左上角的x坐标 38 y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标 39 w0 = boundRect[i].width; //获得第i个外接矩形的宽度 40 h0 = boundRect[i].height; //获得第i个外接矩形的高度 41 rectangle(img2, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形 42 } 43 imshow("result", img2); 44 45 waitKey(0); 46 return 0; 47 }
【示例2】视频的处理
1 //视频处理 2 #include "opencv2/opencv.hpp" 3 #include<iostream> 4 5 using namespace std; 6 using namespace cv; 7 8 Mat MoveDetect(Mat background, Mat img) 9 { 10 Mat result = img.clone(); 11 Mat gray1, gray2; 12 cvtColor(background, gray1, CV_BGR2GRAY); 13 cvtColor(img, gray2, CV_BGR2GRAY); 14 15 Mat diff; 16 absdiff(gray1, gray2, diff); 17 //imshow("absdiss", diff); 18 threshold(diff, diff, 45, 255, CV_THRESH_BINARY); 19 //imshow("threshold", diff); 20 21 Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); 22 Mat element2 = getStructuringElement(MORPH_RECT, Size(15, 15)); 23 erode(diff, diff, element); 24 //imshow("erode", diff); 25 26 dilate(diff, diff, element2); 27 //imshow("dilate", 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 x0 = boundRect[i].x; //获得第i个外接矩形的左上角的x坐标 39 y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标 40 w0 = boundRect[i].width; //获得第i个外接矩形的宽度 41 h0 = boundRect[i].height; //获得第i个外接矩形的高度 42 rectangle(result, Point(x0, y0), Point(x0+w0, y0+h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形 43 } 44 return result; 45 } 46 47 int main() 48 { 49 VideoCapture cap("E://bike.avi"); 50 if(!cap.isOpened()) //检查打开是否成功 51 return; 52 Mat frame; 53 Mat background; 54 Mat result; 55 int count=0; 56 while(1) 57 { 58 cap>>frame; 59 if(!frame.empty()) 60 { 61 count++; 62 if(count==1) 63 background = frame.clone(); //提取第一帧为背景帧 64 imshow("video", frame); 65 result = MoveDetect(background, frame); 66 imshow("result", result); 67 if(waitKey(50)==27) 68 break; 69 } 70 else 71 break; 72 } 73 cap.release(); 74 return 0; 75 }
三帧差法
基本步骤: 相邻帧相减------阈值处理-----去除噪声(腐蚀滤波)------膨胀连通------查找轮廓------外接矩形(椭圆/圆)
【示例】
1 //帧差法---移动物体检测 2 #include <opencv2/opencv.hpp> 3 #include <iostream> 4 5 using namespace std; 6 using namespace cv; 7 8 int main() 9 { 10 VideoCapture cap("bike.avi"); 11 if(!cap.isOpened()) //检查打开是否成功 12 return; 13 Mat frame; 14 Mat result; 15 Mat temp; 16 int count=0; 17 while(1) 18 { 19 cap>>frame; 20 if(!frame.empty()) 21 { 22 count++; 23 if(count==1) 24 result = MoveDetect(frame, frame); 25 else 26 result = MoveDetect(temp, frame); 27 imshow("video", frame); 28 imshow("result", result); 29 temp = frame.clone(); 30 if(waitKey(50)==27) 31 break; 32 } 33 else 34 break; 35 } 36 cap.release(); 37 return 0; 38 }