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

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
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)=_min, 0, 255).astype(np.uint8) segmap = pos_process(segmap) return segmap 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实现)