在不使用 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 指标

如何在不使用临时文件的情况下在 python 的 tarfile 中写入大量数据

如何在不安装的情况下在应用程序中使用 Berkeley DB