基於幀間差分法的前景提取的實現(C++)

一種最簡單的前景(移動區域)提取方怯就是一幀(或之後的幾幀)減去另 一幀,然後將“足夠不同”的地方標爲前景。這個過程會捕捉到移動物體的邊緣。簡單起見,我們考慮三個單通道圖片frameTime1,frameTime2和frameForeground 。圖片frameTime1是過去的一張灰度圖片,frameTime2是當前的灰度圖片。我們用下面的接口來檢測前景,將差分的值(絕對值)保存在frameForeground 中。

cv::absdiff(

frameTime1, // First input array

frameTime2, // Second input array

frameForeground // Result array

);

由於像素總是存在噪音和波動,我們應該忽略幀間微小的不同(例如小於20),並標記出(設爲 255)大的不同。調用閾值化處理函數達到這一目的。

C++實現代碼:

// 幀間差分法
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <string>

using namespace std;

int N = 4; //N幀的幀間差分

int main()
{
	using namespace cv;

	cv::VideoCapture cap;
	if (!cap.open("test.avi"))
	{
		cerr << "Couldn't open video file" << endl;
		return -1;
	}

	vector<Mat> frames;
	for (int i = 1; ; i++)
	{
		Mat frame, frame_gray;
		cap >> frame;
		if( !frame.data ) break;
		if (i > 10 && i <= 10 + N)
		{
			cvtColor(frame, frame_gray, CV_RGB2GRAY); // 將彩色圖像轉換爲灰度圖像;
			frames.push_back(frame_gray);
		}
	}

	int row = frames[0].rows;
	int col = frames[0].cols;

	vector<Mat> alldiff(N-1, Mat(row, col, CV_8UC1)); // 生成一個Mat容器alldiff用於存儲最終的各個幀的差分結果        

	for (int i = 0; i < N - 1; i++)
	{
		Mat diff = Mat(row, col, CV_8UC1);
		absdiff(frames[i], frames[i+1], diff); //幀間差分
		threshold(diff, diff, 20, 255, CV_8UC1); //閾值化處理
		alldiff.push_back(~diff);
		string n = to_string(i);
		string name = "diff_" + n + ".jpg";
		imwrite(name, ~diff);
	}

	waitKey(0);

	return 0;
}

 原視頻:

幀間差分結果:

frame11-frame10
frame12-frame11
frame13-frame12

 

 

發佈了134 篇原創文章 · 獲贊 34 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章