AI备忘录 - 数据增强
type: channel
link: http://www.aiuai.cn/tag/数据增强
items: 计算机视觉之数据增强
items: 无监督学习-MoCoV1&V2
items: Github项目 - AutoAugment 数据增强策略实现
items: Github 项目 - BackgroundMattingV2 之数据集函数
items: torchvision - transform 数据增强
items: Python - 语义分割数据增强实现
items: Github 项目 - NVIDIA DALI 加速库[旧]
items: Github 项目 - PaddleSeg 数据增强策略
items: Pytorch - 图像变换函数集合
items: SSD(Single Shot Detector) 中的数据增强[译]

计算机视觉之数据增强
type: item
date: 2021-09-09T12:08:00+00:00
description: 出处：Paddle文档平台 - 图像增广1. 数据增广在图像分类任务中，图像数据的增广是一种常用的正则化方法，主要用于增加训练数据集，让数据集尽可能的多样化，使得训练的模型具有更强的泛化能力，常用于数据量不足或者模型参数较多的场景。除了 ImageNet 分类任务标准数据增广方法外，还有8种数据增广方式非常常用，这里对其进行简单的介绍和对比，这8种数据增广方式在ImageNet上的精度指标如 图1 所示。图1 8种数据增广方法2. 常用数据增广方法注：如果没有特殊说明，所有示例均为 ImageNet 分类，并且假设最终输入网络的数据维度为：[batch-size, 3, 224, 224]在ImageNet 分类任务中，训练阶段的标准数据增广方法为以下几步：[1] - 图像解码：简写为 ImageDecode[2] - 随机裁剪到长宽均为 224 的图像：简写为 RandCrop[3] - 水平方向随机翻转：简写为 RandFlip[4] - 图像数据的归一化：简写为 Normalize[5] - 图像数据的重排，[224, 224, 3] 变为 [3, 224, 224]：简写为 Transpose[6] - 多幅图像数据组成 batch 数据，如 batch-size 个 [3, 224, 224] 的图像数据拼组成 [batch-size, 3, 224, 224]：简写为 Batch相比于上述标准的图像增广方法，研究者也提出了很多改进的图像增广策略，这些策略均是在标准增广方法的不同阶段插入一定的操作，基于这些策略操作所处的不同阶段，我们将其分为了三类：[1] - 对 RandCrop (上述的阶段2)后的 224 的图像进行一些变换: AutoAugment，RandAugment[2] - 对Transpose (上述的阶段5)后的 224 的图像进行一些裁剪: CutOut，RandErasing，HideAndSeek，GridMask[3] - 对 Batch(上述的阶段6) 后的数据进行混合: Mixup，Cutmix增广后的可视化效果如 图2 所示。图2 数据增广后可视化下文将介绍这些策略的原理与使用方法，其中，每种数据增广策略的参考论文与参考开源代码均在下面的介绍中列出。以 图3 为测试图像，第三节将基于测试图像进行变换，并将变换后的效果进行可视化。由于RandCrop是随机裁剪，变换前后的图像内容可能会有一定的差别，无法直观地对比变换前后的图像。因此，本节将 RandCrop 替换为 Resize。图3 测试图像3. 图像变换类图像变换类指的是对 RandCrop 后的224 的图像进行一些变换，主要包括：AutoAugment[1]RandAugment[2]3.1. AutoAugment论文：https://arxiv.org/abs/1805.09501v1Github：https://github.com/DeepVoltaire/AutoAugment不同于常规的人工设计图像增广方式，AutoAugment 是在一系列图像增广子策略的搜索空间中通过搜索算法找到的适合特定数据集的图像增广方案。针对 ImageNet 数据集，最终搜索出来的数据增广方案包含 25 个子策略组合，每个子策略中都包含两种变换，针对每幅图像都随机的挑选一个子策略组合，然后以一定的概率来决定是否执行子策略中的每种变换。结果如 图4 所示。图4 AutoAugment后图像可视化3.2. RandAugment论文：https://arxiv.org/pdf/1909.13719.pdfGithub：https://github.com/heartInsert/randaugmentAutoAugment 的搜索方法比较暴力，直接在数据集上搜索针对该数据集的最优策略，其计算量很大。在 RandAugment 文章中作者发现，一方面，针对越大的模型，越大的数据集，使用 AutoAugment 方式搜索到的增广方式产生的收益也就越小；另一方面，这种搜索出的最优策略是针对该数据集的，其迁移能力较差，并不太适合迁移到其他数据集上。在 RandAugment 中，作者提出了一种随机增广的方式，不再像 AutoAugment 中那样使用特定的概率确定是否使用某种子策略，而是所有的子策略都会以同样的概率被选择到，论文中的实验也表明这种数据增广方式即使在大模型的训练中也具有很好的效果。结果如 图5 所示。图5 RandAugment后图像可视化4. 图像裁剪类图像裁剪类主要是对Transpose 后的 224 的图像进行一些裁剪，并将裁剪区域的像素值置为特定的常数（默认为0），主要包括：CutOut[3]RandErasing[4]Hid…

