1.背景
在做图像分类时,要求输入图像十分规则,例如IMAGENET竞赛采取224×224的图像大小。但是自己准备的数据集往往是从网站中爬取,图像的尺寸不规则。对此本文探讨了一种简便的图像处理办法。
2.讨论
将size不规则的图像变为规则图像存在很多方法,最简单的就是直接resize,比如keras给出了一种解决方案,可通过调用“image_dataset_from_directory”API对图像进行resize,但是这种方法会导致图像变形,如图1和图2所示。在实际应用中,图像形变是不被期望的,容易给结果增加不确定性。
此时不妨提出一种简单的处理办法来解决形变问题。即选取图像的最短边为基准边规定一个正方形边框,使之在图像范围内随机滑动,剪裁出图像中的正方形子区域而不溢出图像,然后在缩放到预设定的图像大小。这样做的好处在于在训练时可以一定程度上起到数据增强的作用,同时避免了产生形变。在推理阶段,对输入图像做中心剪裁,缩放后送入网络进行预测。该方法效果如下,图3为原图,图4-图7为本文方法,图8用于推理阶段。
下面是简单的数学推演:
假设现有图像高和宽,我们选取最短边L作为基准边,将会产生下图中红色正方形框,款内图像为剪裁图像。输入图像有一个图像中心O,中心坐标为(cx, cy),红色边界框也有个中心,这个中心的移动范围就是线段AB。下面需要做的就是让红色正方形框的中心随机出现在线段AB上就可以了。实现步骤上假定该正方形中心框与O点重合,然后生成[-1,+1]区间内的随机数k,让k乘以线段AO的距离以便生成改变量Δx,最后计算Δx+cx便可以得到红色框的中心坐标。
3.实现
实现代码
import random
from PIL import Image
from matplotlib import pyplot as plt
img = Image.open('tem/0/DGQZDS_36.jpg') # 打开图像
img_w, img_h = img.size
img_l = min(img_w, img_h) # 正方形框边长
cx, cy = img_w // 2, img_h // 2 # 图像中心
for training in range(2):
if training:
k = random.uniform(-1, 1) # 随机系数
if img_w >= img_h:
distance = k * (img_w // 2 - img_l // 2)
cx += distance # 沿着x轴平移中心坐标
else:
distance = k * (img_h // 2 - img_l // 2)
cy += distance # 沿着y轴平移中心坐标
# 图像剪裁
img_crop = img.crop(
(
int(max(0, (cx - img_l // 2))),
int(max(0, (cy - img_l // 2))),
int(min((cx + img_l // 2),img_w)),
int(min((cy + img_l // 2),img_h))
)
)
# 图像缩放
img_crop_resize = img_crop.resize((224, 224), Image.ANTIALIAS)
plt.figure("training:{}".format(training))
plt.imshow(img_crop_resize)
plt.show()