写在最前

这是博主第一篇科技分享类的长文,其实有很多话想跟大家说,但是因为时间关系,不得不先写内容,想跟大家说的话就先放放吧,等有时间我会把这段话换成一篇博客,和大家一起分享科研中的点滴生活,以及博主推出本专栏的初衷,希望大家多多支持!!闲话不说,咱们开启正题~

目录

第一章: 算法效果

第二章: 算法解析
 2.1 算法目标

 2.2 算法原理
  2.2.1 样本建模
  2.2.2 分类操作:前景与背景
  2.2.3 更新策略:前景
  2.2.4 更新策略:背景

第三章: 代码分析
 3.1 样本建模

 3.2 判定策略与更新策略

 3.3 整体项目代码

1. 算法效果

               (备注:因为只是演示效果,我并没有详细的调整参数,演示效果不能完全代表算法效果)

文章原文:ViBE: A powerful random technique to estimate the background in video sequences

2. 算法解析

2.1 解决问题

首先我们先来聊聊ViBe算法是干啥的。ViBe(Visual Background Extractor)算法主要用来解决前景和背景的提取问题。你问我啥是前景?啥是背景?普通话解释一波:前景就是图像中你想要的部分,背景就是你不想要的部分。或者咱们这么说:动态区域提取,是不是更好理解一点?相似的算法比如帧间差分,高斯混合模型,光流法都是可以来解决这个问题的。图像中什么东西在动,我就提取什么东西~上图中的烟雾就是个例子。

2.2 算法原理

不论哪种算法,它需要解决的问题是唯一的:在一幅图像中找出哪些像素是我们想要的(前景),哪些是我们不想要的(背景),其本质就是一个二分类问题。 图像其实是一个巨大的矩阵,每一个矩阵元素代表了一个像素值。 ViBe算法是一个在灰度图像基础上进行计算的算法,也就是说,使用的图像信息是单通道灰度图像(像素值是0-255)。那么ViBe是如何通过灰度图实现这个二分类操作的呢?

2.2.1 样本建模

首先,ViBe需要对待检测的视频图像进行一个建模操作,我们来看这样的一个结构图:

上图中,蓝色大方块代表我们视频图像的 第一帧的灰度图;灰色大方块代表原始图像的 样本库,其数量为N,在论文原文中,这个数量被设定为20,这个样本库的本质我们可以理解为一幅一幅的灰度图片,共有20张,每一张大小尺寸完全和蓝色大方块相同;绿色的大方块代表一个 计数盘,其本质也可以理解为灰度图片,只不过每个像素代表的是计数器所记录的数据,尺寸和蓝色大方块相同(不理解没关系,下文会讲解);白色的大方块代表 结果模板,这个模板用来显示最终的检测结果,尺寸和蓝色大方块相同。直白来说,就是上文演示动画中的左侧图像,这个图像上只有像素值为0和255两种类型的像素点,即:二值化图像。

在第一帧这个蓝色大方块中有一个标记有*符号,位置为 (i,j) 的像素,我们记为A像素。我们就拿这一个像素来举例子,说明算法是如何对所有像素完成建模操作的(其他所有像素的建模操作和该像素相同)。

由于样本库中每一张图像的尺寸完全和蓝色大方块相同,所以数据库中每一张图像都有一个完全对应于A像素位置的像素点,我们记为Ai(i = 1~N)。图中A像素周围会有8个相邻的像素,上图中记为8个灰色的小方格。算法会从这共计9个像素中(8个邻域+本身)随机选择一个像素值赋予层数为 i(i = 1~N) 的Ai像素。通过循环执行这个操作N次,就会将N个样本图像中的所有Ai像素都赋予一个随机选取的像素值,我们将这个像素值记为Pi(i = 1~N) 这样就完成了一颗像素的建模操作。

在建模操作过程中,记数盘结果模板 的所有像素值均赋值为0,从视觉上讲,这两张图片被初始化成两张完全为黑色的图像。

总结来说,建模阶段ViBe算法主要完成了三件事情:

  1. 用第一帧图像的灰度信息填满样本库;
  2. 初始化一个全部为0的计数盘;
  3. 初始化一个全部为0的用来显示检测结果的二值图像模板;

至此,算法第一部分,图像的建模操作全部完成。

2.2.2 分类操作:前景与背景

其次,我们来说明算法是如何区分前景和背景的,如果像素不满足背景的条件,就会被定义为前景,反之亦然。在定义前景和背景的时候,算法引入了一个距离阈值来判定是否满足条件。这个东西的本质可以理解为像素值之差,我们看图说话:

