VIBE背景建模算法之C语言实现

本文实现的检测效果跟原文基本相同,但是在实现上做了很多改进,检测速度比原算法快,而且是纯C语言实现

本文实现的算法也跟VIBE原算法和混合高斯背景建模一样,对光照突变都很敏感,在后续的文章中会提出自适应阈值的方法来改进VIBE算法,使其能适应运动物体接近摄像头时引起的图像亮度变化,同时不会影响算法的速度。

废话不多说先上三张检测图:

                                                      

                                                      

                                                      

ViBe.h

#ifndef _VIBE_H
#define _VIBE_H

#include <iostream>
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/video/video.hpp"

using namespace std;
using namespace cv;

#define VIBE_WIDTH (360) //图像宽
#define VIBE_HEIGHT (240)//图像高
#define VIBE_FORGROUND_COUNT (100)  //统计前景出现次数,如果超过此次数则把前景更新到背景中

void VibeForground(unsigned char *CurImg,unsigned char* ForImg);

#endif //_VIBE_H


ViBe.cpp

#include "ViBe.h"

const int gVibeRandom = 127; //vibe子采样率为16
const int gVibeSize = VIBE_WIDTH*VIBE_HEIGHT;
const int gRadius = 20; //当前帧与背景模型作差的阈值(可变)
const int gMin = 3; //当前帧与背景模型做差其差值小于20的个数,如果大于等于3则认为是当前像素是背景
const int gVibeSimpleSize = 8; //背景模型保存的帧数
const int gVibeModelLastSize =VIBE_WIDTH*VIBE_HEIGHT*8;

static unsigned char VibeModelData[VIBE_WIDTH*VIBE_HEIGHT*9]; //用于存储样本集
static unsigned char BackGroundData[VIBE_WIDTH*VIBE_HEIGHT];

//---------------------------------------------------------------------------
//  Function name:InitialModelData()
//  Function :init VibeModelData by first Frame ,
//  Parameter:pImgData 
//---------------------------------------------------------------------------
void InitialModelData(const unsigned char *pImgData)
{
	int i=0;

	for (i=0;i<gVibeSimpleSize;i++)
	{
		memcpy(VibeModelData +gVibeSize * i, pImgData, gVibeSize);
	}
}

//---------------------------------------------------------------------------
//  Function name:VibeForground()
//  Function:The current frame and background model are compared, 
//            and the foreground of the current frame is obtained.
//  Parameter:CurImgPyr 
//  Reference:<<A universal background subtraction algorithm for video sequences>>
//  201507--zhangbin
//---------------------------------------------------------------------------

void VibeForground(unsigned char *CurImg,unsigned char* ForImg)
{
	unsigned int nOffset = 0;//偏移量

	short nDiff = 0; //保存当前帧与背景模型中某帧的差值
	unsigned int j = 0;
	unsigned int i = 0;
	unsigned char nCount = 0; 
	unsigned char *pSrcImg = 0;
	unsigned char *pDstImg = 0;
	static unsigned char CountNum=0; //此数除以16,127为一个循环,共能够取0-7之前的随机数(模拟VIBE子采样概率生成的随机数)
	static int g_IsModelInit = 1;

	pSrcImg = CurImg;
	pDstImg = ForImg;

	CountNum++;
	if (CountNum>gVibeRandom)
	{
		CountNum=0;
	}

	if(g_IsModelInit) 
	{
		InitialModelData(pSrcImg); //当前帧初始化背景
		memcpy(BackGroundData, pSrcImg, gVibeSize);
		g_IsModelInit = 0;
		return; 
	} 

	nOffset =  (CountNum>>4) * gVibeSize;	//CountNum>>4相当于16帧生成一个数

	for(i = 0; i < gVibeSize; i++)
	{
		nCount = 0;
		pDstImg[i] = 255;

		for(j = 0; j < gVibeSimpleSize; j++) //遍历背景模型
		{
			nDiff = VibeModelData[j*gVibeSize+i]-pSrcImg[i];

			if(nDiff <= gRadius )
			{
				if (nDiff >= -gRadius)
				{
					nCount++; 
				}
			}

			if(nCount >= gMin) //当前帧像素值小于gRadius的次数大于gMin(论文中为#min = 2)则此点判断为背景
			{
				pDstImg[i] = 0;
				break; 
			}
		}
	}

	for(i = 0; i < gVibeSize; i++)
	{
		if (pDstImg[i]) //如果此点为前景则累加此点为前景的次数
		{
			VibeModelData[gVibeModelLastSize+i]++;

			if ( VibeModelData[gVibeModelLastSize+i]>100)
			{
				VibeModelData[nOffset+i] = pSrcImg[i];
			}
		}else//如果此点为背景,则对背景模型进行更新
		{

			VibeModelData[nOffset+i] = pSrcImg[i];

			BackGroundData[i] = pSrcImg[i];

			VibeModelData[gVibeModelLastSize+i] = 0;
		}
	}
}


