1. 程式人生 > >opencv-視訊處理--實時前景檢測-二幀差法

opencv-視訊處理--實時前景檢測-二幀差法

原視訊


主要思想:

通過當前幀的灰度圖(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;
}



發現當運動的顏色,很接近時,前景檢測運動物體容易出現空洞。

--下一篇會介紹對二幀差法的改進,三幀差法