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

Python/PyTorch下如何将不等尺寸图像调整为固定大小并保持宽高比

保持宽高比输出固定尺寸图像的实现方案

要在不拉伸变形的前提下输出严格固定尺寸的图像,核心逻辑是等比缩放+边缘填充(Letterbox):先按比例缩放图像,让图像完整适配目标尺寸的边界,再把缩放后不足的边缘区域用固定颜色填充,最终输出严格符合要求的尺寸。你之前用的方法只做了缩放步骤,没有填充逻辑,自然没法在原图尺寸偏小/宽高比和目标不匹配时输出固定尺寸。


方案1:纯PIL实现(无深度学习框架依赖)

这个方案兼容所有尺寸的输入,不管原图比目标尺寸大还是小都能正常输出,不会出现拉伸、尺寸不达标的问题:

from PIL import Image

def resize_keep_aspect(img, target_size=(128, 128), pad_color=(0, 0, 0)):
    origin_w, origin_h = img.size
    target_w, target_h = target_size
    # 取宽高缩放比的最小值,保证缩放后图像完全落在目标尺寸范围内
    scale_ratio = min(target_w / origin_w, target_h / origin_h)
    new_w = int(round(origin_w * scale_ratio))
    new_h = int(round(origin_h * scale_ratio))
    
    # 等比缩放,新版本PIL用LANCZOS替代旧的ANTIALIAS,缩放画质更好
    resized = img.resize((new_w, new_h), Image.Resampling.LANCZOS)
    
    # 新建目标尺寸的画布,填充指定底色
    canvas = Image.new(img.mode if img.mode in ("RGB", "L") else "RGB", target_size, pad_color)
    # 把缩放后的图像贴到画布居中位置
    offset_x = (target_w - new_w) // 2
    offset_y = (target_h - new_h) // 2
    canvas.paste(resized, (offset_x, offset_y))
    return canvas

使用时直接替换你之前调用的Image.resize()、Image.thumbnail()、ImageOps.contain()即可,输出永远是严格的128×128尺寸。填充颜色可以根据数据集调整,比如用数据集像素均值、常用的中性灰(114,114,114),减少填充区域对模型的干扰。


方案2:PyTorch 生态实现

torchvision 官方已经内置了和上述逻辑完全一致的接口,不用重复造轮子,可以直接接入你现有的transforms流水线:

from torchvision import transforms
from torchvision.transforms import functional as F

# 自定义可复用的变换类
class ResizeKeepAspect(transforms.Resize):
    def forward(self, img):
        return F.resize_with_pad(
            img,
            size=self.size,
            interpolation=F.InterpolationMode.BILINEAR,
            fill=0, # 自定义填充颜色
            antialias=self.antialias
        )

# 接入数据预处理流水线
data_transform = transforms.Compose([
    ResizeKeepAspect((128, 128), antialias=True),
    transforms.ToTensor(),
    # 后续可以接归一化、增强等其他操作
])

之前方法失效的原因说明

  • Image.thumbnail()是原地操作,只会对大于目标尺寸的图像做缩小,不会放大小于目标尺寸的图像,输出尺寸永远小于等于目标尺寸。
  • ImageOps.contain()逻辑和thumbnail类似,仅保证图像不超出目标尺寸边界,不会做填充补边,自然没法输出严格固定的尺寸。
  • 直接传入元组参数调用transforms.Resize((128,128))会强制将图像宽高直接拉伸到目标值,完全忽略原始宽高比,必然会导致图像变形。

如果是做目标检测、关键点检测这类需要映射原图坐标的任务,只需要在上述函数中把缩放比例、填充偏移量作为额外返回值输出,就可以直接用来还原坐标,逻辑完全通用。

内容的提问来源于stack exchange,提问作者Ammar Ul Hassan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:36:17