基於opencv的BackgroundSubtractorMOG2和BackgroundSubtractorKNN通過背景減除來實現目標追蹤

  背景減除(Background Subtraction)是許多基於計算機視覺的任務中的主要預處理步驟。如果我們有完整的靜止的背景幀,那麼我們可以通過幀差法來計算像素差從而獲取到前景對象。但是在大多數情況下,我們可能沒有這樣的圖像,所以我們需要從我們擁有的任何圖像中提取背景。當運動物體有陰影時,由於陰影也在移動,情況會變的變得更加複雜。爲此引入了背景減除算法,通過這一方法我們能夠從視頻中分離出運動的物體前景,從而達到目標檢測的目的。

 

MOG2

MOG2算法,也是高斯混合模型分離算法,是MOG的改進算法。它基於Z.Zivkovic發佈的兩篇論文,即2004年發佈的“Improved adaptive Gausian mixture model for background subtraction”和2006年發佈的“Efficient Adaptive Density Estimation per Image Pixel for the Task of Background Subtraction”中提出。該算法的一個重要特徵是 它爲每個像素選擇適當數量的高斯分佈,它可以更好地適應不同場景的照明變化等。

基本思路:

混合高斯模型:

將圖像分爲3-5個高斯模型,一個像素點來了,如果該像素點離任何一個高斯模型的距離大於其2倍的標準差,則爲前景即運動物體,否則則是背景

步驟:第一步:初始各種參數

           第二步:使用T幀圖像構造模型,對於第一個幀圖像的第一個像素點,使用u1,σ1構造高斯模型

           第三步:對於一個新來的模型,如果該像素在高斯模型3*σ1內,則屬於該高斯模型,對參數進行更新

           第四步:如果不滿足該高斯模型,重新建立一個新的高斯模型


//構造高斯混合模型
Ptr<BackgroundSubtractor> ptrMOG2 = createBackgroundSubtractorMOG2();

//getStructuringElement構造形態學使用的kernel
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
//運用高斯模型進行擬合,在兩個標準差內設置爲0,在兩個標準差外設置爲255
ptrMOG2->apply(frame, bgMask_MOG2);

//使用形態學的開運算做背景的去除
morphologyEx(bgMask_MOG2, bgMask_MOG2, MORPH_OPEN, kernel);

完整項目代碼,可以進行讀寫視頻:

#include <iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include<cstdio>
using namespace std;
using namespace cv;



int main()
{
	VideoCapture video = VideoCapture("F:\\計算機視覺\\c5.mp4");

	VideoWriter write;
	double fps = video.get(CV_CAP_PROP_FPS); //獲取視頻幀率
	double pauseTime = 1000 / fps; //兩幅畫面中間間隔
	int w = static_cast<int>(video.get(CV_CAP_PROP_FRAME_WIDTH));
	int h = static_cast<int>(video.get(CV_CAP_PROP_FRAME_HEIGHT));
	cv::Size S(w, h);

	write.open("testMOGMask.avi", -1, fps, S, true);
	if (!video.isOpened()) {
		cout << "could not load video file ..." << endl;
		return -1;
	}

	Mat frame, bgMask_MOG2, bgMask_KNN, background;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));

	namedWindow("highway_test", WINDOW_AUTOSIZE);
	namedWindow("background_mask_by_MOG2", WINDOW_AUTOSIZE);

	Ptr<BackgroundSubtractor> ptrMOG2 = createBackgroundSubtractorMOG2();

	while (video.read(frame)) {
		imshow("highway_test", frame);

		ptrMOG2->apply(frame, bgMask_MOG2);
		morphologyEx(bgMask_MOG2, bgMask_MOG2, MORPH_OPEN, kernel);

		imshow("background_mask_by_MOG2", bgMask_MOG2);
		write.write(bgMask_MOG2);
		char c = waitKey(50);
		if (c == 27) {
			break;
		}
	}
	//waitKey(0);
	write.release();
	video.release();
	cv::destroyWindow("video");
	return 0;
}

         

 

                        

 

KNN

KNN算法,即K-nearest neigbours - based Background/Foreground Segmentation Algorithm。2006年,由Zoran Zivkovic 和Ferdinand van der Heijden在論文"Efficient adaptive density estimation per image pixel for the task of background subtraction."中提出。

Ptr<BackgroundSubtractor> ptrKNN = createBackgroundSubtractorKNN();
ptrKNN->apply(frame, bgMask_KNN);

完整代碼,可以讀取視頻,寫入視頻,並提取前後景

//以下代碼用OpenCV實現了視頻中背景消除和提取的建模,涉及到KNN(K近鄰算法)
#include <iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include<cstdio>
using namespace std;
using namespace cv;



int main()
{
	VideoCapture video = VideoCapture("F:\\計算機視覺\\c5.mp4");

	VideoWriter write;
	double fps = video.get(CV_CAP_PROP_FPS); //獲取視頻幀率
	double pauseTime = 1000 / fps; //兩幅畫面中間間隔
	int w = static_cast<int>(video.get(CV_CAP_PROP_FRAME_WIDTH));
	int h = static_cast<int>(video.get(CV_CAP_PROP_FRAME_HEIGHT));
	cv::Size S(w, h);

	write.open("testKNNMASK.avi", -1, fps, S, true);
	if (!video.isOpened()) {
		cout << "could not load video file ..." << endl;
		return -1;
	}

	Mat frame, bgMask_KNN, background;

	namedWindow("highway_test", WINDOW_AUTOSIZE);
	//namedWindow("background_mask_by_MOG2", WINDOW_AUTOSIZE);
	//namedWindow("background_by_KNN", WINDOW_AUTOSIZE);
	namedWindow("background_mask_by_KNN", WINDOW_AUTOSIZE);

	Ptr<BackgroundSubtractor> ptrKNN = createBackgroundSubtractorKNN();

	while (video.read(frame)) {
		imshow("highway_test", frame);

		ptrKNN->apply(frame, bgMask_KNN);
		//ptrKNN->getBackgroundImage(background);

		//imshow("background_by_KNN", background);
		imshow("background_mask_by_KNN", bgMask_KNN);
		write.write(bgMask_KNN);
		char c = waitKey(50);
		if (c == 27) {
			break;
		}
	}
	write.release();
	video.release();
	cv::destroyWindow("video");
	return 0;
}

原視頻如上圖所示,下面是效果視頻:

 

    

 

 

 

 

 

 

 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章