美文网首页蓉蓉的计算机视觉打怪之路
运动目标检测vibe算法及其改进Python实现

运动目标检测vibe算法及其改进Python实现

作者: 涂山容容 | 来源:发表于2019-11-06 19:48 被阅读0次

    vibe是一个又简单又牛逼的算法,没有什么数学公式,就只有三步

    1.初始化背景模型,总共有20个背景模型样本,每个样本中的每个点由其八邻域初始化(论文里面没有用到自己这个像素点,看了其他的改进,有用自己的,这个没必要较真,大家都是试出来的,不一定适合每个场景)。

    2.前景背景判定 新来的每一帧与背景模型做比较,如果新的帧的点与背景模型中样本的点的像素值大小不超过20(20是个经验值

    在网上搜了一下,实现的版本,emm,速度真的是太慢了,慢的想要哭,but自己要用啊,这个速度真的是不能接受的,那怎么办呢,只好优化一下,虽然自己也是菜鸡,只能简单的搞一搞了。

    添加了动态阈值与后处理,有效的减少了误检。

    感觉后处理是万能的,可以过滤掉好多东西

    参考的代码

    https://github.com/yangshiyu89/VIBE

    通过profile分析了一下,瓶颈主要是在随机数生成上,所以,要减少随机数生成的次数。然后就是for循环慢,能改就尽量改成numpy。

    def bg_update(I_gray,seg_mask,samples, sub_factor, fg_mask_counts):
        height, width = seg_mask.shape
        x_y_set = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]]
        neighbor_num = len(x_y_set)
        for i in range(height):
            for j in range(width):
    
                if not seg_mask[i,j]:
                    fg_mask_counts[i, j] = 0
     r = np.random.randint(0, sub_factor)
                    if r == 0:
                        r = np.random.randint(0, sample_num)
                        samples[i, j, r] = I_gray[i, j]
                    r = np.random.randint(0, sub_factor)
                    if r == 0:
                        # x, y = random.choice(x_y_set)
     rnd = np.random.randint(0, neighbor_num)
    
                        r = np.random.randint(0, sample_num)
                        ri = i + x_y_set[rnd][0]
                        rj = j + x_y_set[rnd][1]
                        try:
                            if not seg_mask[ri, rj]:
                                samples[ri, rj, r] = I_gray[i, j]
                        except:
                            pass
     else:
                    fg_mask_counts[i, j] += 1
     if fg_mask_counts[i, j] > 200:
                        r = np.random.randint(0, sub_factor)
                        if r == 0:
                            r = np.random.randint(0, sample_num)
                            samples[i, j, r] = I_gray[i, j]
        return samples, fg_mask_counts</pre>
    
    def get_segmap(I_gray, samples, _min, sample_num, radius):
        height = I_gray.shape[0]
        width = I_gray.shape[1]
    
        distance = np.zeros((height, width, sample_num)).astype(np.int8)
        for i in range(sample_num):
            distance[:, :, i] = I_gray - samples[:, :, i]
    
        distance = np.abs(distance)
    
        '''动态阈值'''   
    mean_distance = np.average(distance, axis=-1).astype(np.uint8)
        #radius_adp= np.where((5 * mean_distance)<radius,radius-mean_distance,radius+mean_distance)
     radius_adp = np.where((5 * mean_distance) < radius, radius-0.5*mean_distance, radius + 0.2*mean_distance)
        radius_adp = np.repeat(radius_adp[:,:,np.newaxis],sample_num,axis=2)
        counts = np.sum(distance<radius_adp, axis=-1)
        '''动态阈值end'''  
     '''固定阈值'''
     # counts = np.sum(distance < radius, axis=-1)
     '''固定阈值end'''
     segmap = np.where(counts>=_min, 0, 255).astype(np.uint8)
        segmap = pos_process(segmap)
        return segmap</pre>
    
    def initial_background(I_gray, sample_num):
    
        height = I_gray.shape[0]
        width = I_gray.shape[1]
    
        samples = np.zeros((height, width, sample_num))
        fg_mask = np.zeros((height, width))
        #3邻域
     x_y_set =[[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]]
        #5邻域
     # x_y_set = [[-2, -2], [-2, -1], [-2, 0], [-2, 1], [-2, 2], [-1, -2], [-1, -1], [-1, 0], [-1, 1], [-1, 2], [0, -2], [0, -1], [0, 0], [0, 1], [0, 2], [1, -2], [1, -1], [1, 0], [1, 1], [1, 2], [2, -2], [2, -1], [2, 0], [2, 1], [2, 2]]     neighbor_num = len(x_y_set)
        for i in range(height):
            for j in range(width):
                for n in range(sample_num):
                    rnd = np.random.randint(0, neighbor_num)
                    ri = i + x_y_set[rnd][0]
                    rj = j + x_y_set[rnd][1]
                    if ri< 0:
                        ri = 0
     if ri >= height:
                        ri = height-1
     if rj < 0:
                        rj = 0
     if rj >= width:
                        rj = width-1   #
     # x, y = random.choice(x_y_set) # ri = i + x # rj = j + y samples[i, j, n] = I_gray[ri, rj]
    
        return samples, fg_mask
    

    后处理才是万能的,怎么去处理缝隙啊,还有阴影啊。虽然文章挺老的,但是效果好啊。
    最后就是Python真的是蜗牛,和c++比的话,所以,要是对时间有要求的话,还是转投c++的怀抱吧。一个想哭的我,不说话。

    相关文章

      网友评论

        本文标题:运动目标检测vibe算法及其改进Python实现

        本文链接:https://www.haomeiwen.com/subject/kbrpbctx.html