帧差法是背景减图法中的一种,只不过是帧差法不需要建模,因为它的背景模型就是上一帧的图,所以速度非常快,另外帧差法对缓慢变换的光照不是很敏感,所以其用途还是有的,有不少学者对其做出了出色的改进。
其基本原理可以用下面公式看出:
|i(t)-i(t-1)|<T 背景
|i(t)-i(t-1)|>=T 前景
其中i(t),i(t-1)分别为t,t-1时刻对应像素点的像素值,T为阈值。
当然其缺点也不少,容易出现”双影”和”空洞”现象。
用opencv2.3.1+vs2010做了个简单的实验,其实验代码如下:
// frame_diff.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#define threshold_diff 20 //设置简单帧差法阈值
using namespace cv;
using namespace std;
int main(int argc,unsigned char* argv[])
{
Mat img_src1,img_src2,img_dst,gray1,gray2,gray_diff;
bool pause=false;
VideoCapture vido_file("IndoorGTTest1.avi");//在这里改相应的文件名
namedWindow("foreground",0);
for (;;)
{
if(!pause)
{
vido_file >>img_src1; //因为视频文件帧数已经固定了,所以每次到这句语句都是读取相邻的帧数,没到时间视频并不向前走
cvtColor(img_src1,gray1,CV_BGR2GRAY);
imshow("video_src",img_src1);//可以事先不用新建一个窗口
waitKey(5);
vido_file >>img_src2;
cvtColor(img_src2,gray2,CV_BGR2GRAY);
imshow("video_src",img_src2);//可以事先不用新建一个窗口
waitKey(5);
subtract(gray1,gray2,gray_diff);
for(int i=0;i<gray_diff.rows;i++)
for(int j=0;j<gray_diff.cols;j++)
if(abs(gray_diff.at<unsigned char>(i,j))>=threshold_diff)//这里模板参数一定要用unsigned char,否则就一直报错
gray_diff.at<unsigned char>(i,j)=255;
else gray_diff.at<unsigned char>(i,j)=0;
imshow("foreground",gray_diff);
}
char c=(char)waitKey(10);
if (c==27)
{
break;
}
if(c==' ')
pause=!pause;
}
return 0;
}
实验结果如下:

可以看出其“双影”和”空洞”比较明显。双影是由于帧差法有2个影子,在该试验中就是轮廓变得很粗,”空洞”是由于物体内部颜色相近,检测不出来。当然帧差法还有个致命的缺点那就是阈值T需要人工设定。
对于帧差法的”双影”现象,有人提出来了三帧差法。其原理如下所示:
1. 由i(t)-i(t-1)得到前景图 F1
2. 由i(t+1)-i(t)得到前景图 F2
3. F1 ∩ F2得到前景图 F3
4. 形态学处理
浙公网安备 33010602011771号