Faster RCNN源码分析(一)—— 图像预处理

前言

一般数据集中的图像尺寸、通道都是不一致的,因此不管是进行训练还是预测之前,都需要进行尺寸一致化等预处理操作。处理的最终结果是每一个batch中的tensor尺寸一致,但是跨batch不一定一致。

Faster RCNN源码中,将图像预处理操作封装在一个类GeneralizedRCNNTransform中,下面针对这个类进行介绍。

初始化

1
2
3
4
5
6
7
8
9
10
# 接受4个初始化参数,用于初始化4个对应成员
# min_size : 指定允许的最小尺寸
# max_size : 指定允许的最大尺寸
# image_mean : 指定归一化时三个通道各自的均值(默认来自ImageNet)
# image_std : 指定归一化时三个通道各自的方差(默认来自ImageNet)
def __init__(self, min_size, max_size, image_mean, image_std):
self.min_size = min_size # 指定图像的最小边长范围
self.max_size = max_size # 指定图像的最大边长范围
self.image_mean = image_mean # 指定图像在标准化处理中的均值
self.image_std = image_std # 指定图像在标准化处理中的方差

正向过程

接受1个batch的图像和对应的目标信息(预测时无目标),逐个遍历。依次进行:

  1. 维度检查 —— 因为有些数据集通道数还真不一定是3
  2. 归一化 —— 减去方差,除以均值即可
  3. 缩放 —— 因为图像与其目标信息是耦合的因此要同步做,后面细讲
  4. padding —— 真正的尺寸一致化操作
  5. 二次封装 —— 将resize后的图像尺寸与图像封装在一起

缩放

图像缩放

缩放的原则是长和宽等比例缩放。缩放的目的是使得原图像能够最大程度进一个既定尺寸的框中,不管横着放还是竖着放。

这两个条件意味着,缩放之后的图像的长或宽,至少有一个等于这个框的一个边,所谓最大程度嘛。

具体操作时,先用缩放前图像的短边和框的短边产生缩放比例,然后检查长边按照该比例缩放后是否fit,如果超限了那么就要用两个长边产生缩放比例然后再去缩放短边。

box缩放

因为图像的尺寸变了,box的坐标自然也要跟着变。具体操作是,对比原图像和缩放后图像的长产生长度缩放因子,然后将box的两个角点的x坐标乘以该缩放因子。y坐标同理。

padding

经过缩放之后,一个batch内所有图像的尺寸还是不一致,毕竟有横有竖,而且未填满的那一个边的尺寸也不能保证一致。因此,在这一步找一个更大的,刚好能装下这个batch所有图像的框,以左上角对齐的方式进行尺寸一致化,右下角填不满的地方补0。

二次封装

就是简单的将缩放后,padding前的图像尺寸与图像封装称一个结构体ImageList。结构体的两个成员分别是一个表示本batch所有图像的4维tensor和一个记录图像尺寸的List[Tuple[int, int]]

返回

最终,返回一个ImageListd对象和目标信息target。