You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

skimage.transform.warp与cv2.warpPerspective结果不一致问题排查

问题

近期遇到一个问题:skimage几何变换与OpenCV中对应函数存在差异。尝试用cv2.warpPerspective替换示例中的skimage.transform.warp函数,二者默认参数(如borderMode、borderValue)看似一致,但输出结果却不相同,请问忽略了什么?

代码示例

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

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()

结果差异可视化

skimage与OpenCV变换结果差异

原因与解决方案

二者结果差异主要来自三个容易忽略的核心区别:

  • 变换矩阵的映射方向相反
    skimage的transform.warp采用反向映射逻辑:为输出图像的每个像素计算其对应输入图像的位置,传入的矩阵是用于从输出坐标反推输入坐标的逆变换矩阵。而OpenCV的warpPerspective采用正向映射逻辑:直接用传入的矩阵将输入像素坐标映射到输出坐标。因此给OpenCV传入的矩阵应为原矩阵的逆矩阵。

  • 输出尺寸的参数格式不同
    OpenCV的dsize参数格式是(宽度, 高度)(对应图像列数、行数),而skimage输出图像的shape是(行数, 列数)。原代码直接传入skimage_rotated.shape会导致尺寸对应错误,需要交换维度顺序。

  • 插值计算的细节差异
    即使修正上述两点,仍可能存在微小数值差异:skimage默认双线性插值的实现细节与OpenCV的INTER_LINEAR(默认插值方式)略有不同,但这种差异通常在1e-5量级,不会出现原代码中大于0.1的显著差异。

修正后的完整代码:

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

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)
# 修正矩阵和尺寸参数
R_inv = np.linalg.inv(R)
cv2_rotated = cv2.warpPerspective(img, R_inv, dsize=(skimage_rotated.shape[1], skimage_rotated.shape[0]), borderMode=cv2.BORDER_CONSTANT, borderValue=0)

print(np.count_nonzero(np.where(np.abs(skimage_rotated - cv2_rotated) > 1e-5))) # 差异像素数大幅减少
plt.imshow(np.abs(skimage_rotated - cv2_rotated))
plt.show()

内容的提问来源于stack exchange,提问作者Pazu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 07:32:48