ViBe检测方法

  • 算法简介
    • 1.背景模型的初始化
    • 2.前景检测过程
    • 3.背景模型的更新方法
  • Vibe算法优缺点
  • Vibe代码

算法简介

  该算法采用邻域像素来创建背景模型,通过比对背景模型和当前输入像素值来检测前景。总的来说就是先背景建模,后前景检测的背景差方法。
  具体的思想就是为每个像素点存储了一个样本集,样本集中采样值就是该像素点过去的像素值和其邻居点的像素值,然后将每一个新的像素值和样本集进行比较来判断是否属于背景点。
  vibe算法可以分为以下三个步骤。

1.背景模型的初始化

  初始化单帧图像中每个像素点的背景模型。假设每一个像素和其邻域像素的像素值在空域上有相似的分布。基于这种假设,每一个像素模型都可以用其邻域中的像素来表示。为了保证背景模型符合统计学规律,邻域的范围要足够大。
  对于一个像素点,随机的选择它的邻居点的像素值作为它的模型样本值。M0(x)=v0(y|y∈NG(x)),t=0初始时刻,NG(x)即为邻居点 。

2.前景检测过程

  对后续的图像序列进行前景目标分割操作。
背景模型为每个背景点存储一个样本集,然后每个新的像素值和样本集比较判断是否属于背景。像素点(x,y)的背景模型为,像素值为。按照下面判断该像素值是否为前景。

这里上标r是随机选的;T是预先设置好的阈值。当  
满足符合背景#N次时,我们认为像素点    为背景,否则为前景。

3.背景模型的更新方法

  ViBe算法的更新在时间和空间上都具有随机性。时间上的随机性。在N个背景模型中随机抽取一个,设为图像Pg。当我们得到新的一帧图像Pt时,如果图像Pt中的x位置对应的像素Pt(x)被判断为背景,则Pg需要被更新。这个抽取的过程体现了时间上的随机性。空间上的随机性。在Pg(x)的八邻域中随机抽取一个像素Pg(r),用Pg(r)的来替换掉Pg(x),这体现了模型更新空间上的随机性。

Vibe算法优缺点

优点:

  • 内存占用少,一个像素需要作一次比较,占用一个字节的内存;
  • 无参数法;
  • 性能优于混合高斯,参数化方法,SACON等;
  • 像素级算法,视频处理中的预处理关键步骤;
  • 背景模型及时初始化;
  • 具有较好的抗噪能力;
  • 在背景建模中,不仅减少了背景模型建立的过程,还可以处理背景突然变化的情况,当检测到背景突然变化明显时,只需要舍弃原始的模型,重新利用变化后的首帧图像建立背景模型;
  • 在背景模型更新中,采用八邻域更新的方法,可以去除由于获取的视频细微抖动(摄像机抖动、目标微动)而产生的重影和误差,让检测目标更加准确。

缺点:

  • 在背景建模中,由于可能采用了运动物体的像素初始化样本集,容易引入Ghost区域(拖影、鬼影区域)(Ghost区域也就是指当一个原本静止的物体开始运动,背景差检测算法可能会将原来该物体所覆盖的区域错误的检测为运动的,这块区域就成为Ghost,当然原来运动的物体变为静止的也会引入Ghost区域,Ghost区域在检测中必须被尽快的消除。)Ghost区域如下图所示;

  • 静止目标问题,长时间驻留未运动,该人物运动目标逐渐被背景吸收。

  • 阴影前景问题,阴影的存在导致检测出来的运动目标形状不准确,影响后续目标分类、跟踪、识别和分析等其他智能视频处理模块。产生阴影前景问题的根源是:光线被运动目标前景遮挡,投射阴影区的颜色比背景的颜色暗,即阴影和背景颜色值的距离相差较大,背景差分后被误检为运动目标前景。

  • 运动目标不完整问题,运动目标通常可分为非刚性物体和刚性物体,人属于非刚性物体,车属于刚性物体,这两种常见检测对象的检测结果都出现了不完整现象。

Vibe代码

Vibe.h头文件

