BGSLibrary:A Background Subtraction Library
The BGSLibrary was developed by Andrews Sobral and provides an easy-to-use C++ framework based on OpenCV to perform background subtraction (BGS) in videos.
github介绍及下载地址 : https://github.com/andrewssobral/bgslibrary
现有30+种视频前景提取算法,不一定最优,但可以比较效果,准备研究其中部分。
第一次写,给出完整的头文件和main函数,以后仅给出要实现的算法
这次先实现 帧差法 (FrameDifferenceBGS) FrameDifference,总共4个文件
IBGS.h //IBGS是所有不同的视频前景提取算法的抽象类 ,我去掉其中saveConfig()和loadConfig()
FrameDifferenceBGS.h 帧差法
FrameDifferenceBGS.cpp
main.cpp //自己写的调用
文件名: IBGS.h
/*
This file is part of BGSLibrary.
BGSLibrary is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
BGSLibrary is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with BGSLibrary. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/imgproc/types_c.h>
#include <opencv2/highgui/highgui_c.h>
class IBGS
{
public:
virtual void process(const cv::Mat &img_input, cv::Mat &img_foreground, cv::Mat &img_background) = 0;
/*virtual void process(const cv::Mat &img_input, cv::Mat &img_foreground){
process(img_input, img_foreground, cv::Mat());
}*/
virtual ~IBGS(){}
private:
/*virtual void saveConfig() = 0;
virtual void loadConfig() = 0;*/
};
参考demo后自己写的main函数
main.cpp
#include <iostream>
#include "FrameDifferenceBGS.h"
#include "IBGS.h"
using namespace cv;
using namespace std;
#define resizedHeight 480
#define resizedWidth 600
#define VIDEOFILE "1.mp4"
#define frameTostart 20 //设置开始帧
string inputPath = "E:\\2paperCode\\testVideo\\Crossroad\\229\\";
int main(int argc, char* argv[])
{
VideoCapture capture(inputPath + VIDEOFILE);
if (!capture.isOpened())
{
cerr << "No video input\n" << endl;
return -1;
}
IBGS *bgsFDiff;
bgsFDiff = new FrameDifferenceBGS();//使用帧差法
int pause = 0;
Mat img_input;
Mat img_input_resized(resizedHeight, resizedWidth, CV_8UC3);
capture.set(CAP_PROP_POS_FRAMES, frameTostart);
FrameDifferenceBGS fdiff;
while (!pause)
{
capture >> img_input;
if (img_input.empty())
break;
resize(img_input, img_input_resized, img_input_resized.size());
namedWindow("input", WINDOW_NORMAL);
imshow("input", img_input_resized);
Mat img_mask;
Mat img_bkgmodel;
bgsFDiff->process(img_input, img_mask, img_bkgmodel);
// by default, it shows automatically the foreground mask image
if (cvWaitKey(10) == 'q')
pause = !pause;
}
delete bgsFDiff;
cvDestroyAllWindows();
capture.release();
return 0;
}
帧差法头文件,从 IBGS继承而来
FrameDifferenceBGS.h
#pragma once
#include <iostream>
#include <opencv2/opencv.hpp>
#include "IBGS.h"
class FrameDifferenceBGS : public IBGS
{
private:
bool firstTime;
cv::Mat img_input_prev;
cv::Mat img_foreground;
bool enableThreshold;
int threshold;
bool showOutput;
public:
FrameDifferenceBGS();
~FrameDifferenceBGS();
void process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel);
//private:
// void saveConfig();
// void loadConfig();
};
FrameDifferenceBGS.cpp
#include "FrameDifferenceBGS.h"
FrameDifferenceBGS::FrameDifferenceBGS() : firstTime(true), enableThreshold(true), threshold(15), showOutput(true)
{
std::cout << "FrameDifferenceBGS()" << std::endl;
}
FrameDifferenceBGS::~FrameDifferenceBGS()
{
std::cout << "~FrameDifferenceBGS()" << std::endl;
}
void FrameDifferenceBGS::process(const cv::Mat &img_input, cv::Mat &img_output, cv::Mat &img_bgmodel)
{
if (img_input.empty())
return;
enableThreshold = true;
threshold = 15;
showOutput = true;
if (img_input_prev.empty())
{
img_input.copyTo(img_input_prev);//前一帧为空时,将当前帧复制给前一帧
return;
}
cv::absdiff(img_input_prev, img_input, img_foreground);
if (img_foreground.channels() == 3)
cv::cvtColor(img_foreground, img_foreground, CV_BGR2GRAY);
if (enableThreshold)
cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
if (showOutput)
{
namedWindow("Frame Difference", cv::WINDOW_NORMAL);
cv::imshow("Frame Difference", img_foreground);
}
img_foreground.copyTo(img_output);
img_input.copyTo(img_input_prev);
firstTime = false;
}
PS:尽量使用 OpenCV 内置函数. 调用LUT 函数可以获得最快的速度. 这是因为OpenCV库可以通过英特尔线程架构启用多线程,下面的opencv矩阵操作均是优化的多线程并行处理,较高效
具体参考:快速对图像的像素进行操作 opencv 实战