转自http://blog.csdn.net/icvpr/article/details/8487271
下面这段代码利用OpenCV实现了最为简单的基于自适应背景更新的运动目标检测算法。
即:
运动前景提取——背景减除
foreground = |frame - background| > threshold
更新背景模型——滑动平均滤波
background = background + (frame - background) * alpha = background * (1 - alpha) + frame * alpha
- //运动前景检测——基于自适应背景更新
- //Author: www.icvpr.com
- //Blog: http://blog.csdn.net/icvpr
- #include <iostream>
- #include <string>
- #include <opencv2/opencv.hpp>
- int main(int argc, char** argv)
- {
- std::string videoFileName = "../test.avi";
- int threshold = 25 ; // 二值化阈值
- float alpha = 0.01; // 更新速度 [0, 1]
- cv::VideoCapture capture;
- capture.open(videoFileName);
- if (!capture.isOpened())
- {
- std::cout<<"cannot open video"<<std::endl;
- return -1;
- }
- cv::Mat foregroundImg;
- cv::Mat foregroundMat;
- cv::Mat backgroundImg;
- cv::Mat backgroundMat;
- cv::Mat frame;
- cv::Mat grayImg;
- cv::Mat grayMat;
- while (capture.read(frame))
- {
- cv::cvtColor(frame, grayImg, CV_BGR2GRAY);
- grayImg.convertTo(grayMat, CV_32FC1);
- if (backgroundMat.empty())
- {
- grayImg.copyTo(backgroundImg);
- grayImg.convertTo(backgroundMat, CV_32FC1);
- }
- // 背景减除
- cv::absdiff(grayMat, backgroundMat, foregroundMat);
- // 自适应背景更新
- cv::addWeighted(backgroundMat, alpha, foregroundMat, 1-alpha, 0, backgroundMat);
- // 二值化,获取前景像素点
- cv::threshold(foregroundMat, foregroundMat, threshold, 255, CV_THRESH_BINARY);
- // 为了显示用,将CV_32FC1转换为CV_8U
- cv::convertScaleAbs(foregroundMat, foregroundImg);
- cv::convertScaleAbs(backgroundMat, backgroundImg);
- cv::imshow("frame", frame);
- cv::imshow("foreground", foregroundImg);
- cv::imshow("background", backgroundImg);
- if (cv::waitKey(25) > 0)
- {
- break;
- }
- }
- return 0;
- }