我们依然拿 一个像素来举例子。上图中右侧灰色部分是在初始化阶段建立的样本库中Ai像素的像素值,在每一层样本的Ai点都有一个像素值即Pi, 算法以这些数据作为评价指标,计算与新来数据的距离。例如:目前要判断第二帧图像(i,j)位置的像素点是前景还是背景。

  1. 第一步,算法会将新来像素的像素值分别与1~N个样本库中的像素值进行相减,即循环执行图片右下角的公式(abs()函数代表绝对值函数),得到N个 Distance 数据。
  2. 第二步,设定 阈值1,称为半径阈值,记为R(这个数值在论文原文中为30),设定 阈值2,称为匹配阈值,记为M(这个数值在论文原文中为2)。将 阈值R 与第一步中所有的 Distance 循环比较。
  3. 第三步,如果 Distance < R 的次数 超过阈值M ,说明待判定的像素值与之前的像素值变化不大,距离不远,即定义该点为背景像素,不是动态区域。如果Distance < R 的次数 没有超过阈值M ,说明新来的像素值与之前的像素值差异较大,距离较远,即定义该点为前景像素。

总结来说,前景背景判定的方式就是 用新来的像素与之前的样本像素值做差,如果差的不多,说明变化不大,认为是背景,反之认为是前景。

至此,算法第二部分,前景与背景的判定操作全部完成。

2.2.3 更新策略:前景

接下来, 我们需要知道当确定当前像素为前景像素以后,需要做哪些后续的操作,以及如何维护样本库和计数盘。现假设 像素A 已经被确定为前景像素:

  1. 第一步,将A像素点在最终的检测结果上标记出来。在此,我们用到了2.2.1章节中提到的 结果模板,将 结果模板 上与当前像素A位置对应的像素点置为255,即白色点
  2. 第二步,将2.2.1章节中提到的 计数盘 中与当前像素A位置对应的像素点值+1;
  3. 第三步,判定 计数盘 上与当前像素A位置对应的像素点值,其本质是当前像素被判定程前景像素的次数。若该次数 >50(开源代码中的阈值设定为50次),则认为该点是静止物体被误检测成了动态物体,需要强制更新数据样本信息。

数据样本更新方式较为简单,一句话总结 就是把当前新输入图像的 像素A的像素值 随机的选择一张样本图像(样本图像一共有N个),赋予其对应位置的像素。举个例子,比如当前新输入图像位置为(i,j)的像素A,其像素值为200,通过随机的方式,选中了样本库中第2张样本进行更新,则将第二张样本图像上位于(i,j)的像素的像素值赋值为200。

2.2.4 更新策略:背景

现在我们来聊一聊另外一个分支, 当确定当前像素为背景以后,需要做哪些后续的操作,以及如何维护样本库和计数盘。现假设 像素A 已经被确定为背景像素:

  1. 第一步,将A像素点在最终的检测结果上标记出来。在此,我们用到了2.2.1章节中提到的 结果模板,将 结果模板 上与当前像素A位置对应的像素点置为0,即黑色点
  2. 第二步,将2.2.1章节中提到的 计数盘 中与当前像素A位置对应的像素点值清0;
  3. 第三步,有1/φ的概率更新样本库,并同时更新临近像素的样本库。

第三步稍微有点复杂,在这里博主也出现了点疑问,咱们先说技术,一会再聊疑问。
1/φ这个概率是作者自己定义的(开源代码中为1/16),算法首先维护一个随机数来确定是否达到1/φ这个概率,在达到这个概率后,开始对 当前像素 数据样本执行2.2.3章节给出的更新策略,同时随机选取当前像素的 一个8邻域像素(8个邻域像素中任选一个),执行相同的更新策略。例如当前像素记为A,像素值为Pa,选定的邻域像素记为B,像素值记为Pb,则A像素样本库中更新的像素值为Pa,B像素样本库中更新的像素值也为Pa。即采用A像素的当前像素值更新B像素的样本库。(数值上Pa=Pb不考虑在内)。

存疑:
博主在源代码中发现这一部分的更新策略是:有1/φ的概率更新样本库,并同时有1/φ的概率更新临近像素的样本库。 简单来讲就是代码中同时更新样本和临近像素样本库的概率为(1/φ)*(1/φ)。而论文中的内容是两者同时更新的概率为1/φ,虽然并不影响功能,但是还是希望能有读者大佬帮忙指点迷津,万分感谢!!!

