vibe前景提取改进算法
// improveVibeAlgorithm.h
#ifndef IMPROVED_VIBE_ALGORITHM_H
#define IMPROVED_VIBE_ALGORITHM_H#include <opencv2/opencv.hpp>
using namespace std;#define WINSIZE 5 // Vibe改进算法, Barnich, Olivier & Droogenbroeck, Marc. (2009).
// ViBE: A powerful random technique to estimate the background in video sequences.
// 945-948. 10.1109/ICASSP.2009.4959741.
// http://www.cnblogs.com/ydxt/p/6213601.html
class Vibe
{
public:Vibe(void);Vibe(IplImage *img);void SetMinMatch(int nthreshold) { g_MinMatch = nthreshold; }void SetRadius(int radius) { g_Radius = radius; }void SetSampleNum(int num) { g_SampleNum = num; }void SetThreshold(double t) { g_threshold = t; }IplImage* GetForeground() { return g_ForeImg; }IplImage* GetSegMask() { return g_SegementMask; }void Detect(IplImage *img);void ForegroundCombineEdge(); // 结合边缘信息 void DeleteSmallAreaInForeground(double minArea = 20);//删除小面积区域 // 实现背景更新机制 void Update();// 实现后处理,主要用形态学算子 void PostProcess();public:~Vibe(void);private:void ClearLongLifeForeground(int i_lifeLength = 10); // 清除场景中存在时间较长的像素,i_lifeLength用于控制允许存在的最长时间 double AreaDense(IplImage *pFr, int AI, int AJ, int W, int H); //计算(i,j)处邻域大小为W×H的密度 int GetRandom(int istart, int iend); // 默认istart=0,iend=15 int GetRandom(int random);int GetRandom();// 产生一个随机数 // 计算两个像素之间的欧式距离 double CalcPixelDist(CvScalar bkCs, CvScalar curCs);// 按照Kim的方法来计算颜色畸变 double CalcuColorDist(CvScalar bkCs, CvScalar curCs);int g_SampleNum;// Sample number for the models,默认为20 int g_MinMatch; // 当前像素与背景模型匹配的最少个数,默认为2 int g_Height;int g_Width;int g_Radius;// 球体的半径,默认为20 int g_offset; //边界的宽和高 double g_threshold; // 距离度量的阈值 unsigned char ***g_Model;// 保存背景模型 IplImage *g_ForeImg;// 保存前景图 IplImage *g_Edge;IplConvKernel* element;IplImage *g_SegementMask; //分割掩膜 IplImage *g_UpdateMask; // 更新掩膜 IplImage *g_Gray;int ** LifeLength; // 记录前景点的生命长度,如果前景点的生命长度到达一定的阈值,则将其融入背景中去,且要随机两次。
};#endif // !IMPROVED_VIBE_ALGORITHM_H
// improveVibeAlgorithm.cpp
#include "improveVibeAlgorithm.h" #include <iostream>using namespace std; using namespace cv;Vibe::Vibe(void) {g_Radius = 20;g_MinMatch = 2;g_SampleNum = 20;g_offset = (WINSIZE - 1) / 2;}Vibe::Vibe(IplImage *img) {if (!img){cout << " The parameter referenced to NUll Pointer!" << endl;return;}this->g_Height = img->height;this->g_Width = img->width;g_Radius = 20;g_MinMatch = 2;g_SampleNum = 20;g_threshold = 50;g_offset = (WINSIZE - 1) / 2;g_ForeImg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);g_Gray = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);g_Edge = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);g_SegementMask = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);g_UpdateMask = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);element = cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_CROSS, NULL);cvCvtColor(img, g_Gray, CV_BGR2GRAY);// 以上完成相关的初始化操作 /********************** 以下实现第一帧在每个像素的8邻域内的采样功能,建立对应的背景模型*****************************/int i = 0, j = 0, k = 0;g_Model = new unsigned char**[g_SampleNum];for (k = 0; k<g_SampleNum; k++){g_Model[k] = new unsigned char *[g_Height];for (i = 0; i<g_Height; i++){g_Model[k][i] = new unsigned char[g_Width];for (j = 0; j<g_Width; j++){g_Model[k][i][j] = 0;}}}// 采样进行背景建模 double dVal;int ri = 0, rj = 0; //随机采样的值 for (i = g_offset; i<g_Height - g_offset; i++){for (j = g_offset; j<g_Width - g_offset; j++){// 周围3*3的邻域内进行采样 for (k = 0; k<g_SampleNum; k++){ri = GetRandom(i);rj = GetRandom(j);dVal = cvGetReal2D(g_Gray, ri, rj);g_Model[k][i][j] = dVal;}}}// 初始化前景点掩膜的生命长度 LifeLength = new int *[g_Height];for (i = 0; i<g_Height; i++){LifeLength[i] = new int[g_Width];for (j = 0; j<g_Width; j++){LifeLength[i][j] = 0;}} }void Vibe::Detect(IplImage *img) {cvZero(g_ForeImg);cvCvtColor(img, g_Gray, CV_BGR2GRAY);int i = 0, j = 0, k = 0;double dModVal, dCurrVal;int tmpCount = 0;// 距离比较在阈值内的次数 double tmpDist = 0;int iR1, iR2;//产生随机数 int Ri, Rj; // 产生邻域内X和Y的随机数 for (i = 0; i<g_Height; i++){for (j = 0; j<g_Width; j++){if (i < g_offset || j < g_offset || i> g_Height - g_offset || j> g_Width - g_offset){cvSetReal2D(g_ForeImg, i, j, 0);continue;}else{tmpCount = 0;dCurrVal = cvGetReal2D(g_Gray, i, j);for (k = 0; k<g_SampleNum && tmpCount<g_MinMatch; k++){dModVal = g_Model[k][i][j];//tmpDist=CalcPixelDist(dCurrVal,dModVal); //tmpDist=CalcuColorDist(dCurrVal,dModVal); tmpDist = fabs(dModVal - dCurrVal);if (tmpDist<g_Radius){tmpCount++;}}//判断是否匹配上 if (tmpCount >= g_MinMatch){cvSetReal2D(g_ForeImg, i, j, 0);// 背景模型的更新 iR1 = GetRandom(0, 15);if (iR1 == 0){iR2 = GetRandom();g_Model[iR2][i][j] = dCurrVal;}//进一步更新邻域模型 iR1 = GetRandom(0, 15);if (iR1 == 0){Ri = GetRandom(i);Rj = GetRandom(j);iR2 = GetRandom();g_Model[iR2][Ri][Rj] = dCurrVal;}}else{cvSetReal2D(g_ForeImg, i, j, 255);}}}}//ForegroundCombineEdge(); DeleteSmallAreaInForeground(2000);ClearLongLifeForeground();//PostProcess(); }double Vibe::AreaDense(IplImage *pFr, int AI, int AJ, int W, int H) {if (AI <= 2 || AJ <= 2 || AJ >= (g_Width - 2) || AI >= (g_Height - 2)){return 0;}int Num = 0, i = 0, j = 0;double dVal = 0, dense = 0;int Total = (2 * H + 1)*(2 * W + 1);for (i = AI - H; i <= AI + H; i++){for (j = AJ - W; j <= AJ + W; j++){dVal = cvGetReal2D(pFr, i, j);if (dVal>200){Num++;}}}dense = (double)Num / (double)Total;return dense; }void Vibe::ForegroundCombineEdge() {cvZero(g_Edge);//cvZero(g_SegementMask); //cvCopy(g_ForeImg,g_SegementMask); cvCanny(g_Gray, g_Edge, 30, 200, 3);int i = 0, j = 0;double dense;double dVal;for (i = g_offset; i<g_Height - g_offset; i++){for (j = g_offset; j<g_Width - g_offset; j++){dense = AreaDense(g_ForeImg, i, j, 2, 2);dVal = cvGetReal2D(g_Edge, i, j);if (dense>0.2 && dVal>200){cvSetReal2D(g_ForeImg, i, j, 255);}}}}void Vibe::DeleteSmallAreaInForeground(double minArea/* =20 */) {//cvZero(g_SegementMask); //cvCopy(g_ForeImg,g_SegementMask); int region_count = 0;CvSeq *first_seq = NULL, *prev_seq = NULL, *seq = NULL;CvMemStorage* storage = cvCreateMemStorage();cvClearMemStorage(storage);cvFindContours(g_ForeImg, storage, &first_seq, sizeof(CvContour), CV_RETR_LIST);for (seq = first_seq; seq; seq = seq->h_next){CvContour* cnt = (CvContour*)seq;if (cnt->rect.width * cnt->rect.height < minArea){prev_seq = seq->h_prev;if (prev_seq){prev_seq->h_next = seq->h_next;if (seq->h_next) seq->h_next->h_prev = prev_seq;}else{first_seq = seq->h_next;if (seq->h_next) seq->h_next->h_prev = NULL;}}else{region_count++;}}cvZero(g_ForeImg);cvDrawContours(g_ForeImg, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1);/*CvContourScanner scanner = cvStartFindContours( g_ForeImg, storage,sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );CvSeq *contours=NULL,*c=NULL;int poly1Hull0=0;int nContours=0;double perimScale=100;while( (c = cvFindNextContour( scanner )) != 0 ){double len = cvContourPerimeter( c );double q = (g_ForeImg->height + g_ForeImg->width)/perimScale; // calculate perimeter len thresholdif( len < q ) //Get rid of blob if it's perimeter is too smallcvSubstituteContour( scanner, 0 );else //Smooth it's edges if it's large enough{CvSeq* newC;if( poly1Hull0 ) //Polygonal approximation of the segmentationnewC = cvApproxPoly( c, sizeof(CvContour), storage, CV_POLY_APPROX_DP, 2, 0 );else //Convex Hull of the segmentationnewC = cvConvexHull2( c, storage, CV_CLOCKWISE, 1 );cvSubstituteContour( scanner, newC );nContours++;}}contours = cvEndFindContours( &scanner );// paint the found regions back into the imagecvZero( g_ForeImg );for( c=contours; c != 0; c = c->h_next )cvDrawContours( g_ForeImg, c, cvScalarAll(255), cvScalarAll(0), -1, CV_FILLED, 8,cvPoint(0,0));*/cvReleaseMemStorage(&storage); }void Vibe::ClearLongLifeForeground(int i_lifeLength/* =200 */) {int i = 0, j = 0;double dVal = 0;double dLife = 0;int iR1, iR2 = 0;double dCurrVal = 0;for (i = g_offset; i<g_Height - g_offset; i++){for (j = g_offset; j<g_Width - g_offset; j++){dVal = cvGetReal2D(g_ForeImg, i, j);dLife = LifeLength[i][j];if (dLife>i_lifeLength){LifeLength[i][j] = 0;dCurrVal = cvGetReal2D(g_Gray, i, j);// 更新背景模型 iR1 = GetRandom();iR2 = GetRandom();g_Model[iR1][i][j] = dCurrVal;g_Model[iR2][i][j] = dCurrVal;}else{LifeLength[i][j] = dLife + 1;}}} }void Vibe::Update() {cvZero(g_UpdateMask);}void Vibe::PostProcess() {cvZero(g_SegementMask);cvMorphologyEx(g_ForeImg, g_SegementMask, NULL, element, CV_MOP_OPEN, 1);}//算颜色畸变 double Vibe::CalcuColorDist(CvScalar bkCs, CvScalar curCs) {double r, g, b, br, bg, bb;r = curCs.val[0];g = curCs.val[1];b = curCs.val[2];br = bkCs.val[0];bg = bkCs.val[1];bb = bkCs.val[2];double curDist = r*r + g*g*b*b;double bkDist = br*br + bg*bg + bb*bb;double curBK = r*br + g*bg + b*bb;double curbkDist = curBK*curBK;double SquareP;if (bkDist == 0.0){SquareP = 0;}else{SquareP = curbkDist / bkDist;}double dist = sqrtf(curDist - SquareP);return dist; }double Vibe::CalcPixelDist(CvScalar bkCs, CvScalar curCs) {double tmpDist = pow(bkCs.val[0] - curCs.val[0], 2) + pow(bkCs.val[1] - curCs.val[1], 2) + pow(bkCs.val[2] - curCs.val[2], 2);return sqrtf(tmpDist); }int Vibe::GetRandom() {int val = g_SampleNum * 1.0 * rand() / RAND_MAX;if (val == g_SampleNum)return val - 1;elsereturn val; }int Vibe::GetRandom(int random) {int val = random - g_offset + rand() % (2 * g_offset);if (val<random - g_offset){val = random - g_offset;}if (val>random + g_offset){val = random + g_offset;}return val; }int Vibe::GetRandom(int istart, int iend) {int val = istart + rand() % (iend - istart);return val; }Vibe::~Vibe(void) {if (g_ForeImg){cvReleaseImage(&g_ForeImg);}if (g_SegementMask){cvReleaseImage(&g_SegementMask);}if (g_UpdateMask){cvReleaseImage(&g_UpdateMask);}if (g_Gray){cvReleaseImage(&g_Gray);}if (g_Model != NULL){delete[]g_Model;g_Model = NULL;} }
相关文章:

