本文为原创,转载请表明出处,谢谢!
BackgroundSubtractorMOG2是以高斯混合模型为基础的背景/前景分割算法。它是以2004年和2006年Z.Zivkovic的两篇文章为基础的。这个算法的一个特点是它为每一个像素选择一个合适数目的高斯分布。(上一个方法中我们使用是K高斯分布)。这样就会对由于亮度等发生变化引起的场景变化产生更好的适应。和前面一样我们需要创建一个背景对象。但在这里我们我们可以选择是否检测阴影。如果detectShadows = True(默认值),它就会检测并将影子标记出来,但是这样做会降低处理速度。影子会被标记为灰色。
这里我们采用opencv实现视频追踪,对于opencv的安装、配置和使用,网上有很多教程,我们这里就不在说明。如果你对opencv不太了解,请自行查资料学习。话归正题,这里我将会分别从Python和c++实现BackgroundSubtractorMOG2,我使用的是opencv3.1linux版本。
Python代码:
import numpy as np
import cv2
import time
import datetime
cap = cv2.VideoCapture(0)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
fgbg = cv2.createBackgroundSubtractorMOG2()
fourcc = cv2.VideoWriter_fourcc(*'XVID')
frame1 = np.zeros((640,480))
out = cv2.VideoWriter(datetime.datetime.now().strftime("%A_%d_%B_%Y_%I_%M_%S%p")+'.avi',fourcc, 5.0, np.shape(frame1))
while(1):
ret, frame = cap.read()
fgmask = fgbg.apply(frame)
(_,cnts, _) = cv2.findContours(fgmask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
maxArea = 0
for c in cnts:
Area = cv2.contourArea(c)
if Area < maxArea :
#if cv2.contourArea(c) < 500:
(x, y, w, h) = (0,0,0,0)
continue
else:
if Area < 1000:
(x, y, w, h) = (0,0,0,0)
continue
else:
maxArea = Area
m=c
(x, y, w, h) = cv2.boundingRect(m)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
out.write(frame)
cv2.imshow('frame',frame)
k = cv2.waitKey(30)&0xff
if k==27:
break
out.release()
cap.release()
cv2.destoryAllWindows()
c++版本:
VideoDetect.h
#pragma once
#include
#include
using namespace std;
using namespace cv;
enum VIDEOTYPE
{
CAMERAVIDEO/*摄像头*/,FILEVIDEO/*视频*/
};
class MOG2Detector
{
public:
MOG2Detector();
~MOG2Detector();
/*
VIDEOTYPE 指定摄像头或者文件
path 文件路径
WindowName opencv可视化窗口名称
*/
MOG2Detector(VIDEOTYPE type,char * path = "E:/image/s.avi",char * WindowName = "Video");
//开始
void startDecect();
private:
char * WinName;
VIDEOTYPE VideoType;
cv::VideoCapture capture;
cv::Ptr fgbg;
};
VideoDetect.cpp:
#include "stdafx.h"
#include "MOG2Detector.h"
MOG2Detector::MOG2Detector()
{
}
MOG2Detector::~MOG2Detector()
{
}
MOG2Detector::MOG2Detector(VIDEOTYPE type, char * path, char * WindowName)
{
if (type == CAMERAVIDEO)
{
capture.open(0);
}
else if (type == FILEVIDEO)
{
capture.open("E:/image/s.avi");
}
else
{
cout << "Type is error, you can input CAMERAVIDEO or FILEVIDEO" << endl;
return;
}
if (!capture.isOpened())
{
std::cout << "video camera capture open fail! \n" << std::endl;
exit(1);
}
fgbg = cv::createBackgroundSubtractorMOG2();
WinName = WindowName;
}
void MOG2Detector::startDecect()
{
cv::Mat frame, fgmask;
//cnts存储边缘信息
std::vector<std::vector > cnts;
cv::namedWindow("video", 1);
while (1)
{
capture.read(frame);
fgbg->apply(frame, fgmask);
//检测每一帧边缘
findContours(fgmask, cnts, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
float Area;
Rect rect;
vector m;
for (int i = cnts.size() - 1; i >= 0; i--)
{
vector c = cnts[i];
//获取面积
Area = contourArea(c);
if (Area < 50)//50这个值根据需求设定,这里指的是目标的大小
{
continue;
}
else
{
m = c;
}
rect = boundingRect(m);
rectangle(frame, rect, Scalar(0, 255, 0), 2);
}
resize(frame, frame, Size(480, 320));
imshow("video", frame);
char c = waitKey(33);
if (c == 27)
break;
}
//释放资源
capture.release();
cv::destroyWindow("video");
}