帧差法侦测运动目标 发表于 2018-11-16 更新于 2019-01-02 分类于 未分类 本文字数: 5k 阅读时长 ≈ 5 分钟 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176#include<iostream>#include<opencv2\core\core.hpp>#include<opencv2\highgui\highgui.hpp>#include<opencv2\imgproc\imgproc.hpp>using namespace std;using namespace cv;const unsigned char FORE_GROUD = 255;int thresh = 30;int maxArea = 100;int times = 100;Point getCenterPoint(Rect rect){ Point cpt; cpt.x = rect.x + cvRound(rect.width/2.0); cpt.y = rect.y + cvRound(rect.height/2.0); return cpt;}int main(int argc,char*argv[]){ VideoCapture video(0); //判断如果video是否可以打开 if(!video.isOpened()) return -1; cout<<"Opened"<<endl; //用于保存当前帧的图片 Mat currentBGRFrame; //用来保存上一帧和当前帧的灰度图片 Mat previousSecondGrayFrame; Mat previousFirstGrayFrame; Mat currentGaryFrame; //保存两次的帧差 Mat previousFrameDifference;//previousFrameFirst - previousFrameSecond的差分 Mat currentFrameDifference;//currentFrame - previousFrameFirst; //用来保存帧差的绝对值 Mat absFrameDifferece; //用来显示前景 Mat previousSegmentation; Mat currentSegmentation; Mat segmentation; //显示前景 namedWindow("segmentation",1); createTrackbar("阈值:","segmentation",&thresh,FORE_GROUD,NULL); createTrackbar("面积:","segmentation",&maxArea,FORE_GROUD,NULL); //帧数 int numberFrame = 0; //形态学处理用到的算子 Mat morphologyKernel = getStructuringElement(MORPH_RECT,Size(3,3),Point(-1,-1)); for(;;) { //读取当前帧 video >> currentBGRFrame; //判断当前帧是否存在 if(!currentBGRFrame.data) continue; numberFrame++; //颜色空间的转换 cvtColor(currentBGRFrame,currentGaryFrame,COLOR_BGR2GRAY); if( numberFrame == 1) { //保存当前帧的灰度图 previousSecondGrayFrame = currentGaryFrame.clone(); //显示视频 imshow("video",currentBGRFrame); continue; } else if( numberFrame == 2) { //保存当前帧的灰度图 previousFirstGrayFrame = currentGaryFrame.clone(); //previousFirst - previousSecond subtract(previousFirstGrayFrame,previousSecondGrayFrame,previousFrameDifference,Mat(),CV_16SC1); //取绝对值 absFrameDifferece = abs(previousFrameDifference); //位深的改变 absFrameDifferece.convertTo(absFrameDifferece,CV_8UC1,1,0); //阈值处理 threshold(absFrameDifferece,previousSegmentation,double(thresh),double(FORE_GROUD),THRESH_BINARY); //显示视频 imshow("video",currentBGRFrame); continue; } else { //src1-src2 //subtract(currentGaryFrame,previousFirstGrayFrame,currentFrameDifference,Mat(),CV_16SC1); //取绝对值 //absFrameDifferece = abs(currentFrameDifference); absdiff(currentGaryFrame,previousFirstGrayFrame,absFrameDifferece); //位深的改变 absFrameDifferece.convertTo(absFrameDifferece,CV_8UC1,1,0); //阈值处理 threshold(absFrameDifferece,currentSegmentation,double(thresh),double(FORE_GROUD),THRESH_BINARY); //与运算 bitwise_and(previousSegmentation,currentSegmentation,segmentation); //中值滤波 medianBlur(segmentation,segmentation,3); //形态学处理(开闭运算) //morphologyEx(segmentation,segmentation,MORPH_OPEN,morphologyKernel,Point(-1,-1),1,BORDER_REPLICATE); morphologyEx(segmentation,segmentation,MORPH_CLOSE,morphologyKernel,Point(-1,-1),2,BORDER_REPLICATE); //找边界 vector< vector<Point> > contours; vector<Vec4i> hierarchy; //复制segmentation Mat tempSegmentation = segmentation.clone(); findContours( segmentation, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );//CV_RETR_TREE vector< vector<Point> > contours_poly( contours.size() ); /*存储运动物体*/ Rect rect = Rect(0,0,0,0); vector<Rect> boundRect; boundRect.clear(); //画出运动物体 for(unsigned int index = 0;index < contours.size() ;index++) { approxPolyDP( Mat(contours[index]), contours_poly[index], 3, true ); Rect tmprect = boundingRect( Mat(contours_poly[index]) ); //cout<<getCenterPoint(rect)<<endl; int currentArea = tmprect.area(); if( currentArea >= rect.area() && currentArea >= maxArea*times ) rect = tmprect; } rectangle(currentBGRFrame,rect,Scalar(0,255,255),2); //显示视频 imshow("video",currentBGRFrame); //前景检测 imshow("segmentation",segmentation); //保存当前帧的灰度图 previousFirstGrayFrame = currentGaryFrame.clone(); //保存当前的前景检测 previousSegmentation = currentSegmentation.clone(); } if(waitKey(33) == 'q') break; } return 0;}