npm-debug.log文件出现原因
项目主目录下总是会出现这个文件,而且不止一个,原因是npm i 的时候,如果报错,就会增加一个此文件来显示报错信息,npm install的时候则不会出现。转载于:https://www.cnblogs.com/liuna/p/6558006.html

AutoFac Ioc依赖注入容器
本文原著:牛毅 原文路径 http://niuyi.github.io/blog/2012/04/06/autofac-by-unit-test/ 理解IOC容器请看下图: 没有使用IOC容器的情况下: 使用IOC容器的情况下: 去掉IOC容器的情况后: IOC容器又像一个插座,将电输送…

Linux安装App记录
Ubuntu18.04安装微信

windows socket编程入门示例3
// Lock.h #ifndef _Lock_H #define _Lock_H #include <windows.h>class CriticalSection { private:CRITICAL_SECTION g_cs; //临界区 public:CriticalSection();~CriticalSection();void Lock();void UnLock(); }; #endif// Lock.cpp #include "Lock.h"…

游戏开发:js实现简单的板球游戏
js实现简单的板球游戏大家好,本次我们来使用js来实现一个简单的板球游戏。截图如下:首先,设计页面代码,页面代码很简单,因为整个几乎是使用js编写的,页面几乎没有代码,如下:<!DOC…

