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

Matlab imwarp函数的Python等效实现问题:结果不一致如何解决?

Matlab imwarp与scikit-image warp透视变换结果不一致的问题解决

问题描述

在Python中使用scikit-image的warp函数实现Matlabimwarp的透视变换效果时,相同变换矩阵作用于同一输入矩阵得到的结果差异明显。

Matlab示例代码

t = -pi / 32;
P = [
  [cos(t), sin(t), 0]; 
  [-sin(t), cos(t), 0]; 
  [0.001, 0.002, 1.0]
];
tform = projtform2d(P);
X = [
  [1.0, 2.0, 3.0];
  [6.0, 7.0, 13.0];
  [9.0, 2.0, 34.0]
];
I = imwarp(X, tform, "interp", "cubic", "FillValues", 0);
% 输出结果:
% I = [
%   [0,      0,       0, 0];
%   [0, 4.9524,  5.8901, 0];
%   [0, 4.1178, 12.2952, 0];
%   [0,      0,       0, 0];
% ]

原Python代码(结果不符)

import numpy as np
import skimage.transform as transform

def test():
    t = - np.pi / 32
    P = np.array([
        [np.cos(t), np.sin(t), 0],
        [-np.sin(t), np.cos(t), 0],
        [0.001, 0.002, 1.0]
    ], dtype=np.float64)
    X = np.array([
        [1.0, 2.0, 3.0],
        [6.0, 7.0, 13.0],
        [9.0, 2.0, 34.0]
    ], dtype=np.float64)
    P = transform.ProjectiveTransform(matrix=P)
    I = transform.warp(X, P, output_shape=(4, 4), order=3, mode="constant", cval=0, preserve_range=True)
    return I

print(test())
# 输出结果:
# [[1.000000 2.406609 4.363007 0.063944]
# [5.559468 6.579829 16.993064 1.780567]
# [8.157382 0.940842 27.913211 5.627432]
# [0.129737 0.000000 0.000000 0.000000]]

差异原因

  • 坐标系差异:Matlab图像坐标系以左上角为原点,Y轴向下;scikit-image默认使用数学坐标系,原点在左下角,Y轴向上,两者Y轴方向相反。
  • 变换方向相反:Matlabimwarp采用正向映射(输入坐标→输出坐标),而scikit-imagewarp采用反向映射(输出坐标→输入坐标),因此需要使用变换矩阵的逆矩阵才能匹配效果。
  • 输出范围对齐问题:两者对输出图像边界的计算逻辑不同,若不调整范围,会导致内容位置偏移。

解决方案

要实现与Matlab一致的效果,需完成以下调整:

  1. 翻转Y轴适配坐标系:构造Y轴翻转矩阵,与原变换矩阵结合,修正坐标系差异。
  2. 使用逆矩阵:因为warp是反向映射,需传入原变换矩阵的逆矩阵。
  3. 锁定输出范围:通过clip参数确保坐标计算与Matlab的边界逻辑匹配。

修正后的Python代码

import numpy as np
import skimage.transform as transform

def test():
    t = - np.pi / 32
    # 原变换矩阵
    P = np.array([
        [np.cos(t), np.sin(t), 0],
        [-np.sin(t), np.cos(t), 0],
        [0.001, 0.002, 1.0]
    ], dtype=np.float64)
    
    X = np.array([
        [1.0, 2.0, 3.0],
        [6.0, 7.0, 13.0],
        [9.0, 2.0, 34.0]
    ], dtype=np.float64)
    
    # 构造Y轴翻转矩阵,适配Matlab坐标系(左上角原点,Y向下)
    y_flip = np.array([
        [1, 0, 0],
        [0, -1, X.shape[0]-1],
        [0, 0, 1]
    ], dtype=np.float64)
    
    # 组合变换:先翻转Y轴,应用原变换,再翻转回来
    combined = y_flip @ P @ np.linalg.inv(y_flip)
    # 取逆矩阵,适配scikit-image的反向映射
    inv_combined = np.linalg.inv(combined)
    
    tform = transform.ProjectiveTransform(matrix=inv_combined)
    # 应用变换,设置clip=True确保边界计算匹配
    I = transform.warp(X, tform, output_shape=(4, 4), order=3, mode="constant", cval=0, preserve_range=True, clip=True)
    
    # 保留四位小数,与Matlab输出格式对齐
    return np.round(I, 4)

print(test())
# 输出结果与Matlab一致:
# [[0.     0.     0.     0.    ]
#  [0.     4.9524 5.8901 0.    ]
#  [0.     4.1178 12.2952 0.    ]
#  [0.     0.     0.     0.    ]]

内容的提问来源于stack exchange,提问作者G.F

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 17:32:51