#include<iostream>
#include<cstdio>
#include<opencv2/opencv.hpp>using namespace cv;
using namespace std;//每个像素点的样本个数默认值
#define DEFAULT_NUM_SAMPLES 20//#min指数默认值
#define DEFAULT_MIN_MATCHES 2//Sqthere半径默认值
#define DEFAULT_RADIUS 20//子采样概率默认值
#define DEFAULT_RANDOM_SAMPLE 16class ViBe
{public:ViBe(int num_sam = DEFAULT_NUM_SAMPLES,int min_match = DEFAULT_MIN_MATCHES,int r = DEFAULT_RADIUS,int rand_sam = DEFAULT_RANDOM_SAMPLE);~ViBe(void);//背景模型初始化void init(Mat img);//处理第一帧图像void ProcessFirstFrame(Mat img);//运行ViBe算法,提取前景区域并更新背景模型样本库void Run(Mat img);//获取前景模型二值图像Mat getFGModel();//删除样本库void deleteSamples();//x的邻居点int c_xoff[9];//y的邻居点int c_yoff[9];private://样本库unsigned char*** samples;//前景模型二值图像Mat FGModel;//每个像素点的样本个数int num_samples;//#min指数int num_min_matches;//Sqthere半径int radius;//子采样概率int random_sample;};
#pragma once

Vibe.cpp

#include"Vibe.h"
/*
构造函数ViBe
参数:
int num_sam:每个像素点的样本个数
int min_match:#min 指数
int r: Sqthere 半径
int rand_sam:子采样概率
*/ViBe::ViBe(int num_sam, int min_match, int r, int rand_sam)
{num_samples = num_sam;num_min_matches = min_match;radius = r;random_sample = rand_sam;int c_off[9] = { -1,0,1,-1,1,-1,0,1,0 };for (int i = 0; i < 9; i++) {c_xoff[i] = c_yoff[i] = c_off[i];}
}/*析构函数:~ViBe说明:释放样本库内存
*/ViBe::~ViBe(void)
{deleteSamples();
}/*函数名init说明:背景模型初始化为样本库分配空间参数:Mat img:源图像返回值:void
*/void ViBe::init(Mat img)
{//动态分配三维数组,samples[][][num_samples]存储前景被连续检测的次数//samples = new unsigned char**[img.rows];for (int i = 0; i < img.rows; i++){samples[i] = new uchar *[img.cols];for (int j = 0; j < img.cols; j++){//数组中,在num_samples之外多增加的一个值,用于统计该像素点连续成为前景的次数samples[i][j] = new uchar[num_samples + 1];for (int k = 0; k < num_samples + 1; k++){//创建样本库是,所有样本全部初始化为0samples[i][j][k] = 0;}}}FGModel = Mat::zeros(img.size(), CV_8UC1);
}
/*函数名 ProcessFirstFrame说明:处理第一帧图像读取视频序列第一帧,并随机选取像素点邻域内像素填充样本库,初始化背景模型参数:Mat img:源图像返回值:void*/void ViBe::ProcessFirstFrame(Mat img)
{RNG rng;int row, col;for (int i = 0; i < img.rows; i++){for (int j = 0; j < img.cols; j++){for (int k = 0; k < num_samples; k++){//随机选择num_samples个邻域像素点,构建背景模型int random;random = rng.uniform(0, 9); row = i + c_yoff[random];random = rng.uniform(0, 9); col = j + c_xoff[random];//防止选取的像素点越界if (row < 0)row = 0;if (row >= img.rows)row = img.rows - 1;if (col < 0)col = 0;if (col >= img.cols)col = img.cols - 1;//为样本库赋值随机值samples[i][j][k] = img.at<uchar>(row, col);}}}
}/*
函数名:Run
说明:运行ViBe算法,提取前景区域并更新背景模型样本库
参数:
Mat img 源图像
返回值:void*/void ViBe::Run(Mat img)
{RNG rng;int k = 0, dist = 0, matches = 0;for (int i = 0; i < img.rows; i++){for (int j = 0; j < img.cols; j++){//前景提取//说明:计算当前像素值与样本库的匹配情况//参数://int matches:当前像素值与   样本库中值之差小于阈值范围RADIUS的个数//int count: 遍历样本库的缓存变量for (k = 0, matches = 0; matches < num_min_matches && k < num_samples; k++){dist = abs(samples[i][j][k] - img.at<uchar>(i, j));if (dist < radius)matches++;}//说明:当前像素值与样本库中值匹配次数较高,则认为是背景像素点;//此时更新前景统计次数、更新前景模型、更新该像素模型样本值、更新该像素点邻域像素点if (matches >= num_min_matches){//已经认为是背景像素,故该像素前景统计次数置0samples[i][j][num_samples] = 0;//该像素点的前景模型像素值置0FGModel.at<uchar>(i, j) = 0;}//说明:当前像素值与样本库中值匹配次数较低,则认为是前景像素点//此时需要更新前景统计次数,判断更新前景模型else {//已经认为是前景像素,故该像素的前景统计次数+1samples[i][j][num_samples]++;//该像素点的前景模型像素值置255FGModel.at<uchar>(i, j) = 255;//如果某个像素点连续50次被检测为前景,则认为一块静止区域被误判为运动,将其更新为背景点if (samples[i][j][num_samples] > 50){int random = rng.uniform(0, num_samples);samples[i][j][random] = img.at<uchar>(i, j);}}//更新模型样本库if (matches >= num_min_matches){//已经认为该像素是背景像素,那么它有1/φ的概率去更新自己的模型样本值int random = rng.uniform(0, random_sample);if (random == 0){random = rng.uniform(0, num_samples);samples[i][j][random] = img.at<uchar>(i, j);}//同时也有1/φ的概率去更新它的邻居点的模型样本值random = rng.uniform(0, random_sample);if (random == 0){int row, col;random = rng.uniform(0, 9); row = i + c_yoff[random];random = rng.uniform(0, 9); col = j + c_xoff[random];//防止选取的像素点越界if (row < 0)row = 0;if (row >= img.rows)row = img.rows - 1;if (col < 0)col = 0;if (col >= img.cols)col = img.cols - 1;//为样本库赋值随机值random = rng.uniform(0, num_samples);samples[row][col][random] = img.at<uchar>(i, j);}}}}
}/*
函数名 :getFGModel
说明:获取前景模型二值图像
返回值:Mat*/Mat ViBe::getFGModel()
{return FGModel;
}/*
函数名:deletesamples
说明:删除样本库
返回值:void*/void ViBe::deleteSamples()
{delete samples;
}

main.cpp


#include<opencv2/imgproc.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/types_c.h>
#include <opencv2/objdetect/objdetect.hpp>
#include "Vibe.h"int main(int argc, char* argv[])
{Mat frame, gray, FGModel;VideoCapture capture;capture = VideoCapture("E:/material/yaoyongde/test.avi");if (!capture.isOpened()){capture = VideoCapture("E:/material/yaoyongde/test.avi");if (!capture.isOpened()){capture = VideoCapture("E:/material/yaoyongde/test.avi");if (!capture.isOpened()){cout << "ERROR:Didn't find thid video!" << endl;return 0;}}}capture.set(CAP_PROP_FRAME_WIDTH, 160);capture.set(CAP_PROP_FRAME_HEIGHT, 120);if (!capture.isOpened()){cout << "No camera or video input!" << endl;return -1;}//程序运行时间统计变量double time;double start;ViBe vibe;bool count = true;while (1){capture >> frame;if (frame.empty())continue;cvtColor(frame, gray, CV_RGB2GRAY);if (count){vibe.init(gray);vibe.ProcessFirstFrame(gray);cout << "Training ViBe Success." << endl;count = false;}else{start = static_cast<double>(getTickCount());vibe.Run(gray);time = ((double)getTickCount() - start) / getTickFrequency() * 1000;cout << "Time of Update ViBe BAckground:" << time << "ms" << endl << endl;FGModel = vibe.getFGModel();imshow("FGModel", FGModel);}imshow("input", frame);if (waitKey(25) == 27)break;}return 0;
}

Vibe算法简介、优缺点、代码相关推荐

  1. PnP算法简介与代码解析-柴政

    PnP算法简介与代码解析-柴政 PnP求解算法是指通过多对3D与2D匹配点,在已知或者未知相机内参的情况下,利用最小化重投影误差来求解相机外参的算法.PnP求解算法是SLAM前端位姿跟踪部分中常用的算 ...

  2. 【计算机视觉】PnP算法简介与代码解析-柴政(solvepnp理论篇)

    PnP算法简介与代码解析-柴政 PnP求解算法是指通过多对3D与2D匹配点,在已知或者未知相机内参的情况下,利用最小化重投影误差来求解相机外参的算法.PnP求解算法是SLAM前端位姿跟踪部分中常用的算 ...

  3. ViBe算法原理和代码解析

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

  4. python运动物体检测_运动检测ViBe算法python实现代码

    运动物体检测一般分为背景建模和运动物体分析两步.即构建不包含运动物体的背景模型.然后将新的视频帧和背景模型对比,找出其中的运动物体.目前比较好的背景建模算法有两种:1)文章(Zivkovic Z. ( ...

  5. 支持向量机 SVM 算法推导优缺点 代码实现 in Python

    1.基本思想 前面讲到的Logistic Regression在拟合过程,实际上关注所有样本点的贡献,即寻找这么一个超平面,使得正例的特征远大于0,负例的特征远小于0,强调在全部训练数据上达到这一目标 ...

  6. CSK跟踪算法简介及代码的解读

    (Exploiting the Circulant Structure of Tracking-by-detection with Kernels)Csk算法通过使用高斯核计算相邻两帧之间的相关性,取 ...

  7. 背景提取算法——帧间差分法、背景差分法、ViBe算法、ViBe+算法

    背景提取是在视频图像序列中提取出背景,背景就是场景中静止不动的景物.因为摄像机不动,因此图像中的每个像素点都有一个对应的背景值,在一段时间内,这个背景值是比较固定的.背景提取的目标就是根据视频图像序列 ...

  8. 十大排序算法思想和代码总结(Python版)

    Table of Contents 一.概述 二.算法简介及代码展示 1.冒泡排序($O(n^2)$) 2.简单选择排序($O(n^2)$) 3.简单插入排序($O(n^2)$) 4.堆排序($O(n ...

  9. 背景建模--Vibe 算法优缺点分析

    背景建模--Vibe 算法优缺点分析 一.Vibe 算法的优点 Vibe背景建模为运动目标检测研究邻域开拓了新思路,是一种新颖.快速及有效的运动目标检测算法.其优点有以下两点: 1.思想简单,易于实现 ...

  10. CV之FD之HOG:图像检测之基于HOG算法、简介、代码实现(计算图像相似度)之详细攻略

    CV之FD之HOG:图像检测之基于HOG算法.简介.代码实现(计算图像相似度)之详细攻略 图像检测之基于HOG算法.简介.代码实现(计算图像相似度)之详细攻略 相关文章:CV之FD之HOG:图像检测之 ...

最新文章

  1. 英伟达官宣:CUDA 将不再支持 macOS
  2. P2P网络中DHT算法分析
  3. BZOJ 3720 [洛谷P2137] : Gty的妹子树
  4. Python中被双下划线包围的魔法方法
  5. 用java处理图片(压缩成小尺寸;加文字和logo水印)
  6. Listary Pro - 能极大幅度提高你 Windows 文件浏览与搜索速度效率的「超级神器」...
  7. C语言贪吃蛇 新手入门(超详细)
  8. linux安装moodle最新版,在linux下安装moodle
  9. 海马玩安卓模拟器linux,海马玩模拟器下载安装_海马玩模拟器Droid4X官方下载「手游模拟器」-太平洋下载中心...
  10. 4个团队领导必备的技能和素质
  11. js以索引形式遍历map对象
  12. Win10/Win11下图片扩展安装 HEVC/HEIF/CR2等
  13. 2022-7-8 Leetcode 904.水果成篮
  14. 别忽略国美之争的真正遗产
  15. mac使用u盘安装系统
  16. 德国短期(小于90天)学术访问签证经验申根签证
  17. 华为的笔试好难...
  18. 使用蒲公英来做iOS测试应用的分发 - 唐巧的技术博客
  19. Delete Top n-1 from a groud of records of a table
  20. Homebrew作者面试Google被拒,只因写不出一道算法题

热门文章

  1. 登录小米帐号怎么会显示服务器错误,小米官网登录不进去怎么办 小米官网无法登陆是怎么回事...
  2. meta分析stata教程
  3. 台式计算机打字标准手法,电脑打字技巧口诀
  4. C双拼输入法使用说明
  5. 【NOIP2017】李电下棋
  6. c语言素数环实验报告,c语言素数环问题实例讲解
  7. 华为手机所有图标变黑_华为手机字体白色变黑色 华为图标字体怎么变黑
  8. 人脸识别示例代码解析(二)——人脸识别解析
  9. H5商城与小程序商城哪个好_应该怎么选择_OctShop
  10. matlab最优化工具箱下载,matlab emd工具箱下载