将2.2.3和2.2.4章节的内容合并总结来说,当一个像素被定为一次前景,就会为他增加一层计数器,当计数器超过50,就会强制更新数据库样本信息。当一个像素被定为背景,会有一定概率更新数据库和其邻域像素的数据库,这个概率为1/φ。

至此,ViBe算法的原理全部结束。

3. 代码分析

可能是个人性格问题,博主觉得如果不能亲自撸通代码,在给大家做代码的分析的时候总是没什么底气 (只是我个人对自己的要求,不代表对其他人的看法。。。勿喷) ,所以这个章节中,代码分析用的代码是我自己在对开源代码稍作修改的基础上贴出来的,个人认为应该会更有助于大家理解算法。

PS: 如果感觉看着费劲可以开两个显示器窗口(如果你有两个显示器的话),一边看上面的原理,一边看代码效果会更好~

3.1 样本建模(对应2.2.1章节)

void ViBe::Init(Mat First_Frame){ //函数输入为第一帧图像的灰度图;RNG rng;           //定义一个随机数类;int random;           //定义一个随机数;int random_rows;   //定义随机行数;int random_cols;    //定义随机列数;int x_shift[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 }; //水平偏移;int y_shift[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };   //垂直偏移;//2.2.1总结中提出的三件事情中的第一件://建立一个vector类型的数据库for (int k = 0; k < num_sample; k++){//定义一个缓存模板,即原始图像样本库中的任意一帧;Mat Temp = Mat::zeros(First_Frame.rows, First_Frame.cols, CV_8UC1);//对每个像素进行双for循环内的操作;for (int i = 0; i < First_Frame.rows; i++){for (int j = 0; j < First_Frame.cols; j++){//先算随机坐标,会从9个像素点里随机选取一个存入当前缓存模板;random = rng.uniform(0, 9); random_rows = i + y_shift[random];random = rng.uniform(0, 9); random_cols = j + x_shift[random];//如果超出图像边界会防止越界,也就是说位于图像最外层一周的像素不会有完整//的9个像素供其选择,没有类似于深度学习的padding操作;if (random_rows < 0) random_rows = 0;if (random_rows >= First_Frame.rows) random_rows = First_Frame.rows - 1;if (random_cols < 0) random_cols = 0;if (random_cols >= First_Frame.cols) random_cols = First_Frame.cols - 1;//将当前模板位置为(i,j)的像素值赋值为随机选取的8邻域像素值中的一个;Temp.at<uchar>(i, j) = First_Frame.at<uchar>(random_rows, random_cols);          }}//全部像素初始化完毕,送入样本库,成为一张图像样本,共有 num_sample 张图像样本(即前文中提到的N);samples.push_back(Temp);}//2.2.1总结中提出的三件事情中的第二件://初始化所有像素的前景计数器(计数盘)为0;FG_counts = Mat::zeros(First_Frame.rows, First_Frame.cols, CV_8UC1);//2.2.1总结中提出的三件事情中的第三件://初始化结果模板为全黑色(全部为0);FG_model = Mat::zeros(First_Frame.rows, First_Frame.cols, CV_8UC1);
}

3.2 判定策略与更新策略(对应2.2.2~2.2.4章节)

