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

Python仿射变换无法按预期旋转缩放图像问题求助

仿射变换图像旋转缩放问题排查

问题概述

尝试通过Python代码对图像执行旋转+缩放的仿射变换,但输出结果不符合预期:原始图像为letterR.jpg,预期得到旋转缩放后的清晰字母R,实际仅显示零散像素点。运行无报错,多机器执行结果一致。

原始代码

import matplotlib.pyplot as plt
import numpy as np

img = matplotlib.pyplot.imread('letterR.jpg')
T = np.array([[0, 2, 0],
             [-2, 0, 0],
             [0, 0, 1]])

img_transformed = np.empty((2000, 2000, 4), dtype=np.uint8)
for i, row in enumerate(img):
    for j, col in enumerate(row):
        pixel_data = img[i, j, :]
        input_coords = np.array([i, j, 1])
        i_out, j_out, _ = T @ input_coords
        img_transformed[i_out, j_out, :] = pixel_data

plt.figure(figsize=(5, 5))
plt.imshow(img_transformed)

问题原因分析

  • 坐标对应关系错误:图像的行索引i对应y轴,列索引j对应x轴,但代码直接将(i,j)作为坐标输入变换矩阵,导致变换方向完全偏离预期。
  • 正向映射逻辑缺陷:当前代码是把原始像素坐标通过矩阵映射到目标图像,这会导致目标图像的绝大多数像素没有被赋值(仅原始像素对应的离散位置有值),最终呈现零散像素。正确逻辑应为反向映射:遍历目标图像的每个像素,反向计算其在原始图像中的对应位置,再采样赋值。
  • 矩阵语法隐患:原始代码中变换矩阵T的第二行末尾缺少逗号,虽未触发报错,但属于语法不规范问题。
  • 坐标处理不严谨:变换后的坐标可能为负数或超出目标图像尺寸,直接作为索引会导致错误赋值;同时矩阵运算结果为浮点数,直接截断为整数会引发采样偏差。

修复方案

核心修正点

  1. 改用反向映射逻辑,确保目标图像每个像素都能找到对应的原始图像采样点
  2. 修正坐标与轴的对应关系(x对应列,y对应行)
  3. 使用变换矩阵的逆矩阵进行反向计算
  4. 增加坐标范围校验,避免越界采样

修复后的代码

import matplotlib.pyplot as plt
import numpy as np

# 读取图像并获取尺寸
img = plt.imread('letterR.jpg')
img_h, img_w, _ = img.shape

# 定义正向变换矩阵:顺时针旋转90度 + 缩放2倍
T = np.array([
    [0, 2, 0],
    [-2, 0, 0],
    [0, 0, 1]
])
# 计算逆矩阵用于反向映射
T_inv = np.linalg.inv(T)

# 目标图像尺寸
target_h, target_w = 2000, 2000
# 用0初始化目标图像(避免空数组的随机噪点)
img_transformed = np.zeros((target_h, target_w, 4), dtype=np.uint8)

# 遍历目标图像的每个像素
for y_out in range(target_h):
    for x_out in range(target_w):
        # 将目标坐标转为齐次坐标
        target_coord = np.array([x_out, y_out, 1])
        # 反向计算原始图像中的对应坐标
        x_in, y_in, _ = T_inv @ target_coord
        
        # 校验坐标是否在原始图像范围内
        if 0 <= x_in < img_w and 0 <= y_in < img_h:
            # 最近邻采样(如需更平滑效果可改用双线性采样)
            x_in_int = int(round(x_in))
            y_in_int = int(round(y_in))
            img_transformed[y_out, x_out, :] = img[y_in_int, x_in_int, :]

plt.figure(figsize=(5, 5))
plt.imshow(img_transformed)
plt.show()

额外优化建议

  • 若需要更平滑的变换效果,可将最近邻采样替换为双线性采样,计算周围四个像素的加权平均值
  • 可通过计算变换后图像的边界范围,调整目标画布的尺寸和位置,避免图像被裁剪或出现大量空白区域

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 11:52:41