1、VIBE思想:

为每个像素点存储了一个样本集,样本集中采样值就是该像素点过去的像素值和其邻居点的像素值,然后将每一个新的像素值和样本集进行比较来判断是否属于背景点。

2、VIBE模型初始化

通用的检测算法的初始化,需要一定长度的视频序列来完成,需要耗费数秒时间;VIBE只需要一帧图像即可。ViBe初始化就是填充像素的样本集的过程但是由于在一帧图像中不可能包含像素点的时空分布信息,我们利用了相近像素点拥有相近的时空分布特性,具体来讲就是:对于一个像素点,随机的选择它的邻居点的像素值作为它的模型样本值。这种初始化方法优点是对于噪声的反应比较灵敏,计算量小速度快,可以很快的进行运动物体的检测,缺点是容易引入Ghost区域。

3、VIBE模型更新策略

保守策略+前景点计数

保守策略:如果初始检测为前景像素,那么就一直认为是前景像素

前景点计数:对像素点进行统计,如果被标记为前景像素的次数>阈值,则认为是前景点

借鉴大牛人的代码运行、调试:

main.cpp

// This is based on
// "VIBE: A POWERFUL RANDOM TECHNIQUE TO ESTIMATE THE BACKGROUND IN VIDEO SEQUENCES"
// by Olivier Barnich and Marc Van Droogenbroeck
// Author : zouxy
// Date : 2013-4-13
// HomePage : http://blog.csdn.net/zouxy09
// Email : zouxy09@qq.com #include "ViBe.h"
#include <opencv2/video/video.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <iostream> using namespace cv;
using namespace std; int main(int argc, char* argv[])
{
Mat frame, gray, mask;
VideoCapture capture("C:\\TEST\\opencv\\car.avi");
if (!capture.isOpened())
{
cout << "No camera or video input!\n" << endl;
return -;
} ViBe_BGS Vibe_Bgs;
int count = ; while ()
{
count++;
capture >> frame;
if (frame.empty())
break;
cvtColor(frame, gray, CV_RGB2GRAY); if (count == )
{
cout << "row=" << frame.rows << " " << "cols=" << frame.cols << endl;
Vibe_Bgs.init(gray);
Vibe_Bgs.processFirstFrame(gray);
cout << " Training GMM complete!" << endl;
}
else
{
Vibe_Bgs.testAndUpdate(gray);
mask = Vibe_Bgs.getMask();
morphologyEx(mask, mask, MORPH_OPEN, Mat());
imshow("mask", mask);
} imshow("input", frame); if (cvWaitKey() == 'q')
break;
} return ;
}

ViBe.cpp