void ViBe::Run(Mat Frame){//函数输入为待检测图像的灰度图;RNG rng;               //定义一个随机数类;int distance = 0;        //定义2.2.2章节中提到的Distance距离;int match_count = 0;  //匹配计数器;int random = 0;         //定义一个随机数;int random_rows;       //定义一个随机行数;int random_cols;      //定义一个随机列数;int x_shift[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };   //水平偏移;int y_shift[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };   //垂直偏移;for (int i = 0; i < Frame.rows; i++){//以下两个for循环完成的是每个像素的距离计算;//即2.2.2章节中三大步骤中的第一步和第二步;for (int j = 0; j < Frame.cols; j++){for (int k = 0; k < num_sample; k++){//2.2.2章节中的距离计算;distance = abs(samples[k].at<uchar>(i, j) - Frame.at<uchar>(i, j));//如果距离小于半径,说明变化不明显,即不是动态区域;if (distance < radius)match_count++;//这句话的目的是加速算法计算,如果Distance < R 的次数等于阈值M,就没有必要//继续向下计算了,值接退出就可以了;//min_match是2.2.2章节中提到的 匹配阈值 M if (match_count == min_match)break;}//如果匹配程度较高,则认为是背景,2.2.2章节第三步;if (match_count >= min_match){//匹配计数器清0;match_count = 0;//背景模型置黑(置0),2.2.4章节第一步;FG_model.at<uchar>(i, j) = 0;//前景计数器清0,2.2.4章节第二步;FG_counts.at<uchar>(i, j) = 0;//2.2.4章节第三步;//已经为背景,有1/φ的概率更新样本库和临近像素值;(该处与开源代码不同);//updata_probability即是φ;random = rng.uniform(0, updata_probability);//如果恰好命中概率,则执行2.2.4章节的更新策略if (random == 0){//更新本像素样本;random = rng.uniform(0, num_sample);//该步骤为2.2.3章节的样本更新策略;samples[random].at<uchar>(i, j) = Frame.at<uchar>(i, j);//更新临近像素样本;random = rng.uniform(0, 9); random_rows = i + x_shift[random];random = rng.uniform(0, 9); random_cols = j + y_shift[random];// 防止选取的像素点越界if (random_rows < 0) random_rows = 0;if (random_rows >= Frame.rows)  random_rows = Frame.rows - 1;if (random_cols < 0) random_cols = 0;if (random_cols >= Frame.cols) random_cols = Frame.cols - 1;// 为临近像素随机样本库赋值;random = rng.uniform(0, num_sample);samples[random].at<uchar>(random_rows, random_cols) = Frame.at<uchar>(i, j);}}//否则,该像素点为动态区域,即前景像素,2.2.2章节第三步;else{match_count = 0;//2.2.3章节第一步,背景模型置白;FG_model.at<uchar>(i, j) = 255;//2.2.3章节第二步,前景计数器+1,FG_counts.at<uchar>(i, j)++;//2.2.3章节第三步,强制更新样本//如果前景计数器大于50,则认为一块静止区域被误判为运动,更新为背景点;if (FG_counts.at<uchar>(i, j) > 50){random = rng.uniform(0, num_sample);samples[random].at<uchar>(i, j) = Frame.at<uchar>(i, j);}}}}
}

3.3 整体项目代码(详细备注请看3.1和3.2~)

不开源完整代码的程序员不是好博主~完整代码如下(我才不去骗大家的C币呢~~):

刚好有个小插曲在这里跟大家聊聊:关于类定义

博主并不是编程大神,只是会简单的用用相应语言而已,之前也有过疑问,什么时候用类?为什么大家都用类?类有啥好处啊??以下是我个人的粗浅理解,大家勿喷~

自己慢慢体会慢慢发现,感觉类这个东西最好的用途就是可以 “局部” 使用 “全局变量”。不知道这么说大家能不能理解。就拿下面这段程序中的 class ViBe 来说,在其内部定义的所有变量(如:samples,FG_counts,FG_model)都能被类内部的函数视为 “全局变量”,这种 “局部” 的 “全局效应” 仅在类内部有效,可以对比 “闭包” 的概念~ 这样是不是解决了很多小伙伴们既想让一个变量在一定场合下 “局部”,又在个别场景下 “全局” 的困惑??

说明:有小伙伴私信我说下文源代码中

  1. CV_CAP_PROP_FRAME_HEIGHT
  2. CV_CAP_PROP_FRAME_WIDTH
  3. CV_RGB2GRAY

这三个变量系统无法识别,原因是因为小伙伴们用的OpenCV版本比较高,上述三个变量已经被重新命名了,下文中的OpenCV版本为3.1.0,如果你们出现了报错,将上述三个变量分别改为:

  1. CAP_PROP_FRAME_HEIGHT
  2. CAP_PROP_FRAME_WIDTH
  3. COLOR_RGB2GRAY

这样应该就可以啦!!

