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++的怀抱吧。一个想哭的我,不说话。
网友评论