SLAM精度测评——EVO进阶
1. 基本概念 1.1 Umeyama算法 ATE: evo_ape tum state_groundtruth_estimate0/data.tum orb2/CameraTrajectory.txt -r trans_part -va --plot --plot_mode xy --save_results /home/sun/evo/v1_01_easy/orb2/ate.zip RPE: evo_rpe tum state_groun…

python读取图片并且显示
使用python-opencv读取图片,利用opencv或matplotlib显示图片。 # -*- coding: utf-8 -*-import numpy as np from matplotlib import pyplot as plt #import urllib import cv2def load_image1(file):# Load an color image in grayscaleimg cv2.imread(file,0)cv…

shiro认证
shiro权限认证: 具体的认证流程是这样的: 一般流程: 通过.ini的文件来初始化工厂,.ini的文件的好处是可以创建多个组,而.properties的文件只能创建一组。 系统默认有shiro.ini的文件,但是一般我们是自定义数…

小猿圈Linux基础面试题,看看你能答对几道?
最近身边的很多朋友都在学习linux,从最开始的安装软件都需要百度一天的他们,现在已经成长为了,不需要百度就可以把自己弄懵圈的了,接下来的几天小猿圈linux老师会为大家准备一些实用的linux技巧分析给大家,希望对你有所…

