运动检测ViBe算法python实现

运动物体检测一般分为背景建模和运动物体分析两步。即构建不包含运动物体的背景模型。然后将新的视频帧和背景模型对比,找出其中的运动物体。目前比较好的背景建模算法有两种:1)文章(Zivkovic Z. (2004) Improved adaptive Gausianmixture model for  backgroundsubtraction, Proceedings of ICPR 2004, August 23-26, Cambridge, UK.)提出的高斯混合模型法。在此算法中,背景的每一个像素都被拟合到一个高斯混合模型。对于新的图片,只需要判断每个像素是否服从这个高斯混合模型就可以判断出这个像素是背景还是前景。但混合高斯算法的缺点是计算量相对比较大,速度偏慢,对光照敏感。2)文章(ViBe: A universal backgroundsubtraction algorithm for video sequences.)提出的ViBe算法。该算法速度非常快,计算量比较小,而且对噪声有一定的鲁棒性,检测效果不错。

由于最近在做一些跟踪检查的研究,就用到了ViBe算法,根据网上的c++版本编写了这个python版的算法,在这分享给大家。


class ViBe:
    '''
    classdocs
    '''
    __defaultNbSamples = 20        #每个像素点的样本个数
    __defaultReqMatches = 2        #min指数
    __defaultRadius = 20;          #Sqthere半径
    __defaultSubsamplingFactor = 16#子采样概率
    __BG = 0                       #背景像素
    __FG = 255                     #前景像素
    __c_xoff=[-1,0,1,-1,1,-1,0,1,0]  #x的邻居点 len=9
    __c_yoff=[-1,0,1,-1,1,-1,0,1,0]  #y的邻居点 len=9
    
    __samples=[]              #保存每个像素点的样本值,len defaultNbSamples+1
    __Height = 0
    __Width = 0

    def __init__(self, grayFrame):
        '''
        Constructor
        '''
        self.__Height = grayFrame.shape[0]
        self.__Width = grayFrame.shape[1]
        

        for i in range(self.__defaultNbSamples+1):
            self.__samples.insert(i,np.zeros((grayFrame.shape[0],grayFrame.shape[1]),dtype=grayFrame.dtype));
            
        self.__init_params(grayFrame)
      
    def __init_params(self,grayFrame):
        #记录随机生成的 行(r) 和 列(c)
        rand=0
        r=0
        c=0

        #对每个像素样本进行初始化
        for y in range(self.__Height):
            for x in range(self.__Width):
                for k in range(self.__defaultNbSamples):
                    #随机获取像素样本值
                    rand=random.randint(0,8)
                    r=y+self.__c_yoff[rand]
                    if r<0:
                        r=0
                    if r>=self.__Height: 
                        r=self.__Height-1    #行
                    c=x+self.__c_xoff[rand]
                    if c<0:
                        c=0 
                    if c>=self.__Width:
                        c=self.__Width-1     #列
                    #存储像素样本值
                    self.__samples[k][y,x] = grayFrame[r,c]
            self.__samples[self.__defaultNbSamples][y,x] = 0
            
    def update(self,grayFrame,frameNo):
        foreground = np.zeros((self.__Height,self.__Width),dtype=np.uint8)
        for y in range(self.__Height):    #Height
            for x in range(self.__Width):     #Width
                #用于判断一个点是否是背景点,index记录已比较的样本个数,count表示匹配的样本个数
                count=0;index=0;
                dist=0.0;
                while (count<self.__defaultReqMatches) and (index<self.__defaultNbSamples):
                    dist= float(grayFrame[y,x]) - float(self.__samples[index][y,x]);
                    if dist<0: dist=-dist
                    if dist<self.__defaultRadius: count = count+1
                    index = index+1

                if count>=self.__defaultReqMatches:
                    #判断为背景像素,只有背景点才能被用来传播和更新存储样本值
                    self.__samples[self.__defaultNbSamples][y,x]=0
    
                    foreground[y,x] = self.__BG
    
                    rand=random.randint(0,self.__defaultSubsamplingFactor)
                    if rand==0:
                        rand=random.randint(0,self.__defaultNbSamples)
                        self.__samples[rand][y,x]=grayFrame[y,x]
                    rand=random.randint(0,self.__defaultSubsamplingFactor)
                    if rand==0:
                        rand=random.randint(0,8)
                        yN=y+self.__c_yoff[rand]
                        if yN<0: yN=0
                        if yN>=self.__Height: yN=self.__Height-1
                        rand=random.randint(0,8)
                        xN=x+self.__c_xoff[rand]
                        if xN<0: xN=0
                        if xN>=self.__Width: xN=self.__Width-1
                        rand=random.randint(0,self.__defaultNbSamples)
                        self.__samples[rand][yN,xN]=grayFrame[y,x]
                else:
                    #判断为前景像素
                    foreground[y,x] = self.__FG;
                    self.__samples[self.__defaultNbSamples][y,x] += 1
                    if self.__samples[self.__defaultNbSamples][y,x]>50:
                        rand=random.randint(0,self.__defaultNbSamples)
                        if rand==0:
                            rand=random.randint(0,self.__defaultNbSamples)
                            self.__samples[rand][y,x]=grayFrame[y,x]
        return foreground

我做的鱼的跟踪效果图


  • 12
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 82
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 82
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值