/*===================================================================
* 作者:打团从来人不齐;
* 时间:2019.12.18;
* OpenCV版本:3.1.0
* 说明:ViBe算法手撸修改版;
* 维护:打团从来人不齐;
* 备注:欢迎大家多多评论交流!!
=====================================================================
*/#include <stdio.h>
#include <stdlib.h>
#include <string>
#include<opencv2\opencv.hpp> using namespace cv;
using namespace std;#define DEFAULT_NUM_SAMPLES  20     //每个像素点的默认样本数量
#define DEFAULT_MIN_MATCHES  2      //匹配阈值 M
#define DEFAULT_RADIUS 30           //半径阈值 R
#define DEFAULT_RANDOM_SAMPLE 16    //采样概率φstring PATH1 = "<Your_Video_Path>";
string PATH2 = "<Your_Video_Path>";class ViBe{public://ViBe初始化函数;void Init(Mat First_Frame);//ViBe检测函数;void Run(Mat Frame);//检测结果获取;Mat GetFGModel();//删除样本库;void DeleteSamples();private:int num_sample = DEFAULT_NUM_SAMPLES;int min_match = DEFAULT_MIN_MATCHES;int radius = DEFAULT_RADIUS;int updata_probability = DEFAULT_RANDOM_SAMPLE;vector<Mat> samples; //数据样本库;Mat FG_counts;       //图像计数盘;Mat FG_model;       //结果模板;
};void ViBe::Init(Mat First_Frame){RNG rng;int random;int random_rows;int random_cols;int x_shift[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };int y_shift[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };//初始化所有像素的前景计数器为0;FG_counts = Mat::zeros(First_Frame.rows, First_Frame.cols, CV_8UC1);//初始化前景图像模板为全黑色;FG_model = Mat::zeros(First_Frame.rows, First_Frame.cols, CV_8UC1);//建立一个vector类型的数据库for (int k = 0; k < num_sample; k++){Mat Temp = Mat::zeros(First_Frame.rows, First_Frame.cols, CV_8UC1);for (int i = 0; i < First_Frame.rows; i++){for (int j = 0; j < First_Frame.cols; j++){random = rng.uniform(0, 9); random_rows = i + y_shift[random];random = rng.uniform(0, 9); random_cols = j + x_shift[random];if (random_rows < 0) random_rows = 0;if (random_rows >= First_Frame.rows) random_rows = First_Frame.rows - 1;if (random_cols < 0) random_cols = 0;if (random_cols >= First_Frame.cols) random_cols = First_Frame.cols - 1;Temp.at<uchar>(i, j) = First_Frame.at<uchar>(random_rows, random_cols);}}samples.push_back(Temp);}
}void ViBe::Run(Mat Frame){RNG rng;int distance = 0;int match_count = 0;int random = 0;int random_rows;int random_cols;int x_shift[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };int y_shift[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };for (int i = 0; i < Frame.rows; i++){for (int j = 0; j < Frame.cols; j++){for (int k = 0; k < num_sample; k++){//距离计算;distance = abs(samples[k].at<uchar>(i, j) - Frame.at<uchar>(i, j));//如果距离小于半径,说明变化不明显,即不是动态区域;if (distance < radius)match_count++;if (match_count == min_match)break;}//如果匹配程度较高,则认为是背景,前景计数器清0,背景模型置黑;if (match_count >= min_match){match_count = 0;FG_counts.at<uchar>(i, j) = 0;FG_model.at<uchar>(i, j) = 0;//已经为背景,有1/φ的概率更新样本库和临近像素值;(该处于代码不同);random = rng.uniform(0, updata_probability);if (random == 0){//更新本像素样本;random = rng.uniform(0, num_sample);samples[random].at<uchar>(i, j) = Frame.at<uchar>(i, j);//跟新临近样本;random = rng.uniform(0, 9); random_rows = i + x_shift[random];random = rng.uniform(0, 9); random_cols = j + y_shift[random];// 防止选取的像素点越界if (random_rows < 0) random_rows = 0;if (random_rows >= Frame.rows)  random_rows = Frame.rows - 1;if (random_cols < 0) random_cols = 0;if (random_cols >= Frame.cols) random_cols = Frame.cols - 1;// 为样本库赋随机值random = rng.uniform(0, num_sample);samples[random].at<uchar>(random_rows, random_cols) = Frame.at<uchar>(i, j);}}//否则,该像素点为动态区域,即前景像素;else{match_count = 0;//前景计数器+1,背景模型置白;FG_model.at<uchar>(i, j) = 255;FG_counts.at<uchar>(i, j)++;//如果前景计数器大于50,则认为一块静止区域被误判为运动,更新为背景点;if (FG_counts.at<uchar>(i, j) > 50){random = rng.uniform(0, num_sample);samples[random].at<uchar>(i, j) = Frame.at<uchar>(i, j);}}}}
}Mat ViBe::GetFGModel(){return FG_model;
}void ViBe::DeleteSamples()
{vector<Mat>().swap(samples);
}void main(){VideoCapture capture;capture = VideoCapture(PATH2); capture.set(CV_CAP_PROP_FRAME_WIDTH, 160);capture.set(CV_CAP_PROP_FRAME_HEIGHT, 120);Mat frame;Mat gray;Mat FG_img;ViBe Vibe_Model;int Start_Flag = 0;while (1){capture >> frame;resize(frame, frame, Size(480, 320));cvtColor(frame, gray, CV_RGB2GRAY);if (Start_Flag == 0){Vibe_Model.Init(gray);Start_Flag += 1;}else{Vibe_Model.Run(gray);FG_img = Vibe_Model.GetFGModel();imshow("ori", frame);imshow("test", FG_img);}if (waitKey(25) == 27){break;}}system("pause");
}

4.写在最后

非常感谢大家的光临!希望大家有什么宝贵的建议和意见能够在评论区多多交流!希望与大家一同进步!!

(来自一名励志用“普通话”讲技术的菜狗子~)

用 “普通话” 讲算法之 VIBE算法相关推荐

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

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

  2. 论文翻译:ViBe+算法(ViBe算法的改进版本)

    论文翻译:ViBe+算法(ViBe算法的改进版本) 原文地址: <Background Subtraction: Experiments and Improvements for ViBe> ...

  3. 运动目标检测ViBe算法

    一.运动目标检测简介   视频中的运动目标检测这一块现在的方法实在是太多了.运动目标检测的算法依照目标与摄像机之间的关系可以分为静态背景下运动检测和动态背景下运动检测.先简单从视频中的背景类型来讨论. ...

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

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

  5. opencv-视频处理-实时的前景检测-Vibe算法

    vibe算法是一种像素级的前景检测算法,实时性高,内存占有率低,前景检测准确率高.但是会出现"鬼影",当然基于对鬼影的处理,也会有相应的对vibe算法的改进. 把下面三篇文章看明白 ...

  6. 背景建模--Vibe 算法改进

    背景建模--Vibe 算法改进 一.概述 针对鬼影问题,提出一种了基于前景区域与邻域背景区域直方图相似性度量的判别方法,检测并消除鬼影:针对静止目标问题,改进了Vibe背景模型的更新策略,有效抑制静止 ...

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

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

  8. 计算机视觉与深度学习 | 基于MATLAB的Vibe算法消除鬼影(代码版)

    /********************************************************** github:https://github.com/MichaelBeechan ...

  9. 数据结构与算法之美学习笔记:哈希算法-哈希算法在分布式系统中有哪些应用(第22讲)...

    上一节,我讲了哈希算法的四个应⽤,它们分别是:安全加密.数据校验.唯⼀标识.散列函数.今天,我们再来看剩余三种应用: 负载均衡.数据分片.分布式存储 你可能已经发现,这三个应用都跟分布式系统有关.没错 ...

  10. 前景检测算法(七)--ViBe算法

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

最新文章

  1. UI设计培训分享:设计当中的颜色运用
  2. Linux下覆盖目录的方法
  3. IIS网站的权限设置问题
  4. SQL语言基础:常用的数据查询语句
  5. Class的 getSuperclass与getGenericSuperclass区别
  6. v-for中用elementUI实现分页
  7. Linux常用命令——chattr、lsattr
  8. netty 水位线与oom
  9. 计算机操作系统的功能有哪些,操作系统的基本功能是什么
  10. 摆脱某某助手,使用无线投屏功能共享安卓屏幕到PC
  11. dubbo中bugger集
  12. 爬取Bilibili视频评论,并生成云词图
  13. Qt窗口模糊和阴影效果
  14. 电脑开不了机的原因和解决办法
  15. 基于mochiweb的chatty聊天室1
  16. flash player安装教程--亲测有效
  17. Android 扫描、生成、识别二维码、条码 一库搞定
  18. 我说,执着造就了成功
  19. ARM裸机的知识点总结---------11、iNandFlash (sd卡芯片化)
  20. 图形化开放式生信分析系统开发- 1基本需求分析及技术实现

热门文章

  1. ui web php,Uimaker 一个精美的后台管理系统模版,可使用在web 中 WEB(ASP,PHP,...) 262万源代码下载- www.pudn.com...
  2. 基于51单片机超声波测距仪设计倒车雷达防撞报警器
  3. 无线网radius服务器ip,怎么设置无线路由器的radius服务器ip地址
  4. 湖南对口招生计算机专业试卷,湖南省2018年普通高等学校对口招生考试计算机应用类综合试卷 参考答案...
  5. 计算机桌面无法新建文件夹,Win7桌面不能新建文件夹和修改文件名怎么办?
  6. Linux BT下载(7)-种子解析模块设计与实现1
  7. 彻底关闭360安全卫士弹窗广告方法
  8. 前端开发必备,【项目实战】
  9. matlab2012b破解版安装
  10. idea黑暗护眼主题