#include <opencv2/opencv.hpp>
#include <iostream>
#include "ViBe.h" using namespace std;
using namespace cv; int c_xoff[] = { -, , , -, , -, , , }; //x的邻居点
int c_yoff[] = { -, , , -, , -, , , }; //y的邻居点 ViBe_BGS::ViBe_BGS(void)
{ }
ViBe_BGS::~ViBe_BGS(void)
{ } /**************** Assign space and init ***************************/
void ViBe_BGS::init(const Mat _image)
{
for (int i = ; i < NUM_SAMPLES; i++)
{
m_samples[i] = Mat::zeros(_image.size(), CV_8UC1);//初始化每个像素点有20个样本像素点的存储值0
}
m_mask = Mat::zeros(_image.size(), CV_8UC1);
m_foregroundMatchCount = Mat::zeros(_image.size(), CV_8UC1);//
} /**************** Init model from first frame ********************/
void ViBe_BGS::processFirstFrame(const Mat _image)
{
RNG rng;
int row, col; for (int i = ; i < _image.rows; i++)
{
for (int j = ; j < _image.cols; j++)
{
for (int k = ; k < NUM_SAMPLES; k++)
{
// Random pick up NUM_SAMPLES pixel in neighbourhood to construct the model
int random = rng.uniform(, ); row = i + c_yoff[random];//修正随机值
if (row < )
row = ;
if (row >= _image.rows)
row = _image.rows - ; col = j + c_xoff[random];//修正随机值
if (col < )
col = ;
if (col >= _image.cols)
col = _image.cols - ; m_samples[k].at<uchar>(i, j) = _image.at<uchar>(row, col);//随机抽取20次该像素点周围的像素点,做为样本像素点
}
}
}
} /**************** Test a new frame and update model ********************/
void ViBe_BGS::testAndUpdate(const Mat _image)
{
RNG rng; for (int i = ; i < _image.rows; i++)
{
for (int j = ; j < _image.cols; j++)
{
int matches(), count();
float dist; while (matches < MIN_MATCHES && count < NUM_SAMPLES)//两者都满足的话就继续循环,只要有一个不满足就中断循环
{
dist = abs(m_samples[count].at<uchar>(i, j) - _image.at<uchar>(i, j));//20个样本点
if (dist < RADIUS)
matches++;
count++;
} if (matches >= MIN_MATCHES)
{
// It is a background pixel
m_foregroundMatchCount.at<uchar>(i, j) = ;//background pixel=0;It is black; // Set background pixel to 0
m_mask.at<uchar>(i, j) = ; // 如果一个像素是背景点,那么它有 1 / defaultSubsamplingFactor 的概率去更新自己的模型样本值
int random = rng.uniform(, SUBSAMPLE_FACTOR);
if (random == )
{
random = rng.uniform(, NUM_SAMPLES);
m_samples[random].at<uchar>(i, j) = _image.at<uchar>(i, j);
} // 同时也有 1 / defaultSubsamplingFactor 的概率去更新它的邻居点的模型样本值
random = rng.uniform(, SUBSAMPLE_FACTOR);
if (random == )
{
int row, col;
random = rng.uniform(, );
row = i + c_yoff[random];
if (row < )
row = ;
if (row >= _image.rows)
row = _image.rows - ; random = rng.uniform(, );
col = j + c_xoff[random];
if (col < )
col = ;
if (col >= _image.cols)
col = _image.cols - ; random = rng.uniform(, NUM_SAMPLES);
m_samples[random].at<uchar>(row, col) = _image.at<uchar>(i, j);
}
}
else
{
// It is a foreground pixel
m_foregroundMatchCount.at<uchar>(i, j)++; // Set background pixel to 255
m_mask.at<uchar>(i, j) = ; //如果某个像素点连续N次被检测为前景,则认为一块静止区域被误判为运动,将其更新为背景点
if (m_foregroundMatchCount.at<uchar>(i, j) > )
{
int random = rng.uniform(, SUBSAMPLE_FACTOR);
if (random == )
{
random = rng.uniform(, NUM_SAMPLES);
m_samples[random].at<uchar>(i, j) = _image.at<uchar>(i, j);
}
}
}
}
}
}

ViBe.h

#pragma once
#include <iostream>
#include "opencv2/opencv.hpp" using namespace cv;
using namespace std; #define NUM_SAMPLES 20 //每个像素点的样本个数
#define MIN_MATCHES 2 //#min指数
#define RADIUS 20 //Sqthere半径
#define SUBSAMPLE_FACTOR 16 //子采样概率 class ViBe_BGS
{
public:
ViBe_BGS(void);
~ViBe_BGS(void); void init(const Mat _image); //初始化
void processFirstFrame(const Mat _image);
void testAndUpdate(const Mat _image); //更新
Mat getMask(void){ return m_mask; }; private:
Mat m_samples[NUM_SAMPLES];
Mat m_foregroundMatchCount;
Mat m_mask;
};

实验测试如上图,存在的问题:

1、在input窗口中并没有A,mask窗口中A是黑色车前几帧造成的,这说明A这部分消失的太慢了,就是模型数据更新的慢了点。也可以说是VIBE的最大缺点,容易进入Ghost区。

2、B 处是白色小车的影子造成的,所以VIBE算法没有做影子消除。

3、D处检测的数据有点乱

还需要做很多优化和测试工作!

