最近接触移动侦测项目,其对应的原理主要是背景建模,而背景建模方法众多,常见的如帧差法、背景减除法、codebook、Vibe、GMM等。
前景提取的步骤如下:
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;
void updateBG(Mat src, Mat &dst, double alpha);
void drawRect(Mat &src, Mat mask);
void main()
{
VideoCapture cap("E:\\Database\\768x576.avi");
if (!cap.isOpened())
return;
Mat frame, gray_frame;
Mat BgImg, FrImg_src, FrImg;
Mat BgImg_32, FrImg_src_32, FrImg_32;
bool firstflag = true;
while (1)
{
cap >> frame;
if (frame.empty())
return;
if (firstflag)
{
cvtColor(frame, BgImg, CV_BGR2GRAY);
BgImg.convertTo(BgImg_32, CV_32FC1); //BgImg、FrImg、FrImg_src都已经转换为CV_32FC1.
firstflag = false;
FrImg_32 = BgImg_32.clone();
FrImg_src_32 = BgImg_32.clone();
}
else
{
cvtColor(frame, gray_frame, CV_BGR2GRAY);
gray_frame.convertTo(gray_frame, CV_32FC1);
absdiff(gray_frame, BgImg_32, FrImg_src_32);
threshold(FrImg_src_32, FrImg_32, 50, 255.0, CV_THRESH_BINARY);
updateBG(gray_frame, BgImg_32, 0.005);
BgImg_32.convertTo(BgImg, CV_8UC1);
FrImg_32.convertTo(FrImg, CV_8UC1);
FrImg_src_32.convertTo(FrImg_src, CV_8UC1);
drawRect(frame, FrImg);
imshow("SRC", frame);
imshow("BG", BgImg);
imshow("FG", FrImg);
imshow("FG_Src", FrImg_src);
waitKey(10);
}
}
}
//dst = dst*(1-alpha) + src*alpha
void updateBG(Mat src, Mat &dst, double alpha)
{
for (int i = 0; i < src.rows;i++)
{
float* ptr1 = src.ptr<float>(i);
float* ptr2 = dst.ptr<float>(i);
for (int j = 0; j < src.cols; j++)
{
ptr2[j] = ptr1[j] * alpha + (1 - alpha)*ptr2[j];
}
}
}
void drawRect(Mat &src, Mat mask)
{
vector<vector<Point>> contours;
findContours(mask, contours, CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); i++)
{
Rect r(0, 0, 0, 0);
if (contourArea(contours[i])>100)
{
int x_min = 1000;
int x_max = 0;
int y_min = 1000;
int y_max = 0;
//找最大外接矩形
for (int j = 0; j < contours[i].size(); j++)
{
x_min = x_min > contours[i][j].x ? contours[i][j].x : x_min;
x_max = x_max < contours[i][j].x ? contours[i][j].x : x_max;
y_min = y_min > contours[i][j].y ? contours[i][j].y : y_min;
y_max = y_max < contours[i][j].y ? contours[i][j].y : y_max;
}
r.x = x_min;
r.y = y_min;
r.width = x_max - x_min;
r.height = y_max - y_min;
}
rectangle(src, r, Scalar(0, 255, 0), 2, 8);
}
}
效果还是很不错的,可以有效自适应光照的变化。