Opencv_CUDA应用之 使用背景相减法进行对象跟踪
-
背景相减法是在一系列视频帧中将前景对象从背景中分离出来的过程,它广泛应用于对象检测和跟踪应用中去除背景
-
背景相减法分四步进行:
图像预处理 -> 背景建模 -> 检测前景 -> 数据验证
-
- 预处理去除噪声
-
- 背景建模,以便与前景分离
-
- 利用当前帧和背景之间的绝对差,将前景与模型背景相分离,将这个绝对差于设置的阈值相比较:如果大于阈值,则对象被认为是移动的,否则是静止的。
-
1. 高斯混合法
- 高斯混合法(MoG) 是一种广泛使用的基于高斯混合的背景减法,用于分离前景和背景
- 背景从帧序列中不断更新,混合K高斯分布用于将像素分类为前景或者背景,同时对帧的时间序列进行加权,以改善背景建模。
- 连续变化的强度被归类为前景强度,静态强度被归类为背景强度
- 实现代码如下:
#include <iostream>
#include <string>
#include "opencv2/opencv.hpp"
#include<opencv2/cudabgsegm.hpp>
using namespace std;
using namespace cv;
using namespace cv::cuda;
int main()
{
VideoCapture cap("images/abc.avi");
if (!cap.isOpened())
{
cerr << "can not open camera or video file" << endl;
return -1;
}
Mat frame;
cap.read(frame);
GpuMat d_frame;
d_frame.upload(frame);
Ptr<BackgroundSubtractor> mog = cuda::createBackgroundSubtractorMOG();
GpuMat d_fgmask, d_fgimage, d_bgimage;
Mat h_fgmask, h_fgimage, h_bgimage;
mog->apply(d_frame, d_fgmask, 0.01);
while (1)
{
cap.read(frame);
if (frame.empty())
break;
d_frame.upload(frame);
int64 start = cv::getTickCount();
mog->apply(d_frame, d_fgmask, 0.01);
mog->getBackgroundImage(d_bgimage);
double fps = cv::getTickFrequency() / (cv::getTickCount() - start);
std::cout << "FPS : " << fps << std::endl;
d_fgimage.create(d_frame.size(), d_frame.type());
d_fgimage.setTo(Scalar::all(0));
d_frame.copyTo(d_fgimage, d_fgmask);
d_fgmask.download(h_fgmask);
d_fgimage.download(h_fgimage);
d_bgimage.download(h_bgimage);
cv::namedWindow("image", 0);
cv::namedWindow("foreground mask", 0);
cv::namedWindow("foreground image", 0);
cv::namedWindow("mean background image", 0);
imshow("image", frame);
imshow("foreground mask", h_fgmask);
imshow("foreground image", h_fgimage);
imshow("mean background image", h_bgimage);
cv::waitKey(0);
if (waitKey(1) == 'q')
break;
}
return 0;
}
2. GMG 背景相减法
- GMG算法的名称源自该算法发明人的首字母,这个算法结合了背景估计与贝叶斯图像分割,使用贝叶斯推断将背景与前景分离,还使用帧的历史来建模
- 它在此基于帧的时间序列进行加权,新的观测比旧的观测的权重还要高
- 实现代码如下:
#include <iostream>
#include <string>
#include "opencv2/opencv.hpp"
#include "opencv2/cudabgsegm.hpp"
#include "opencv2/cudalegacy.hpp"
using namespace std;
using namespace cv;
using namespace cv::cuda;
int main(
)
{
VideoCapture cap("images/abc.avi");
if (!cap.isOpened())
{
cerr << "can not open video file" << endl;
return -1;
}
Mat frame;
cap.read(frame);
GpuMat d_frame;
d_frame.upload(frame);
Ptr<BackgroundSubtractor> gmg = cuda::createBackgroundSubtractorGMG(40);
GpuMat d_fgmask, d_fgimage, d_bgimage;
Mat h_fgmask, h_fgimage, h_bgimage;
gmg->apply(d_frame, d_fgmask);
while (1)
{
cap.read(frame);
if (frame.empty())
break;
d_frame.upload(frame);
int64 start = cv::getTickCount();
gmg->apply(d_frame, d_fgmask, 0.01);
double fps = cv::getTickFrequency() / (cv::getTickCount() - start);
std::cout << "FPS : " << fps << std::endl;
d_fgimage.create(d_frame.size(), d_frame.type());
d_fgimage.setTo(Scalar::all(0));
d_frame.copyTo(d_fgimage, d_fgmask);
d_fgmask.download(h_fgmask);
d_fgimage.download(h_fgimage);
namedWindow("image", 0);
namedWindow("foreground mask", 0);
namedWindow("foreground image", 0);
imshow("image", frame);
imshow("foreground mask", h_fgmask);
imshow("foreground image", h_fgimage);
if (waitKey(30) == 'q')
break;
}
return 0;
}