VIBE(前景检测)的更多相关文章

  1. [转]前景检测算法--ViBe算法

    原文:http://blog.csdn.net/zouxy09/article/details/9622285 转自:http://blog.csdn.net/app_12062011/article ...

  2. 运动检测(前景检测)之(一)ViBe

    运动检测(前景检测)之(一)ViBe zouxy09@qq.com http://blog.csdn.net/zouxy09 因为监控发展的需求,目前前景检测的研究还是很多的,也出现了很多新的方法和思 ...

  3. ViBe(Visual Background extractor)背景建模或前景检测

    ViBe算法:ViBe - a powerful technique for background detection and subtraction in video sequences 算法官网: ...

  4. 运动检测(前景检测)之(二)混合高斯模型GMM

    运动检测(前景检测)之(二)混合高斯模型GMM zouxy09@qq.com http://blog.csdn.net/zouxy09 因为监控发展的需求,目前前景检测的研究还是很多的,也出现了很多新 ...

  5. [转]运动检测(前景检测)之(二)混合高斯模型GMM

    转自:http://blog.csdn.net/zouxy09/article/details/9622401 因为监控发展的需求,目前前景检测的研究还是很多的,也出现了很多新的方法和思路.个人了解的 ...

  6. 目标检测之vibe---ViBe(Visual Background extractor)背景建模或前景检测

    ViBe算法:ViBe - a powerful technique for background detection and subtraction in video sequences 算法官网: ...

  7. [综]前景检测GMM

    tornadomeet 前景检测算法_4(opencv自带GMM) http://www.cnblogs.com/tornadomeet/archive/2012/06/02/2531705.html ...

  8. paper 83:前景检测算法_1(codebook和平均背景法)

    前景分割中一个非常重要的研究方向就是背景减图法,因为背景减图的方法简单,原理容易被想到,且在智能视频监控领域中,摄像机很多情况下是固定的,且背景也是基本不变或者是缓慢变换的,在这种场合背景减图法的应用 ...

  9. 运动目标前景检测之ViBe源代码分析

    一方面为了学习,一方面按照老师和项目的要求接触到了前景提取的相关知识,具体的方法有很多,帧差.背景减除(GMM.CodeBook. SOBS. SACON. VIBE. W4.多帧平均……).光流(稀 ...

随机推荐

  1. Python第1天

    今天主要学习内容如下: 概论,各种开发语言的对比,高级语言包括:python(开发效率高,执行效率低) Java(开发效率低,执行效率高),PHP,低级语言包括:C语言,汇编语言: Python 语言 ...

  2. django 的model是如何把字段加入到meta中的

    def contribute_to_class(self, cls, name): self.set_attributes_from_name(name) self.model = cls cls._ ...

  3. Object.defineProperty(o,p,descriptor ) 理解应用

    1. Object.defineProperty  在一个对象上定义一个新属性,或修改一个已经存在的属性, 最终返回这个对象. var __define = this.__define || func ...

  4. 深度学习VS机器学习——到底什么区别

    转自:https://baijiahao.baidu.com/s?id=1595509949786067084&wfr=spider&for=pc 最近在听深度学习的课,老师提了一个基 ...

  5. Linux下MySQL5.7.18 yum方式从卸载到安装

    本文出处:http://www.cnblogs.com/wy123/p/6932166.html 折腾了大半天,看了想,想了看,总算是弄清楚yum安装的过程了,之前写过二进制包安装的,这里用yum安装 ...

  6. oracle数据库中存储过程使用MD5算法加密

    一.技术点 1. DBMS_OBFUSCATION_TOOLKIT.MD5 DBMS_OBFUSCATION_TOOLKIT.MD5是MD5编码的数据包函数,但偶在使用select DBMS_OBFU ...

  7. 安装SourceTree工具,无需注册就可以正常使用SourceTree

    1. 下载SourceTree安装包 2. 双击安装包进行安装,默认会直接安装在系统盘,此时桌面就会SourceTree的快捷键 3. 双击打开桌面的SourceTree,就会提示让你安装授权,那么接 ...

  8. 浅析AnyCast网络技术

    什么是BGP AnyCast? BGP anycast就是利用一个(多个) as号码在不同的地区广播相同的一个ip段.利用bgp的寻路原则,短的as path 会选成最优路径(bgp寻路原则之n),从 ...

  9. Linux - 操作系统的发展史

    操作系统的发展史(科普章节) 目标 了解操作系统的发展历史 知道 Linux 内核及发行版的区别 知道 Linux 的应用领域 01. 操作系统的发展历史 1.1 Unix 1965 年之前的时候,电 ...

  10. python--第十天总结(Select/Poll/Epoll使用 )

    首先列一下,sellect.poll.epoll三者的区别 select select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监视多个文件描述符的数组,当select ...