numpy skimage.transform.warp vs cv2.warpPerspective

rggaifut  于 2023-04-21  发布在  其他
关注(0)|答案(1)|浏览(142)

最近我也遇到了一个主题,即 skimage 几何变换和 opencv 中的等价变换之间的区别。我的目标是替换下面示例中的skimage.transform.warp函数。仅从基本外观来看,它们的工作方式相似,默认情况下borderModeborderValue也是相同的,但我没有收到相同的结果。我错过了什么?

import numpy as np
import skimage.transform
import cv2

img = np.random.rand(16,16)

angle = np.deg2rad(45)
cos_a, sin_a = np.cos(angle), np.sin(angle)
R = np.array([[cos_a, sin_a, -11 * (cos_a + sin_a - 1)],
             [-sin_a, cos_a, -11 * (cos_a - sin_a - 1)],
             [0, 0, 1]])

skimage_rotated = skimage.transform.warp(img, R, clip=False)
cv2_rotated = cv2.warpPerspective(img, R, dsize=skimage_rotated.shape)

print(np.count_nonzero(np.where(np.abs(skimage_rotated - cv2_rotated) > 1e-1)))) #356

plt.imshow(np.abs(skimage_rotated - cv2_rotated))
plt.show()

dddzy1tm

dddzy1tm1#

问题是skimage.transform.warp执行向后转换,而cv2.warpPerspective执行向前转换。
cv2.WARP_INVERSE_MAP标志传递给cv2.warpPerspective解决了这个问题。(我们也可以发明变换矩阵):

cv2_rotated = cv2.warpPerspective(img, R, dsize=skimage_rotated.shape, flags=cv2.INTER_LINEAR+cv2.WARP_INVERSE_MAP)

skimage.transform.warp文档:
skimage.transform.warp(image,inverse_map,map_args=None,...
inverse_maptransformation对象,可调用cr = f(cr,**kwargs)或ndarray

坐标Map,将输出图像中的坐标转换为输入图像中对应的坐标。

cv2.warpPerspective文档:
函数warpPerspective转换源图像...
当标志WARP_INVERSE_MAP被设置时。否则,转换首先使用invert进行inverted,然后将M放入上述公式中。
代码示例:

import numpy as np
import skimage.transform
import cv2
from matplotlib import pyplot as plt

img = np.random.rand(16,16).astype(np.float32)

angle = np.deg2rad(45)
cos_a, sin_a = np.cos(angle), np.sin(angle)
R = np.array([[cos_a, sin_a, -11 * (cos_a + sin_a - 1)],
             [-sin_a, cos_a, -11 * (cos_a - sin_a - 1)],
             [0, 0, 1]])

skimage_rotated = skimage.transform.warp(img, R, clip=False)

#invR = np.linalg.inv(R)
#cv2_rotated = cv2.warpPerspective(img, invR, dsize=skimage_rotated.shape)
cv2_rotated = cv2.warpPerspective(img, R, dsize=skimage_rotated.shape, flags=cv2.INTER_LINEAR+cv2.WARP_INVERSE_MAP)

print(np.count_nonzero(np.where(np.abs(skimage_rotated - cv2_rotated) > 1e-1))) #0

fig, ax = plt.subplots()
im = ax.imshow(np.abs(skimage_rotated - cv2_rotated))
fig.colorbar(im)
plt.show()

np.abs(skimage_rotated - cv2_rotated)

相关问题