目录
一、c++ opencv 背景减除算法内置算法
1.1 MOG2算法
1.2 KNN算法
二、完整案例实现
2.1 程序代码
2.2 程序编译及输出
一、c++ opencv 背景减除算法内置算法
背景减除算法的目标是将视频帧中的背景与前景(通常是移动的对象)分离。OpenCV提供MOG2(Gaussian Mixture-based Background/Foreground Segmentation)和KNN(K-Nearest Neighbors)等背景减除算法,他们都派生于BackgroundSubtractor,各派生类需要重写父类的apply函数。
CV_WRAP virtual void apply(InputArray image, OutputArray fgmask, double learningRate=-1) = 0;
这些内置算法,来自video模块的modules\video\include\opencv2\video\background_segm.hpp。
1.1 MOG2算法
BackgroundSubtractorMOG2
是基于高斯混合模型(Gaussian Mixture Model, GMM)的背景减除算法。它适用于处理具有动态背景的场景,如对于缓慢变化的光照条件和动态背景(如摇曳的树叶或水面波纹)也具有一定的鲁棒性。
apply()
函数是BackgroundSubtractorMOG2
类的一个重写父类BackgroundSubtractor的成员函数,它接受一个输入帧(frame
),并输出一个前景掩模(fgMaskMOG2
)。前景掩模是一个灰度图像,其中背景像素接近黑色(值接近0),而前景(移动的对象)像素则更亮(值接近255)。
1.2 KNN算法
BackgroundSubtractorKNN
是基于K近邻(K-Nearest Neighbors, KNN)算法的背景减除器。这种算法对于处理突然的光照变化或复杂的动态背景可能更为有效。
与BackgroundSubtractorMOG2
的示例类似。apply()
函数是BackgroundSubtractorKNN
类的一个重写父类BackgroundSubtractor的成员函数,它接受一个输入帧(frame
),并输出一个前景掩模(fgMaskKNN
)。前景掩模是一个灰度图像,其中背景像素接近黑色(值接近0),而前景(移动的对象)像素则更亮(值接近255)。
BackgroundSubtractorKNN
类有几个可以调整的参数,如nframes
(用于算法训练的初始帧数)、dist2Threshold
(前景检测中的距离阈值)等。这些参数可以通过setNFrames()
、setDist2Threshold()
等成员函数进行设置。
二、完整案例实现
2.1 程序代码
main.cpp代码,先读取一段视频或打开摄像头,并创建一个BackgroundSubtractorMOG2
实例或BackgroundSubtractorKNN实例
。然后,在读取视频帧的循环中,使用apply()
方法将当前帧与背景模型进行比较,并生成一个前景掩模(fgMask
)。这个掩模是一个与输入帧相同大小的灰度图像,其中背景像素接近黑色(值接近0),而前景像素则更亮(值接近255)。
#include <opencv2/opencv.hpp>
#include <vector>
#include <iostream>
int main(int argc, char* argv[])
{
cv::VideoCapture capture; // 视频捕获对象
if(argc< 2){
capture.open(0); //0是摄像头的索引
}else{
// 加载视频
capture.open(argv[1]); //如果是视频文件,则传入文件路径
}
// cv::VideoCapture capture(0); // 0是摄像头的索引,如果是视频文件,则传入文件路径
if (!capture.isOpened()) {
std::cerr << "Error opening video stream or file" << std::endl;
return -1;
}
// 创建背景减除器对象
cv::Ptr<cv::BackgroundSubtractorMOG2> pBackSub = cv::createBackgroundSubtractorMOG2();
// cv::Ptr<cv::BackgroundSubtractorKNN> pBackSub = cv::createBackgroundSubtractorKNN();
cv::Mat frame, fgMask;
while (capture.read(frame)) {
if (frame.empty())
break;
// 应用背景减除
pBackSub->apply(frame, fgMask);
// 可选:进行一些形态学操作来去除噪声
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3));
morphologyEx(fgMask, fgMask, cv::MORPH_OPEN, kernel);
// 显示结果
imshow("Frame", frame);
imshow("FG Mask", fgMask);
// 对检测图像进行判断
char c = (char) cv::waitKey(30);
if (c == 27) break; // 按ESC退出
}
capture.release();
cv::destroyAllWindows();
return 0;
}
2.2 程序编译及输出
本文是采用win系统下,opencv采用MinGW编译的静态库(C/C++开发,win下OpenCV+MinGW编译环境搭建_opencv mingw-CSDN博客),建立makefile:
#/bin/sh
#win32
CX= g++ -DWIN32
#linux
#CX= g++ -Dlinux
BIN := ./
TARGET := Motion_detection.exe
FLAGS := -std=c++11 -static
SRCDIR := ./
#INCLUDES
INCLUDEDIR := -I"../../opencv_MinGW/include" -I"./"
#-I"$(SRCDIR)"
staticDir := ../../opencv_MinGW/x64/mingw/staticlib/
#LIBDIR := $(staticDir)/libopencv_world460.a\
# $(staticDir)/libade.a \
# $(staticDir)/libIlmImf.a \
# $(staticDir)/libquirc.a \
# $(staticDir)/libzlib.a \
# $(wildcard $(staticDir)/liblib*.a) \
# -lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid
#opencv_world放弃前,然后是opencv依赖的第三方库,后面的库是MinGW编译工具的库
LIBDIR := -L $(staticDir) -lopencv_world460 -lade -lIlmImf -lquirc -lzlib \
-llibjpeg-turbo -llibopenjp2 -llibpng -llibprotobuf -llibtiff -llibwebp \
-lgdi32 -lComDlg32 -lOleAut32 -lOle32 -luuid
source := $(wildcard $(SRCDIR)/*.cpp)
$(TARGET) :
$(CX) $(FLAGS) $(INCLUDEDIR) $(source) -o $(BIN)/$(TARGET) $(LIBDIR)
clean:
rm $(BIN)/$(TARGET)
编译如下:
程序运行输出如下,本测试没有指定视频图像,采用笔记本的摄像头抓取视频:
PS:读者可以调整参数、图像光影效果等验证测试BackgroundSubtractorKNN方法。