在不使用 opencv 的情况下在 python 中应用 Homography 变换
Posted
技术标签:
【中文标题】在不使用 opencv 的情况下在 python 中应用 Homography 变换【英文标题】:Applying Homography transformation in python without using opencv 【发布时间】:2022-01-15 13:13:30 【问题描述】:给定一个输入图像和单应矩阵,我想在转换后得到一个输出图像。
这是ndimage中的内置函数:
im = np.array(Image.open('lena.jpg').convert('L'))
H = np.array([[1.4,0.05,-100],[0.05,1.5,-100],[0,0,1]])
im2 = ndimage.affine_transform(im, H[:2,:2], (H[0,2], H[1, 2]))
imshow(im)
imshow(im2)
对于原始图像,我看到了这个:
对于 ndimage 转换后的 im2,我看到了这个:
现在我想编写一个只使用 python 和 numpy 库的代码来自己做这个单应性。这是我写的代码:
left, up = 0, 0
right, down = im.shape[1], im.shape[0]
# define the homography operation
def get_point_coor(x, y, H):
input = np.array(([x], [y], [1]))
output = np.dot(H, input)
return int(output[0]), int(output[1])
# after transformation the image size might be different from the original one,
# we need to find the new size
height_max = max(get_point_coor(left, up, H)[0], get_point_coor(left, down, H)[0], get_point_coor(right, up, H)[0], get_point_coor(right, up, H)[0])
width_max = max(get_point_coor(left, up, H)[1], get_point_coor(left, down, H)[1], get_point_coor(right, up, H)[1], get_point_coor(right, up, H)[1])
height_min = min(get_point_coor(left, up, H)[0], get_point_coor(left, down, H)[0], get_point_coor(right, up, H)[0], get_point_coor(right, up, H)[0])
width_min = min(get_point_coor(left, up, H)[1], get_point_coor(left, down, H)[1], get_point_coor(right, up, H)[1], get_point_coor(right, up, H)[1])
# can ignore this 50 now. The new_height without 50 should be able to be the new boundary
# , but somehow it is not, so I add a random big number (50) for ploting.
new_height = abs(height_max) + abs(height_min)+50
new_width = abs(width_max) + abs(width_min)+50
new_image = np.zeros((new_height, new_width))
# start the main
for row in range(im.shape[0]):
for col in range(im.shape[1]):
new_row, new_col = get_point_coor(row, col, H)
new_col += abs(width_min)
new_row += abs(height_min)
new_image[new_row, new_col] = im[row][col]
imshow(new_image)
我得到的结果是这样的:
方向、颜色和大小看起来都与 ndimage 非常不同。实现这个单应性的正确方法是什么?
【问题讨论】:
反转单应性。然后,对于每个结果像素位置,将其粘贴在倒置矩阵中(如果它是真正的单应性而不仅仅是仿射,您还需要除以“w”坐标,以便得到(?, ?, 1)
) ,然后您将获得需要采样的 source 中的像素位置。 ——你做错了。你不能 push 像素。这会留下间隙和其他令人讨厌的伪影。
您在图像中看到的是 scipy.ndimage.affine_transform
不 反转矩阵。它假设矩阵已经反转(即向后)。始终阅读您正在使用的文档,并努力理解所有内容:docs.scipy.org/doc/scipy/reference/generated/…
另外,您的最小/最大内容会删除结果中矩阵的翻译分量,因此您看不到它的效果...
【参考方案1】:
很抱歉,但您犯了一个初学者的错误:如果您扫描源图像并将像素复制到变换坐标处的目标,您会得到很差的结果:要么点太密集,要么相互碰撞,或太稀疏而留下孔洞。
正确的做法是扫描目的地并使用逆变换得到源坐标。
由于源坐标通常不是整数,您可以将它们四舍五入,或者为了获得更好的质量,在源像素之间使用双线性或双三次插值。
出现第二个困难:由于目标域是一般的四边形,您应该只绘制内部像素,并且需要对轮廓进行光栅扫描转换。或者,您可以填充此四边形的边界框,并在源像素超出边界时指定背景颜色。
【讨论】:
以上是关于在不使用 opencv 的情况下在 python 中应用 Homography 变换的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用转储的情况下在 python 中编写 json 文件
如何在不传递引用的情况下在 Python 中使用 SyncManager 跨进程共享列表
想要在不使用 Scikit-Learn 的情况下在 python 中构建支持向量机的真正建议 [关闭]
仅在不存在的情况下在 Python 中注册 Prometheus 指标