• admin
  • 261
  • 2025-12-24 21:17:46

1 总体简介

对图像进行预处理操作的时候,一般有两种缩放方式。

一种是直接宽、高缩放至想要的宽、高,这种方式快捷,但可能会导致图像变形

一种是等比例缩放,然后用灰色边缘填充

step1: 计算宽高缩放比例,选择较小的那个缩放系数;

step2: 计算缩放后的尺寸: 原始图片的长宽都乘以较小的缩放系数;

step3:计算短边需要填充的灰边数,将短边的两边各自填充一半的灰行即可。

2 实现效果

2.1 直接缩放,不怕变形

针对直接缩放的方式,主要代码如下,全部代码实现见最下方

new_image = image.resize((target_w, target_h), Image.BICUBIC)

变形resize

2.2 不变形缩放/letterbox_image

2.2.1 不变形缩放,两端填充灰边

yolov3使用这个方案

不变形resize,两端填充灰边

2.2.2 不变形缩放,一端填充灰边

Yolov5使用这个方案,是Yolov5推理速度能够很快的一个trick

不变形resize,一端填充灰边

很多图片的长宽比不同导致缩放填充后,两端的黑边大小都不同。而如果填充的比较多,则存在信息冗余,影响推理速度。YOLOv5作者对letterbox的缩放策略进行了修改,对原图自适应的添加最少的黑边。

计算方法:

1.计算原始图片宽高与输入尺寸的缩放比例rw和rh,选取r = min(rw,rh)后把原图按r进行缩放

2.原图宽和高中一定有一边完全贴合输入尺寸,没有达到输入尺寸的一边计算与输入尺寸的差值,然后进行上下(or左右)的填充。

3 代码

import matplotlib.pyplot as plt

from PIL import Image

# ---------------------------------------------------#

# 对输入图像进行resize,他人测试发现,不用letterbox_image直接resize的效果更好

# ---------------------------------------------------#

def resize_image(image, size, letterbox_image):

iw, ih = image.size

w, h = size # w=200, h=300

if letterbox_image:

scale = min(w/iw, h/ih)

nw = int(iw*scale)

nh = int(ih*scale)

image = image.resize((nw,nh), Image.BICUBIC)

new_image = Image.new('RGB', size, (128,128,128)) # 新建一张image,第二个参数表示尺寸,第三个参数表示颜色

# --------------------------------------------------#

# image.paste函数表示将一张图片覆盖到另一张图片的指定位置去

# a.paste(b, (50,50)) 将b的左上顶点贴到a的坐标为(50,50)的位置,左上顶点为(0,0), b超出a的部分会被自动舍弃

# ---------------------------------------------------#

# new_image.paste(image, ((w-nw)//2, (h-nh)//2)) # 不变形resize,两端填充灰边

new_image.paste(image, (0, 0)) # 不变形resize,一端填充灰边

else:

new_image = image.resize((w, h), Image.BICUBIC)

return new_image

img_PIL = Image.open("Avatar.jpg")

img = resize_image(img_PIL, (200, 300), True) # 第二参数表示目标尺寸,第三参数表示是否使用letterbox

plt.imshow(img)

plt.show()