无监督学习-MoCoV1&V2
type: item
date: 2021-04-30T13:33:00+00:00
description: 论文：MoCov1 - Momentum Contrast for Unsupervised Visual Representation Learning - 2019论文：MoCov2 - Improved Baselines with Momentum Contrastive Learning - 2020Github - facebookresearch/mocoMoCo，Momentum Contrast，是一种无监督视觉表示学习算法. MoCo 基于对比学习(contrastive learning) 的角度，将问题转换为字典查询(dictionary look-up)，构建了基于队列的动态字典更新(dynamic dictionary with a queue)和滑动平均编码器(moving-averaged encoder)的算法.1. MoCoMoCo 基于的假设：可以通过覆盖大量负样本的大型字典来学习好的特征，且字典 keys 的编码器尽管在不断的更新，但仍应尽可能保持连续性.对于给定的一个样本x， 选择一个(或一批)正样本y(这里正样本对对于图像上的理解就是x的不同的data augmentation版本). 然后选择一批负样本(对于图像来说，就是除了x之外的图像), 然后设计loss function来将x与正样本之间的距离拉近，负样本之间的距离推开.MoCo 主要有如下特点：1.1. InfoNCE 损失函数[1] - 将对比学习问题转化为字典查询问题损失函数(InfoNCE)形式如：$$ L_q = -log \frac{exp(q \cdot k_+/ \tau)}{\sum_{i=0}^K exp(q \cdot k_i / \tau)} $$另一种形式如，$$ L_{q, k_+, \lbrace k_- \rbrace} = -log \frac{exp(q \cdot k_+/ \tau)}{exp(q \cdot k_+/ \tau) + \sum_{k_-} exp(q \cdot k_- / \tau)} $$其中，$q$ 是查询的特征表示；$k_+$ 是正样本(相似)的特征表示，$\lbrace k_- \rbrace$ 是负样本(不相似)的特征表示；$\tau$ 是超参数.损失函数的求和，是对一个正样本和K个负样本进行的，其类似于 (K+1) Softmax 分类的 log 损失函数，其目标是将$q$ 分类为 $k_+$. 参考 SoftmaxEntropyCross 损失：$$ L_{ce} = -log \frac{exp(x_i)}{\sum_j exp(x_j)} $$或，$$ L(x, class) = -log (\frac{exp(x[class])}{\sum_j exp(x[j])}) $$1.2. 动量更新记 $f_k$ 为 key 编码器；$f_q$ 为 q 查询编码器，$\theta_k$ 和 $\theta_q$ 分别为其参数，MoCo 提出的 $\theta_k$ 动量更新方式如：$$ \theta _k \leftarrow m \theta_k + (1 - m) \theta_q $$其中，只有 $\theta_q$ 是需要 BP 梯度计算的. $m$ 为动量系数，实验证明，相对大的动量(如，m=0.999) 比相对小的动量(如，m=0.9) 的效果好很多.1.3. 将字典作为队列MoCo 的核心是，将字典维护为数据样本的队列. 有利于重用训练过程中的历史 mini-batches 的编码 keys. 基于队列的实现，可以将字典大小和 mini-batch size 解耦，且更大. 队列中的样本是渐进式被替代的. 当前 mini-batch 入队列；最老的 mini-batch 出队列. 字典 keys 一般都所有数据的部分采样子集.1.4. Shuffling BNMoCo 论文所述，在标准 ResNet 的 BN 层，会影响模型的训练. 因为模型可能在试图欺骗任务，并容易地找到loss值比较低的方案.而，MoCo 采用的方式是 shuffling BN. 采用多个 GPU 进行训练，分别对每个 GPU 上的样本进行独立的进行BN. 即，对于 key 编码器 $f_k$，在将其分发到各 GPUs 上时，打乱当前 mini-batch 的采样次序；而查询编码器 $f_q$ 的mini-batch 的采样次序保持不变.1.5. MoCo 实现伪代码2. MoCoV2MoCoV2 的提出源于 SimCLR - A Simple Framework for Contrastive Learning of Visual Representations,Si…

Github项目 - AutoAugment 数据增强策略实现
type: item
date: 2021-01-17T09:11:00+00:00
description: Github - AutoAugment论文：AutoAugment - Learning Augmentation Policies from Data - 2018Google AI Blogpost - improving-deep-learning-performance图：ImageNet 数据集上成功的策略. 可以看出，其大部分策略只要是颜色变换.1. autoaugment.pyautoaugment.pyfrom PIL import Image, ImageEnhance, ImageOps import numpy as np import random class ImageNetPolicy(object): """ Randomly choose one of the best 24 Sub-policies on ImageNet. Example: >>> policy = ImageNetPolicy() >>> transformed = policy(image) Example as a PyTorch Transform: >>> transform=transforms.Compose([ >>> transforms.Resize(256), >>> ImageNetPolicy(), >>> transforms.ToTensor()]) """ def __init__(self, fillcolor=(128, 128, 128)): #数据增强策略列表 self.policies = [ SubPolicy(0.4, "posterize", 8, 0.6, "rotate", 9, fillcolor), SubPolicy(0.6, "solarize", 5, 0.6, "autocontrast", 5, fillcolor), SubPolicy(0.8, "equalize", 8, 0.6, "equalize", 3, fillcolor), SubPolicy(0.6, "posterize", 7, 0.6, "posterize", 6, fillcolor), SubPolicy(0.4, "equalize", 7, 0.2, "solarize", 4, fillcolor), SubPolicy(0.4, "equalize", 4, 0.8, "rotate", 8, fillcolor), SubPolicy(0.6, "solarize", 3, 0.6, "equalize", 7, fillcolor), SubPolicy(0.8, "posterize", 5, 1.0, "equalize", 2, fillcolor), SubPolicy(0.2, "rotate", 3, 0.6, "solarize", 8, fillcolor), SubPolicy(0.6, "equalize", 8, 0.4, "posterize", 6, fillcolor), SubPolicy(0.8, "rotate", 8, 0.4, "color", 0, fillcolor), SubPolicy(0.4, "rotate", 9, 0.6, "equalize", 2, fillcolor), SubPolicy(0.0, "equalize", 7, 0.8, "equalize", 8, fillcolor), SubPolicy(0.6, "invert", 4, 1.0, "equalize", 8, fillcolor), SubPolicy(0.6, "color", 4, 1.0, "contrast", 8, fillcolor), SubPolicy(0.8, "rotate", 8, 1.0, "color", 2, fillcolor), SubPolicy(0.8, "color", 8, 0.8, "solarize", 7, fillcolor), SubPolicy(0.4, "sharpness", 7, 0.6, "invert", 8, fillcolor), SubPolicy(0.6, "shearX", 5, 1.0, "equalize", 9, fillcolor), SubPolicy(0.4, "color", 0, 0.6, "equalize", 3, fillcolor), SubPolicy(0.4, "equalize", 7, 0.2, "solarize", 4, fillcolor), SubPolicy(0.6, "solarize", 5, 0.6, "auto…

Github 项目 - BackgroundMattingV2 之数据集函数
type: item
date: 2020-12-27T09:17:00+00:00
description: 主要集中汇总学习下 BackgroundMattingV2 中的一些关于数据集、数据增强等辅助函数.1. ImagesDatasetimport os import glob from torch.utils.data import Dataset from PIL import Image class ImagesDataset(Dataset): def __init__(self, root, mode='RGB', transforms=None): self.transforms = transforms self.mode = mode self.filenames = sorted( [*glob.glob(os.path.join(root, '**', '*.jpg'), recursive=True), *glob.glob(os.path.join(root, '**', '*.png'), recursive=True)]) def __len__(self): return len(self.filenames) def __getitem__(self, idx): with Image.open(self.filenames[idx]) as img: img = img.convert(self.mode) if self.transforms: img = self.transforms(img) return img2. VideoDatasetimport cv2 import numpy as np from torch.utils.data import Dataset from PIL import Image class VideoDataset(Dataset): def __init__(self, path: str, transforms: any = None): self.cap = cv2.VideoCapture(path) self.transforms = transforms self.width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)) self.height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) self.frame_rate = self.cap.get(cv2.CAP_PROP_FPS) self.frame_count = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT)) def __len__(self): return self.frame_count def __getitem__(self, idx): if isinstance(idx, slice): return [self[i] for i in range(*idx.indices(len(self)))] if self.cap.get(cv2.CAP_PROP_POS_FRAMES) != idx: self.cap.set(cv2.CAP_PROP_POS_FRAMES, idx) ret, img = self.cap.read() if not ret: raise IndexError(f'Idx: {idx} out of length: {len(self)}') img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img = Image.fromarray(img) if self.transforms: img = self.transforms(img) return img def __enter__(self): return self def __exit__(self, exc_type, exc_value, exc_traceback): self.cap.release()3. ZipDatasetfrom torch.utils.data import Dataset from typing import List class ZipDataset(Dataset): def __init__(self, datasets: List[Dataset], transforms=None, assert_equal_length=False): self.datasets = datasets self.transforms = transforms if assert_equal_length: for i in range(1, len(datasets)): ass…

torchvision - transform 数据增强
type: item
date: 2020-06-16T04:38:00+00:00
description: 数据增强(Data Augmentation)，又称为数据增广，数据扩增，它是对训练集进行变换，使训练集更丰富，从而提升模型的泛化能力.torchvision transforms 数据增强主要涉及如下：[1] - 裁剪类transforms.CenterCrop - 中心裁剪transforms.RandomCrop - 随机裁剪transforms.RandomResizedCrop - 随机长宽比裁剪transforms.FiveCrop - 上下左右中心裁剪transforms.TenCrop - 上下左右中心裁剪后旋转[2] - 翻转和旋转transforms.RandomHorizontalFlip - 随机水平翻转transforms.RandomVerticalFlip - 随机垂直翻转transforms.RandomRotation - 随机旋转[3] - 图像变换transforms.Pad - 填充transforms.ColorJitter - 亮度、对比度和饱和度transforms.Grayscale - 转灰度图transforms.RandomGrayscale - 随机转灰度图transforms.RandomAffine - 随机仿射变换transforms.LinearTransformation - 线性变换transforms.RandomErasing - 随机擦除transforms.Lambda - 自定义变换transforms.Resizetransforms.ToTensor - 转为 Tensor，并归一化到[0, 1].transforms.Normalize - 标准化[4] - transforms的操作transforms.RandomChoice(transforms) - 随机选择给定 transforms 中的一种transforms.RandomApply(transforms, p=0.5) - 加上随机概率transforms.RandomOrder - 随机打乱 transforms 操作的顺序示例 - FixRes codeblockFrom FixResimport numpy as np import torch import torchvision.transforms.functional as F from torchvision import transforms class Resize(transforms.Resize): """ Resize with a ``largest=False'' argument allowing to resize to a common largest side without cropping """ def __init__(self, size, largest=False, **kwargs): super().__init__(size, **kwargs) self.largest = largest @staticmethod def target_size(w, h, size, largest=False): if h < w and largest: w, h = size, int(size * h / w) else: w, h = int(size * w / h), size size = (h, w) return size def __call__(self, img): size = self.size w, h = img.size target_size = self.target_size(w, h, size, self.largest) return F.resize(img, target_size, self.interpolation) def __repr__(self): r = super().__repr__() return r[:-1] + ', largest={})'.format(self.largest) # def get_transforms(input_size=224,test_size=224, kind='full', crop=True, need=('train', 'val')): mean, std = [0.485, 0.456, 0.406], [0.229, 0.224, 0.225] transformations = {} if 'train' in need: if kind == 'torch': transformations['train'] = transforms.Compose([…

Python - 语义分割数据增强实现
type: item
date: 2020-04-06T13:42:39+00:00
description: From: https://github.com/PaddlePaddle/PaddleSeg/blob/release/v0.4.0/pdseg/data_aug.pyfrom __future__ import print_function import cv2 import numpy as np def resize(img, grt=None, mode=ModelPhase.TRAIN): """ 改变图像及标签图像尺寸 AUG.AUG_METHOD为unpadding，所有模式均直接resize到AUG.FIX_RESIZE_SIZE的尺寸 AUG.AUG_METHOD为stepscaling, 按比例resize，训练时比例范围AUG.MIN_SCALE_FACTOR到AUG.MAX_SCALE_FACTOR,间隔为AUG.SCALE_STEP_SIZE，其他模式返回原图 AUG.AUG_METHOD为rangescaling，长边对齐，短边按比例变化，训练时长边对齐范围AUG.MIN_RESIZE_VALUE到AUG.MAX_RESIZE_VALUE，其他模式长边对齐AUG.INF_RESIZE_VALUE Args： img(numpy.ndarray): 输入图像 grt(numpy.ndarray): 标签图像，默认为None mode(string): 模式, 默认训练模式，即ModelPhase.TRAIN Returns： resize后的图像和标签图 """ if cfg.AUG.AUG_METHOD == 'unpadding': target_size = cfg.AUG.FIX_RESIZE_SIZE img = cv2.resize(img, target_size, interpolation=cv2.INTER_LINEAR) if grt is not None: grt = cv2.resize(grt, target_size, interpolation=cv2.INTER_NEAREST) elif cfg.AUG.AUG_METHOD == 'stepscaling': if mode == ModelPhase.TRAIN: min_scale_factor = cfg.AUG.MIN_SCALE_FACTOR max_scale_factor = cfg.AUG.MAX_SCALE_FACTOR step_size = cfg.AUG.SCALE_STEP_SIZE scale_factor = get_random_scale(min_scale_factor, max_scale_factor, step_size) img, grt = randomly_scale_image_and_label( img, grt, scale=scale_factor) elif cfg.AUG.AUG_METHOD == 'rangescaling': min_resize_value = cfg.AUG.MIN_RESIZE_VALUE max_resize_value = cfg.AUG.MAX_RESIZE_VALUE if mode == ModelPhase.TRAIN: if min_resize_value == max_resize_value: random_size = min_resize_value else: random_size = int(np.random.uniform(min_resize_value, max_resize_value) + 0.5) else: random_size = cfg.AUG.INF_RESIZE_VALUE value = max(img.shape[0], img.shape[1]) scale = float(random_size) / float(value) img = cv2.resize(img, (0, 0), fx=scale, fy=scale, interpolation=cv2.INTER_LINEAR) if grt is not None: grt = cv2.resize(grt, (0, 0), fx=scale, fy=scale, interpolation=cv2.INTER_NEAREST) else: raise Exception("Unexpect data augmention method: {}".format( cfg.AUG.AUG_METHOD)) return img, grt def get_random_scale(min_scale_f…

Github 项目 - NVIDIA DALI 加速库[旧]
type: item
date: 2020-03-26T13:15:00+00:00
description: Github - NVIDIA/DALIdocs - NVIDIA DALI documentationNVIDIA/DALI(NVIDIA Data Loading Library) 库包含了用于加速深度学习应用的数据预处理的高度优化的构建模块(highly optimized building blocks)和执行引擎(execution engine).深度学习应用中，往往需要复杂的、多阶段的数据预处理管道. 这些数据管道主要是在CPU上执行的数据密集型操作(compute-intensive operation),b 比如，从磁盘加载数据，解码，裁剪，随机resize，颜色和空间增强，格式转换，等等，都主要是在 CPUs 上完成的，其限制了训练和推断时的性能和可扩展性.另外，深度学习框架有很多不同的数据预处理实现，这就为网络训练和推断工作流的可移植性和代码维护带来了挑战.DALI 是高度优化后的构建模块的集合，是用于加速输入数据预处理的执行引擎. DALI 作为单独的库，为不同数据管道的加速，提供了更优的性能和灵活性. DALI 库可以很方便的整合仅不同深度学习训练和推断应用中.1. DALI Highlights[1] - 全数据管道加速 - 从磁盘读取到用于训练和推断的数据处理.[2] - 灵活性高 - 可配置图(configurable graphs)和定制操作子(custom operators).[3] - 支持图像分类和分割的数据加载.[4] - 易于整合 - 直接的框架插件和开源绑定(open source bindings).[5] - 训练工作流的便携性，支持多种输入格式：JPEG,PNG (fallback to CPU), TIFF (fallback to CPU), BMP (fallback to CPU), raw formats, LMDB, RecordIO, TFRecord.[6] - 定制化的可扩展性.2. DALI 安装NVIDIA GPU Cloud 中的 TensorFlow, PyTorch 和 MXNet containers(18.07 以后版本) 已经预安装了 DALI 库.2.1. prebuilt DALI 安装依赖项：[1] - Linux x64.[2] - NVIDIA Driver supporting CUDA 9.0 or later (i.e., 384.xx or later driver releases).[3] - 深度框架:MXNet 1.3 mxnet-cu90 or later.PyTorch 0.4 or later.TensorFlow 1.7 or later.CUDA9.0 安装：pip install --extra-index-url https://developer.download.nvidia.com/compute/redist/cuda/9.0 nvidia-daliCUDA10.0 安装(DALI 0.80 以后版本)：pip install --extra-index-url https://developer.download.nvidia.com/compute/redist/cuda/10.0 nvidia-daliDALI 0.6.1 版本以后，nvidia-dali 不再包含 DALI TensorFlow 插件的 prebuilt 版本，因此需要采用如下方式安装：pip install --extra-index-url https://developer.download.nvidia.com/compute/redist/cuda/9.0 nvidia-dali-tf-pluginDALI 0.8.0 版本以后，支持 CUDA10.0：pip install --extra-index-url https://developer.download.nvidia.com/compute/redist/cuda/10.0 nvidia-dali-tf-plugin此时，会自动安装 nvidia-dali 及其依赖项.安装指定版本：pip install --extra-index-url https://developer.download.nvidia.com/compute/redist nvidia-dali-tf-plugin==0.6.1### 2.2. Nightly builds DALI 安装在安装每日更新的 DALI 库前，建议先卸载常规 DALI.CUDA9:pip install --extra-index-url https://developer.download.nv…

Github 项目 - PaddleSeg 数据增强策略
type: item
date: 2019-09-25T12:06:00+00:00
description: Github 项目 - 百度语义分割库PaddleSeg - AIUAIGithub 项目 - PaddleSeg 模型训练 - AIUAI在语义分割的模型训练时，由于语义分割数据集的标注与收集难度比较大，因此往往需要借助数据增强策略进行处理.1. PaddleSeg 数据增强基本流程PaddleSeg 数据增强1.1. Resizeresize 步骤是指将输入图像按照某种规则讲图片重新缩放到某一个尺寸.PaddleSeg 支持以下3种resize方式:[1] - Unpadding 将输入图像直接resize到某一个固定大小下，送入到网络中间训练，对应参数为AUG.FIX_RESIZE_SIZE. 预测时同样操作. [2] - Step-Scaling 将输入图像按照某一个比例 resize，这个比例以某一个步长在一定范围内随机变动. 设定最小比例参数为AUG.MIN_SCALE_FACTOR, 最大比例参数AUG.MAX_SCALE_FACTOR，步长参数为AUG.SCALE_STEP_SIZE. 预测时不对输入图像做处理. [3] - Range-Scaling 固定长宽比resize，即图像长边对齐到某一个固定大小，短边随同样的比例变化. 设定最小大小参数为AUG.MIN_RESIZE_VALUE，设定最大大小参数为AUG.MAX_RESIZE_VALUE. 预测时需要将长边对齐到AUG.INF_RESIZE_VALUE所指定的大小，其中AUG.INF_RESIZE_VALUE在AUG.MIN_RESIZE_VALUE和AUG.MAX_RESIZE_VALUE范围内. Range-Scaling示意图如下：1.2. FlipPaddleSeg支持以下2种翻转方式：[1] - 左右翻转(Mirror) ：AUG.MIRROR，为True时该功能开启，为False时该功能关闭. [2] - 上下翻转(Flip) ：AUG.FLIP，为True时该功能开启，AUG.FLIP_RATIO 控制是否上下翻转的概率. 为False时该项功能关闭. 二者可独立运作，也可组合使用. 故图像翻转一共有如下4种可能的情况：1.3. Rich CropRich Crop 是 PaddleSeg 结合实际业务经验开放的一套数据增强策略，面向标注数据少，测试数据情况繁杂的分割业务场景使用的数据增强策略. 流程如下图所示:Rich crop 是指对图像进行多种变换，保证在训练过程中数据的丰富多样性，PaddleSeg支持以下几种变换. AUG.RICH_CROP.ENABLE为False时会直接跳过该步骤. [1] - blur 图像加模糊，使用开关AUG.RICH_CROP.BLUR，为False时该功能关闭. AUG.RICH_CROP.BLUR_RATIO控制加入模糊的概率. [2] - rotation 图像旋转，AUG.RICH_CROP.MAX_ROTATION控制最大旋转角度. 旋转产生的多余的区域的填充值为均值. [3] - aspect 图像长宽比调整，从图像中crop一定区域出来之后在某一长宽比内进行resize. 控制参数AUG.RICH_CROP.MIN_AREA_RATIO和AUG.RICH_CROP.ASPECT_RATIO. [4] - color jitter 图像颜色调整，控制参数AUG.RICH_CROP.BRIGHTNESS_JITTER_RATIO、AUG.RICH_CROP.SATURATION_JITTER_RATIO、AUG.RICH_CROP.CONTRAST_JITTER_RATIO.1.4. Random Crop该步骤主要是通过crop的方式使得输入到网络中的图像在某一个固定大小，控制该大小的参数为TRAIN_CROP_SIZE，类型为tuple，格式为(width, height). 当输入图像大小小于CROP_SIZE的时候会对输入图像进行padding，padding值为均值.输入图片格式原图图片格式：RGB三通道图片和RGBA四通道图片两种类型的图片进行训练，但是在一次训练过程只能存在一种格式.图片转换：灰度图片经过预处理后之后会转变成三通道图片图片参数设置：当图片为三通道图片时IMAGE_TYPE设置为rgb， 对应MEAN和STD也必须是一个长度为3的list，当图片为四通道图片时IMAGE_TYPE设置为rgba，对应的MEAN和STD必须是一个长度为4的list.标注图图片格式：标注图片必须为png格式的单通道多值图，元素值代表的是这个元素所属于的类别.图片转换：在datalayer层对label图片进行的任何resize，以及旋转的操作，都必须采用最近邻的插值方式.图片ign…

Pytorch - 图像变换函数集合
type: item
date: 2018-12-15T07:16:00+00:00
description: PyTorch 的 Vision 模块提供了图像变换的很多函数. vision/torchvision/transforms/functional.py# 必要的 python 模块 from __future__ import division import torch import sys import math from PIL import Image, ImageOps, ImageEnhance, PILLOW_VERSION try: import accimage except ImportError: accimage = None import numpy as np import numbers import collections import warnings import matplotlib as plt if sys.version_info < (3, 3): Sequence = collections.Sequence Iterable = collections.Iterable else: Sequence = collections.abc.Sequence Iterable = collections.abc.Iterable以下图为例：img_file = "test.jpe" img = Image.open(img_file) width, height = img.size #(750, 815) img.show()1. PyTorch 图像变换函数1.1. 判断图像数据类型# 图像格式检查，如，pil, tensor, numpy def _is_pil_image(img): if accimage is not None: return isinstance(img, (Image.Image, accimage.Image)) else: return isinstance(img, Image.Image) def _is_tensor_image(img): return torch.is_tensor(img) and img.ndimension() == 3 def _is_numpy_image(img): return isinstance(img, np.ndarray) and (img.ndim in {2, 3})如：_is_pil_image(img) # True _is_tensor_image(img) # False _is_numpy_image(img) # False _is_numpy_image(np.array(img)) # True1.2. to_tensor(pic)将 PIL Image 或 nupy.ndarray 转换为 tensor.def to_tensor(pic): """ Args: pic (PIL Image or numpy.ndarray): Image to be converted to tensor. Returns: Tensor: Converted image. """ if not(_is_pil_image(pic) or _is_numpy_image(pic)): raise TypeError('pic should be PIL Image or ndarray. Got {}'.format(type(pic))) if isinstance(pic, np.ndarray): # handle numpy array img = torch.from_numpy(pic.transpose((2, 0, 1))) # backward compatibility if isinstance(img, torch.ByteTensor): return img.float().div(255) else: return img if accimage is not None and isinstance(pic, accimage.Image): nppic = np.zeros([pic.channels, pic.height, pic.width], dtype=np.float32) pic.copyto(nppic) return torch.from_numpy(nppic) # handle PIL Image if pic.mode == 'I': img = torch.from_numpy(np.array(pic, np.int32, copy=False)) elif pic.mode == 'I;16': img = torch.from_…

SSD(Single Shot Detector) 中的数据增强[译]
type: item
date: 2018-08-07T13:38:00+00:00
description: 原文：Data Augmentation in SSD (Single Shot Detector) - 2018.06.28作者研究了 single shot 目标检测器 SSD: Single Shot MultiBox Detector 如何取得了比 Faster R-CNN 更佳的 mAP，且计算复杂度明显减少，实时运行效果更快. 这里将详细描述 SSD 所采用的数据增强策略. 根据论文所述，其数据增强策略取得了 8.8% 的 mAP 提升. 数据增强对于小目标检测的精度提升尤其重要，因为其对图像进行缩放(zoom)，使得分类器能够识别更多图片中的目标物体. 数据增强对于图像中出现被遮挡物体(occluded objects)的处理，也很重要，通过对训练数据中的图像进行裁剪，使得只有部分物体是可见的.1. 数据增强流程采用的数据增强处理流程步骤如下：光度变形(Photometric Distortions)几何变换(Geometric Distortions)图像扩展(ExpandImage)随机裁剪(RandomCrop)随机镜像(RandomMirror) 下面会详细介绍这些数据增强(包括相应的代码实现片段). 其中，每一数据变换都是概率随机的(一般 probability=0.5). 因此，不同的训练次数采用的是数据增强后的不同图像数据.Github - amdegroot/ssd.pytorch2. 光度变形(Photometric Distortions)2.1. 随机调整亮度(Random Brightness)以 probability=0.5 的 随机概率，随机对图像每个像素添加一个值，该添加值是从 [-delat, delta] 中随机选取的. 默认的 delta 值是 32.def __call__(self, image, boxes=None, labels=None): if random.randint(2): delta = random.uniform(-self.delta, self.delta) image += delta return image, boxes, labels2.2. 随机调整对比度(Contrast), 色相(Hue) 和饱和度(Saturation)亮度(Brightness)调整后，进行对比度，色相和饱和度的随机变换. 其顺序是随机的. 有两种选择，首先对比度处理，然后色相和饱和度；或者首先色相和饱和度处理，然后对比度处理. 每种选择都是随机的，probability=0.5.self.pd = [RandomContrast(), ConvertColor(transform='HSV'), RandomSaturation(), RandomHue(), ConvertColor(current='HSV', transform='BGR'), RandomContrast() ] im, boxes, labels = self.rand_brightness(im, boxes, labels) if random.randint(2): distort = Compose(self.pd[:-1]) else: distort = Compose(self.pd[1:]) im, boxes, labels = distort(im, boxes, labels)其中，对比度是在 RGB 空间处理，色相和饱和度是在 HSV 空间. 因此，在进行每一步操作前需要先作对应的颜色空间转换. 对比度，色相和饱和度的调整类似于亮度调整，都是 probability=0.5 的随机进行. 通过随机在一个上界和下界区间内选择形变的值. 例如，饱和度调整：def __call__(self, image, boxes=None, labels=None): if random.randint(2): image[:, :, 1] *= random.uniform(self.lower, self.upper) return image, boxes, labels2.3. 随机光照噪声(RandomLightingNoise)最后一种光度形变是随机光照噪声. 其包括随机颜色通道交换(color channel swap). 颜色变换定义为：self.perms = ((0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0))对于 RGB 图像，颜色通道变换(0 2 1) 则交换 green 和 blue 通道，保持 red 通道不变.3. 几何变换光度调整只会改变图像像素，而不会改变图像的…