ORB-SLAM2 论文翻译
https://ug98gs7tbw.feishu.cn/docs/doccnKKOWAjkKv7AzAiEvbnM3Tf

mxnet教程1
import mxnet as mx #%matplotlib inline import os import subprocess import numpy as np import matplotlib.pyplot as plt import tarfileimport warnings warnings.filterwarnings("ignore", categoryDeprecationWarning)# 从内存中读取数据 def test1():data …

番外:Spring MVC环境搭建和Mybatis配置避坑篇
2019独角兽企业重金招聘Python工程师标准>>> web.xml引入对spring mvc的支持; spring-mvc配置spring-mvc; spring-mybatis配置mybatis支持,并指名mapper文件的位置; mybaits-config配置mybatis; jdbc.prope…

50个云终端只需一台服务器是怎么一回事
看到这个标题也许有人会说50个云终端只需要一台服务器这应该是不可能的吧,即使是真的那这个服务器的配置和价格应该也要非常高的吧。但是如果有人和你说50个云终端只需要一台中等配置和价格的服务器就可以的呢。而且这50个用户桌面都可以正常的使用不会出现卡顿等现…

SLAM学习,小白入门到殿堂级大牛资料整理
总结一下我接触过的SLAM算法吧,主要集中在visual slam: 特征法: ORB SLAM https://github.com/raulmur/ORB_SLAM2优势: 在静态环境下定位准确,稳定, 单目和双目版本都可以达到实时(高于10frames/s)。代码可读性强,易扩展, 网上也有实现和imu融合的版本。 劣势:建的地图…

