帧间差分法是一种通过对视频图像序列中相邻两帧作差分运算来获得运动目标轮廓的方法,它可以很好地适用于存在多个运动目标和摄像机移动的情况。当监控场景中出现异常物体运动时,帧与帧之间会出现较为明显的差别,两帧相减,得到两帧图像亮度差的绝对值,判断它是否大于阈值来分析视频或图像序列的运动特性,确定图像序列中有无物体运动。
优点:速度快,对光线等场景变化不太敏感,能够适应各种动态环境,稳定性较好,适用于实时性较高的场合。
缺点:①不能提取出对象的完整区域,只能提取出边界;②依赖于选择的帧间时间间隔。对快速运动的物体,需要选择较小的时间间隔,如果选择不合适,当物体在前后两帧中没有重叠时,会被检测为两个分开的物体:而对慢速运动的物体,应该选择较大的时间差,如果时间选择不适当,当物体在前后两帧中几乎完全重叠时,则检测不到物体;③“双影”现象,由于帧差法有两帧,所以导致差分图像物体边缘轮廓较粗,三侦察发可以一定利用2次相邻帧的差,然后去与操作,就得到了真正的那个影子);④“空洞”现象,当运动目标的色彩分布比较均匀时,且在前后两帖中,运动目标所在位置的差别在目标运动方向两侧,内部却没有什么变化,这样通过帖差法会漏检目标内部的像素点,导致运动目标有空洞出现;⑤算法效果依赖于差分图像二值化时阈值的选取。
代码如下:
#include <iostream> #include "cv.h" #include "opencv2/opencv.hpp" using namespace std; using namespace cv; // 描述:帧差法 void main() { //读入视频 VideoCapture capture("J:\\CQH\\DLFR\\lab_face\\video\\DSC_0023.MOV"); namedWindow("当前视频帧",CV_WINDOW_NORMAL); namedWindow("背景减图后区域", CV_WINDOW_NORMAL); Mat tempframe, currentframe, previousframe; Mat frame; int framenum = 0; while (true) { //读取帧 tempframe = capture.read(frame); capture >> frame; tempframe = frame; framenum++; if (framenum == 1) { cvtColor(tempframe, previousframe, CV_BGR2GRAY); } else { //将tempframe转为单通道灰度图,输出为currentFrame cvtColor(tempframe, currentframe, CV_BGR2GRAY); //做差求绝对值,输出为currentframe,即差分图像 absdiff(currentframe, previousframe, currentframe); //遍历差分图像中点,将图像信息二值化,大于阈值20,为255,反之则为0,输出为currentframe threshold(currentframe, currentframe, 20, 255.0, CV_THRESH_BINARY); dilate(currentframe, currentframe, Mat());//膨胀 erode(currentframe, currentframe, Mat());//腐蚀 //显示图像 imshow("当前视频帧", tempframe); imshow("背景减图后区域", currentframe); } //把当前帧保存作为下一次处理的前一帧 cvtColor(tempframe, previousframe, CV_BGR2GRAY); waitKey(33); } }
运行效果如下: