MXNet的数据预处理:mxnet.image.CreateAugmenter源码详解

这篇博文要介绍的mxnet.image.CreateAugmenter是承接前面一篇博文:MXNet如何用mxnet.image.ImageIter直接导入图像,在那篇博文中介绍了如何用ImageIter类导入图像,如下代码(修改后的data.py脚本):

train = mx.image.ImageIter(
        batch_size          = args.batch_size,
        data_shape          = (3,224,224),
        label_width         = 1,
        path_imglist        = args.data_train,
        path_root           = args.image_train,
        part_index          = rank,
        shuffle             = True,
        data_name           = 'data',
        label_name          = 'softmax_label',
        aug_list            = mx.image.CreateAugmenter((3,224,224),resize=224,rand_crop=True,rand_mirror=True,mean=True))

可以看出在ImageIter类中主要通过调用image.py脚本中的CreateAugmenter()函数来实现数据预处理,这个函数的细节在image.py脚本中,脚本image.py可以在~/mxnet/python/mxnet/image.py找到。接下来主要看看这个脚本中的这个重要的函数:CreateAugmenter(),重点可以看代码中的注释。

CreateAugmenter()函数:

def CreateAugmenter(data_shape, resize=0, rand_crop=False, rand_resize=False, rand_mirror=False,mean=None, 
std=None, brightness=0, contrast=0, saturation=0,
                    pca_noise=0, inter_method=2):
    """Creates an augmenter list."""
    auglist = []


# resize这个参数很重要,一般都要做resize,如果你的resize参数设置为224,你的原图像是350*300,那么最后resize的大小就是
# (350*300/224)*224。这里ResizeAug()函数调用resize_short()函数,resize_short()函数调用OpenCV的imresize()函数完成resize
# ,interp参数为2表示采用双三次插值做resize,可以参考:http://docs.opencv.org/master/da/d54/group__imgproc__transform.html。
    if resize > 0:
        auglist.append(ResizeAug(resize, inter_method))

    crop_size = (data_shape[2], data_shape[1])

# 如果rand_resize参数是true,那么会调用RandomSizedCropAug()函数,输入是size,min_area,retio,interp,
# 这个函数既做resize又做crop,因此这边才会写成if elif的语句。RandomSizedCropAug()函数调用random_size_crop()函数,
# 这个函数会先生成随机的坐标点和长宽值,然后调用fixed_crop()函数做crop。
#这里还有一个语句是assert rand_crop,python的assert语句是用来声明其布尔值必须为真,如果表达式为假,就会触发异常。
# 也就是说要调用RandomSizedCropAug()函数的前提是rand_crop是True。
    if rand_resize:
        assert rand_crop
        auglist.append(RandomSizedCropAug(crop_size, 0.3, (3.0 / 4.0, 4.0 / 3.0), inter_method))

#如果rand_crop参数是true,表示随机裁剪,randomCropAug()函数的输入之一是crop_size,
# 这个crop_size就是CreateAugmenter()函数的输入data_shape的图像大小,然后randomCropAug()函数调用random_crop()函数,
# random_crop()函数会先生成新的长宽值和坐标点,然后以此调用fixed_crop()函数做crop,
# 最后返回crop后的图像和坐标即长宽值,因为生成中心坐标点的时候是随机的,所以还是random crop。
    elif rand_crop:
        auglist.append(RandomCropAug(crop_size, inter_method))

# 如果前面两个if条件都不满足,就调用CenterCropAug()函数做crop,这个函数的输入也包括了crop_size,也就是你的输入data_shape,
# 所以这个参数是很有用的。CenterCropAug()函数调用center_crop()函数,这个函数的输入输出都是NDArray格式。
# center_crop()函数和random_crop()函数的区别在于前者坐标点的生成不是随机的,而是和原图像一样,
# 然后再将坐标点和新的长宽作为fixed_crop()函数的输入。
    else:
        auglist.append(CenterCropAug(crop_size, inter_method))