python解析json
“data.json”文件内容如下: {"id":"1220562","alt":"http:\/\/book.douban.com\/book\/1220562","rating":{"max":10, "average":"7.0", "numRaters":282, "min…

8.改进应用程序
2019独角兽企业重金招聘Python工程师标准>>> ##8.1数字格式设置(storyboard) ##8.1.2可选类型拆封 import Cocoa extension Double{var dollars : String{let formatter : NumberFormatter NumberFormatter()//NSNumberFormatter弃用var re…

小猿圈Linux学习-Linux种搜索的命令
做Linux工程师的每天都不能少的工作就是搜索文件,这是他们的日常活动,很繁琐很枯燥,所以我们就需要知道一些搜索的命令,这些命令更高效更快捷,今天小猿圈就给大家分享4个可以搜索的Linux命令。。 方法 1:使…
SURF与SIFT比较分析
opencv3.2 SURF实现特征点匹配 opencv3.2中SurfFeatureDetector、SurfDescriptorExtractor、BruteForceMatcher这三个的使用方法已经和原先2.4版本前不一样了。 使用方法示例如下: Ptr<SURF> detector SURF::create(minHessian);detector->detect(img_1…

python文件和目录
# -*- coding: utf-8 -*-import osdef printFile(rootDir):allFiles os.listdir(rootDir) #列出文件夹下所有文件和目录for i in range(0, len(allFiles)):# print(rootDir allFiles[i])path os.path.join(rootDir, allFiles[i])if not os.path.isfile(path):print(path, &q…

你不怕他离职吗?
图片来自“wikiart” 这是我同事在晚上11点多跟我聊微信时问起的一个问题,我觉得这个问题还是挺有代表性的,所以我还是决定就这个问题展开聊聊我对这句话的看法。 我同事之所以这么说,是因为他的组员,也就是问题中的那个他&#x…

tensorflow 1
import tensorflow as tf import numpy as np import matplotlib.pylab as pltdef tfDemo1():#create datax_data np.random.rand(100).astype(np.float32)y_data x_data * 0.1 0.3#create tensorflow structureWeightstf.Variable(tf.random_uniform([1],-1.0,1.0)) #一维&…

SLAM资源整理
资源整理 浙大3D Group VINS orbslam2 orbslam2 video study https://www.bilibili.com/video/BV1bK4y197kB/?spm_id_fromautoNext orbslam2 csdn https://blog.csdn.net/ncepu_chen/category_9874746.html https://www.zhihu.com/column/c_1114864226103037952 https:…

Golang微服务开发实践
github: github.com/yun-mu/Micr… 微服务概念学习:可参考 Nginx 的微服务文章 微服务最佳实践:可参考 微服务最佳实践 demo 简介 服务: consignment-service(货运服务)user-service(用户服务)l…

Linux ssh/scp/docker学习
文章目录Linux ssh/scp/docker使用学习1. ssh 登录2. scp传输文件3. docker4. git checkout 替换指定分支的单个文件Linux ssh/scp/docker使用学习 1. ssh 登录 sudo ssh fireflyip (登录账号密码) scp -r company/data_depthfill/ firefly192.168.105.6:/tmp/ 2…

tensorflow mnist 1
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import keras.backend.tensorflow_backend as KTFdef add_layer(inputs,in_size,out_size,activation_functionNone):#Weights是一个矩阵,[行,列]为[in_size,out_s…

framework7使用笔记
2019独角兽企业重金招聘Python工程师标准>>> myApp.addView(.view-main, {}); 以上这句代码一定要添加 ,否则链接的页面不能正常加载 --------------------------------------------- 如果初始化时定义了preprocess,则页面上链接的自动加载将…

Linux:检查当前运行级别的五种方法
2019独角兽企业重金招聘Python工程师标准>>> 运行级就是Linux操作系统当前正在运行的功能级别。存在七个运行级别,编号从0到6。系统可以引导到任何给定的运行级别。运行级别由数字标识。每个运行级别指定不同的系统配置,并允许访问不同的进程…

概率机器人资料整理
机器人算法仿真 https://atsushisakai.github.io/PythonRobotics/ 最大熵对应的概率分布及其优化推导 https://www.cnblogs.com/yychi/p/9401807.html 矩阵计算网址 http://www.yunsuan.info/matrixcomputations/index.html

LLVM官方文档翻译---- LLVM原子指令与并发指引
英文原文地址:http://llvm.org/docs/Atomics.html 译文原文地址:http://blog.csdn.net/wuhui_gdnt/article/details/52485591 注:该文章转载已经得到译者授权。 --------------------------------------------------------------------------…

matplotlib画图
import matplotlib.pyplot as plt import numpy as npdef test1():# 从[-1,1]中等距去50个数作为x的取值x np.linspace(-1, 1, 50)print(x)y 2*x 1y1 2**x 1# 第一个是横坐标的值,第二个是纵坐标的值plt.plot(x, y)plt.plot(x, y1)# 必要方法,用于将…