opencv-視訊處理--實時前景檢測-二幀差法
阿新 • • 發佈:2019-02-16
原視訊
主要思想:
通過當前幀的灰度圖(currentGrayFrame)和前一幀的灰度圖(previousGrayFrame)的差,進行畫素級的比較。
符號:
:代表當前幀(x,y)處的灰度值
:代表前一幀(x,y)處的灰度值
:代表當前幀和上一幀在(x,y)處的差的絕對值
如果
:差值大於閾值Thresh,代表是前景點
:差值小於閾值Thresh,代表為背景點
優點:
實時性
缺點:
1、運動物體如果過大,且顏色一致,則會造成運動物體中空的現象
2、如果光照變化強烈,也不適合該演算法
程式碼:
#include<iostream> using namespace std; #include<opencv2\core\core.hpp> #include<opencv2\highgui\highgui.hpp> #include<opencv2\imgproc\imgproc.hpp> using namespace cv; const unsigned char FORE_GROUD = 255; int thresh = 30; int main(int argc,char*argv[]) { VideoCapture video(argv[1]); //判斷如果video是否可以開啟 if(!video.isOpened()) return -1; //用於儲存當前幀的圖片 Mat currentBGRFrame; //用來儲存上一幀和當前幀的灰度圖片 Mat previousGrayFrame; Mat currentGaryFrame; //用來儲存幀差 Mat frameDifference;//CV_16SC1 //用來儲存幀差的絕對值 Mat absFrameDifferece; //用來顯示前景 Mat segmentation; //顯示原視訊 namedWindow("video",1); //顯示前景 namedWindow("segmentation",1); createTrackbar("閾值:","segmentation",&thresh,FORE_GROUD,NULL); //幀數 int numberFrame = 0; //形態學處理用到的運算元 Mat morphologyKernel = getStructuringElement(MORPH_RECT,Size(3,3),Point(-1,-1)); for(;;) { //讀取當前幀 video >> currentBGRFrame; //判斷當前幀是否存在 if(!currentBGRFrame.data) break; numberFrame++; if( numberFrame == 1) { //顏色空間的轉換 cvtColor(currentBGRFrame,currentGaryFrame,COLOR_BGR2GRAY); //儲存當前幀的灰度圖 previousGrayFrame = currentGaryFrame.clone(); imshow("video",currentBGRFrame); continue; } else { //顏色空間的轉換 cvtColor(currentBGRFrame,currentGaryFrame,COLOR_BGR2GRAY); //src1-src2 subtract(currentGaryFrame,previousGrayFrame,frameDifference,Mat(),CV_16SC1); //取絕對值 absFrameDifferece = abs(frameDifference); //位深的改變 absFrameDifferece.convertTo(absFrameDifferece,CV_8UC1,1,0); //閾值處理 threshold(absFrameDifferece,segmentation,double(thresh),double(FORE_GROUD),THRESH_BINARY); //中值濾波 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); //顯示二值化圖片 imshow("segmentation",segmentation); //找邊界 vector< vector<Point> > contours; vector<Vec4i> hierarchy; findContours( segmentation, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );//CV_RETR_TREE vector< vector<Point> > contours_poly( contours.size() ); /*儲存運動物體*/ vector<Rect> boundRect; boundRect.clear(); //畫出運動物體 //對視訊中出現的運動物體,進行初次的篩選 for(int index = 0;index < contours.size() ;index++) { approxPolyDP( Mat(contours[index]), contours_poly[index], 3, true ); Rect rect = boundingRect( Mat(contours_poly[index]) ); rectangle(currentBGRFrame,rect,Scalar(0,255,255),2); } //顯示原視訊 imshow("video",currentBGRFrame); //儲存當前幀的灰度圖 previousGrayFrame = currentGaryFrame.clone(); } if(waitKey(33) == 'q') break; } return 0; }
發現當運動的顏色,很接近時,前景檢測運動物體容易出現空洞。
--下一篇會介紹對二幀差法的改進,三幀差法