main.cpp

#include "ViBe.h"
#include <stdio.h>

char *VideoName = "E:\\ViBe\\测试视频\\seq-320-240.avi";

int main(int argc, char* argv[])
{
	//声明IplImage指针
	IplImage* pFrame = NULL; 
	IplImage* pResizeFrame = NULL; 
	IplImage* pGrayImg = NULL;
	IplImage* pFrImg = NULL;

	CvCapture* pCapture = NULL;
	double t;
	int nFrmNum = 0;
	int otsuThresh = 0;
	//创建窗口
	cvNamedWindow("video", 1);
	cvNamedWindow("foreground",1);
	
	//使窗口有序排列
	cvMoveWindow("video", 300, 50);
	cvMoveWindow("foreground", 680, 50);

	if( !(pCapture = cvCaptureFromAVI(VideoName)))
	{
		fprintf(stderr, "Can not open video.\n");
		return -2;
	}

	//逐帧读取视频
	while(pFrame = cvQueryFrame( pCapture ))
	{
		nFrmNum++;

		//如果是第一帧,需要申请内存,并初始化
		if(nFrmNum == 1)
		{
			pResizeFrame  = cvCreateImage(cvSize(VIBE_WIDTH, VIBE_HEIGHT),  IPL_DEPTH_8U,3);
			pFrImg = cvCreateImage(cvSize(VIBE_WIDTH, VIBE_HEIGHT), IPL_DEPTH_8U,1);
			pGrayImg = cvCreateImage(cvSize(VIBE_WIDTH, VIBE_HEIGHT), IPL_DEPTH_8U,1);
			cvResize(pFrame,pResizeFrame,1);
			cvCvtColor(pResizeFrame, pGrayImg, CV_BGR2GRAY);
			VibeForground((unsigned char*)pGrayImg->imageData,(unsigned char*)pFrImg->imageData);
		}
		else
		{
			cvResize(pFrame,pResizeFrame,1);
			cvCvtColor(pResizeFrame, pGrayImg, CV_BGR2GRAY);
			t = (double)cvGetTickCount();
			VibeForground((unsigned char*)pGrayImg->imageData,(unsigned char*)pFrImg->imageData);
			t = (double)cvGetTickCount() - t;
			printf( "exec time = %gms\n", t/(cvGetTickFrequency()*1000));
			
			//显示图像
			cvShowImage("video", pGrayImg);
			cvShowImage("foreground", pFrImg);

			char c=cvWaitKey(5);//显示每一帧之间有5毫秒的间隔

			if(c==27)break;//如果在这间隔期间用户触发Esc按键 循环就退出 否则继续执行循环
		}
	}

	//销毁窗口
	cvDestroyWindow("video");
	cvDestroyWindow("foreground");

	//释放图像和矩阵
	cvReleaseImage(&pFrImg);
	cvReleaseImage(&pGrayImg);
	cvReleaseImage(&pResizeFrame);
	cvReleaseCapture(&pCapture);
	system("pause");
	return 0;
}
 

http://blog.csdn.net/huiguixian/article/details/17334195

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
vibe算法是一种用于目标检测和跟踪的算法,它基于背景模型和像素的相似度来判断是否为前景像素。针对vibe算法的改进可以从以下几个方面考虑: 1. 背景模型更新策略:vibe算法使用了很简单的随机采样方法来更新背景模型,可以尝试更复杂的模型更新策略,例如利用递归滤波或卡尔曼滤波来提高背景的准确性。 2. 像素相似度计算方法:vibe算法使用了基于颜色直方图的方法来计算像素的相似度,可以考虑引入其他更高效准确的相似度计算方法,例如局部二值模式(LBP)或高斯混合模型(GMM)。 3. 前景区域分割:vibe算法在输出前景时,通常会得到一些噪点或无关的区域,可以通过引入形态学操作或连通性分析等方法对前景区域进行进一步的处理和优化。 4. 自适应参数设置:vibe算法的性能很大程度上依赖于参数的设置,可以考虑引入自适应的参数调整策略,根据场景的变化动态地调整算法的参数,以提高算法的适应性和性能。 5. 并行化实现vibe算法可以通过并行化实现来加速计算过程,例如使用GPU或多线程技术来提高算法的运行速度。 综上所述,针对vibe算法的改进可以从背景模型更新策略、像素相似度计算方法、前景区域分割、自适应参数设置和并行化实现等方面进行优化,以提高算法的准确性、鲁棒性和实时性。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值