最佳缝合线能够有效的去除拼接中运动物体移动出现的鬼影,如何寻找最佳缝合线对于图像拼接去除鬼影比较的重要。寻找最佳缝合线涉及到比较重要的一个思想是动态规划,寻找强度值最优的路径。
关于强度值的计算,具体情况如下:
以上公式是重叠像素点的颜色值之差,是结构值之差。这里的结构值计算采用Sobel算子,也可以考虑其他的边缘检测算子,其中x,y方向的算子如下:
最后寻找最佳缝合线思想,步骤:
1、考虑强度值E的每一列都为一条最佳缝合线,首先从第一行开始,累计添加下一行的强度值;
2、每一列强度值向下一行的左、中、右进行扫描,获取最小的强度累计值,并记录最小强度值的列号;
3、统计出强度值最小的一条做为最佳缝合线。
4、最后根据最佳缝合线进行图像的拼接融合,融合也可以采用改进加权平均融合。
直接看效果图
重影图
最佳缝合线融合图
def optimal_seam_rule_value(self, I1, I2):
I1 = cv2.cvtColor(I1, cv2.COLOR_BGR2GRAY)
I2 = cv2.cvtColor(I2, cv2.COLOR_BGR2GRAY)
Sx = np.array([[-2, 0, 2], [-1, 0, 1], [-2, 0, 2]])
Sy = np.array([[-2, -1, -2], [0, 0, 0], [2, 1, 2]])
I1_Sx = cv2.filter2D(I1, -1, Sx)
I1_Sy = cv2.filter2D(I1, -1, Sy)
I2_Sx = cv2.filter2D(I2, -1, Sx)
I2_Sy = cv2.filter2D(I2, -1, Sy)
E_color = (I1 - I2) ** 2
E_geometry = (I1_Sx - I2_Sx) * (I1_Sy - I2_Sy)
E = E_color + E_geometry
return E.astype(float)
def optimal_seam_rule2(self, I1, I2):
E = self.optimal_seam_rule_value(I1, I2)
# optimal seam
paths_weight = E[0, 1:-1].reshape(1, -1) # Cumulative strength value
paths = np.arange(1, E.shape[1] - 1).reshape(1, -1) # save index
for i in range(1, E.shape[0]):
# boundary process
lefts_index = paths[-1, :] - 1
lefts_index[lefts_index < 0] = 0
rights_index = paths[-1, :] + 1
rights_index[rights_index > E.shape[1] - 1] = E.shape[1] - 1
mids_index = paths[-1, :]
mids_index[mids_index < 0] = 0
mids_index[mids_index > E.shape[1] - 1] = E.shape[1] - 1
# compute next row strength value(remove begin and end point)
lefts = E[i, lefts_index] + paths_weight[-1, :]
mids = E[i, paths[-1, :]] + paths_weight[-1, :]
rights = E[i, rights_index] + paths_weight[-1, :]
# return the index of min strength value
values_3direct = np.vstack((lefts, mids, rights))
index_args = np.argmin(values_3direct, axis=0) - 1 #
# next min strength value and index
weights = np.min(values_3direct, axis=0)
path_row = paths[-1, :] + index_args
paths_weight = np.insert(paths_weight, paths_weight.shape[0], values=weights, axis=0)
paths = np.insert(paths, paths.shape[0], values=path_row, axis=0)
# search min path
min_index = np.argmin(paths_weight[-1, :])
return paths[:, min_index]
另外一篇博客多个路径抵达某点时最小能量和计算,然后通过回溯方式自底向上查找最佳缝合线:动态规划最佳缝合线查找(Image Stitching 3)_基于动态规划算法的最优拼缝查找-CSDN博客