#可以看出不管你是否要做crop,只要你给定了data_shape参数,就默认要将输入图像做crop操作。
# 因此如果你不想在test的时候做crop,可以在这修改源码。

# 随机镜像处理,参数是0.5,HorizontalFlipAug()函数调用nd.flip()函数做水平翻转
    if rand_mirror:
        auglist.append(HorizontalFlipAug(0.5))


# CastAug()函数主要是将数据格式转化为float32
    auglist.append(CastAug())


# 这三个参数分别是亮度,对比度,饱和度。当你对这三个参数设置了值,
# 就会调用ColorJitterAug()函数对其相应的亮度或对比度或饱和度做改变
    if brightness or contrast or saturation:
        auglist.append(ColorJitterAug(brightness, contrast, saturation))


# 这个部分主要是添加pca噪声的,具体可以看LightingAug()函数
    if pca_noise > 0:
        eigval = np.array([55.46, 4.794, 1.148])
        eigvec = np.array([[-0.5675, 0.7192, 0.4009],
                           [-0.5808, -0.0045, -0.8140],
                           [-0.5836, -0.6948, 0.4203]])
        auglist.append(LightingAug(pca_noise, eigval, eigvec))


# mean这个参数主要是和归一化相关。这里的assert语句前面已经介绍过了。mean参数默认是None,这种情况下是不会进入下面的if elif条件函数的。
# 如果想进行均值操作,可以设置mean为True,那么就会进入第一个if条件,如果你设置为其他值,就会进入elif条件,
# 这个时候如果你的mean不符合要求,比如isinstance函数用来判断类型,就会触发异常。
    if mean is True:
        mean = np.array([123.68, 116.28, 103.53])
    elif mean is not None:
        assert isinstance(mean, np.ndarray) and mean.shape[0] in [1, 3]

# std与mean同理
    if std is True:
        std = np.array([58.395, 57.12, 57.375])
    elif std is not None:
        assert isinstance(std, np.ndarray) and std.shape[0] in [1, 3]

# 这里需要mean和std同时都设置正确才能进行预处理,如果你只设置了mean,没有设置std,那么还是没有启动归一化的预处理。
# 这里主要调用ColorNormalizeAug()函数,这个函数调用color_normalize()函数,这个函数的实现很简单,
# 就是将原图像的像素值减去均值mean,然后除以标准差std得到返回值。
    if mean is not None and std is not None:
        auglist.append(ColorNormalizeAug(mean, std))

# 最后返回预处理的列表
    return auglist
要将Kaggle的数字识别(Digit Recognizer)数据转化为`mxnet.gluon.data.dataloader.DataLoader`格式,你可以按照以下步骤进行操作: 1. 导入必要的库: ```python import numpy as np import pandas as pd import mxnet as mx from mxnet.gluon.data import Dataset, DataLoader ``` 2. 加载训练数据集: ```python train_data = pd.read_csv('train.csv') ``` 3. 定义自定义数据集: ```python class DigitDataset(Dataset): def __init__(self, data, transform=None): self.data = data self.transform = transform def __getitem__(self, idx): image = np.array(self.data.iloc[idx, 1:]).reshape(28, 28, 1).astype(np.float32) / 255.0 label = np.array(self.data.iloc[idx, 0]) if self.transform: image = self.transform(image) return image, label def __len__(self): return len(self.data) ``` 在这个自定义数据集中,我们将图像数据转化为`np.float32`型,并将像素值缩放到0-1范围内。你也可以根据需要添加其他的数据转换操作。 4. 创建数据集实例并进行数据转换(如果需要的话): ```python dataset = DigitDataset(train_data) ``` 5. 创建`DataLoader`实例: ```python batch_size = 32 dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True) ``` 在这里,设置了批量大小(`batch_size`),并选择是否对数据进行洗牌(`shuffle=True`)。 现在,你可以使用`dataloader`来迭代访问你的数据集。每次迭代将返回一个批量的图像和标签。 希望这能帮助到你!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值