CV08-数据预处理与数据增强

复现车道线分割项目(Lane Segmentation赛事说明在这里),学习数据预处理和数据增强。学习分为Model、Data、Training、Inference、Deployment五个阶段,也就是建模、数据、训练、推断、部署这五个阶段。现在进入的是Data阶段。项目的第一名也就是baseline在这里https://github.com/gujingxiao/Lane-Segmentation-Solution-For-BaiduAI-Autonomous-Driving-Competition

一、数据预处理

1.1 数据的说明

对于竞赛数据集:
使用Gray_Label里面的灰度标签;Labels_Fixed是RGB标签,只是灰度和RGB的一个映射关系,Gray_Label用于训练,Label_Fixed方便查看。使用Road02-04里面的数据,数据里面的lable不要使用,那些label是无效的。

数据增强肯定可以增加准确率,但是在项目开始时,不建议使用。应先建立baseline,尽快是模型能够跑起来,再想办法提高精度。

1.2 观察数据

注意观察数据。观察数据的分布、数据不平衡问题、异常、错误等。发现问题,要用数据清洗的办法解决。什么情况下进行数据清洗?与任务无关的、不能训练模型的、不包含目标特征的图片,剪裁掉无用的部分。由于GPU的限制,在服务器上建立训练用的张量NCHW里面的N一般选择2。

要注意维度的转换, NHWC维度转换为NCHW维度。利用张量的transpose方法转换维度。

数据不平衡会有什么问题?如果二分类类别不平衡,A分类99%,B分类1%,那么模型学不到东西。因为给一个图片就标记A就可以获得99%的正确率。

数据的data和label对应可以用文件名匹配的办法,文件名是时间戳命名的。观察数据集,每个图片的大小H×W=1710×3384。图片分辨率很大,不能全部加载,否则会把内存耗尽。面对这样的数据,在内存小、GPU性能差时怎么办?可以减小batch_size,resize降低图像分辨率,对图片剪裁crop。

1.3 label的处理

训练的时候,label要使用trainId。因为trainId是0-8连续的9个分类,方便做成one-hot向量label。
提交结果时,将推断映射到trainId对应的任意一个id就行。
注意:ignoreInEval列,ignoreInEval==True表示忽略,表示这个数据集里面就没有这个分类,因此不必要关注。直接将这类trainId变成背景类void。
注意:trainId==4的这个类别,ignoreInEval都是True,说明整个这个类别在数据集里面都没有。那么,就把这个类别忽略掉,后面的递进补上,5变成4,6变成5……8变成7。这样最终,实际只有8个分类。

1.4 生成CSV文件

前面提到data和label对应,用程序处理一下,生成CSV格式文件。CSV文件有两列,一列data的绝对路径,一列label的绝对路径。这个可以用pandas库来处理。列举一下pandas库的用法。

个人比较喜欢第一种用法,columns指定csv文件中有几列,这里是image和label两列。data是一个列表类型,每个元素都是一个item数据。这样就可以想写几条就写j

import pandas as pd

df = pd.DataFrame(data=abspaths,  # csv文件数据,每个元素是一条数据
                  columns=['image', 'label'])  # 两列 image、label
        

# 生成csv文件
save = pd.DataFrame({'image':image_list, 'label':label_list})
save_shuffle = shuffle(save)
save_shuffle.to_csv('../data_list/train.csv', index=False)

# 读取csv文件
data_dir = './data_list/train.csv'
train_list = pd.read_csv(data_dir)

1.5 推断

推断的方式可以用模型融合。baseline里面的模型融合就是三个模型的推断做平均值,用平均值作为推断。

1.6 其他内容

补充一些知识。语义分割常见的数据集:PASCAL VOC 2012、cityscapes等;Lane Segmentation的数据集是阿波罗数据集的一部分。阿波罗数据集的论文地址https://arxiv.org/abs/1803.06184,论文题目The ApolloScape Open Dataset for Autonomous Driving and its Application

语义分割的Label比较特殊,是和原图大小一样的图。或者label比原图要小,因为只对其中一部分感兴趣。要有自己的工具,可以参考COCO API,地址https://github.com/cocodataset/cocoapi

二、数据增强

  • 数据增强的目的是:提升特征的鲁棒性与模型的泛化性。
  • 一般来讲,数据增强是可以提升模型性能,但是并不是所有方法都成立,要考虑性价比。
  • 数据增强与数据集和任务存在一定关联性。(色彩增强对分类问题有效、翻转等对目标检测有效)

复现的常用的数据增强的代码在这里https://github.com/Ascetics/Pytorch-SegToolbox/blob/master/utils/augment.py

2.1 数据增强——基于pixel

  • 亮度。图像均值反应。也就是改变了图像的均值。
  • 对比度。均值不变的情况下,缩放差别。也就是图像均值不变,各色彩的方差增大。
  • 颜色饱和度。RGB转向HSV,再增加饱和度。

代码示例

import torch
import torchvision.transforms.functional as TF
import matplotlib.pyplot as plt
import numpy as np
import random
import os
from PIL import Image, ImageFilter
from utils.tools import get_proj_root


class PairAdjustColor(object):
    def __init__(self, factors=(0.3, 2.)):
        super(PairAdjustColor, self).__init__()
        self.factors = factors
        pass

    def __call__(self, image, label=None):
        """
        调整亮度、对比度、饱和度
        只调整image,不调整label
        :param image: [H,W,C] PIL Image RGB 0~255
        :param label: [H,W] PIL Image trainId
        :return: [H,W,C] PIL Image RGB 0~255,  [H,W] PIL Image trainId
        """
        brightness_factor = random.uniform(*self.factors)
        contrast_factor = random.uniform(*self.factors)
        saturation_factor = random.uniform(*self.factors)

        image = TF.adjust_brightness(image, brightness_factor)
        image = TF.adjust_contrast(image, contrast_factor)
        image = TF.adjust_saturation(image, saturation_factor)
        return image, label

    pass

2.2 数据增强——基于位置变换

  • 水平或垂直翻转
  • 平移
  • 旋转
  • 缩放
  • 剪裁

以水平或垂直翻转为例

class PairRandomHFlip(object):
    def __init__(self):
        super(PairRandomHFlip, self).__init__()
        pass

    def __call__(self, image, label=None):
        """
        图像随机左右翻转
        :param image: [H,W,C] PIL Image RGB
        :param label: [H,W] PIL Image trainId
        :return: [H,W,C] PIL Image RGB,  [H,W] PIL Image trainId
        """
        if random.uniform(0, 1) < 0.5:  # 50%的概率会翻转
            image = TF.hflip(image)  # 左右翻转
            if label is not None:
                label = TF.hflip(label)
        return image, label

    pass


class PairRandomVFlip(object):
    def __init__(self):
        super(PairRandomVFlip, self).__init__()
        pass

    def __call__(self, image, label=None):
        """
        图像随机上下翻转
        :param image: [H,W,C] PIL Image RGB
        :param label: [H,W] PIL Image trainId
        :return: [H,W,C] PIL Image RGB,  [H,W] PIL Image trainId
        """
        if random.uniform(0, 1) < 0.5:  # 50%的概率会翻转
            image = TF.vflip(image)  # 上下翻转
            if label is not None:
                label = TF.vflip(label)
        return image, label

    pass

注意缩放的时候,image用bilinear差值,label只能用nearest插值。这是因为label中分类是从0,1,2……n_class-1的,插值会产生新的不存在的label。比如,图像的label是555777,bilinear插值变成5556677777,这里面66就是新的在原有label里面不存在的,用nearest差值就可以不会有这个问题。

2.3 数据增强——其他

  • Mixup方法,两个目标融合成一个目标
  • Cutout随机丢弃图像中的一部分,就相当于针对遮挡问题的增强。在图像中随机找到一个部分,像素全部置0。
  • AutoArgument

以Cutout为例

class PairRandomFixErase(object):
    def __init__(self, mask_size=64, value=0):
        """
        按照固定大小,随机遮挡图像中的某一块方形区域
        :param mask_size: 被遮挡的区域大小,默认64x64
        :param value: 被遮挡的部分用value值填充
        """
        super(PairRandomFixErase, self).__init__()
        self.mask_size = mask_size
        self.value = value
        pass

    def __call__(self, image, label=None):
        """
        按照固定大小,随机遮挡图像中的某一块方形区域
        :param image: [C,H,W] tensor,必须是tensor
        :param label: [H,W] tensor,必须是tensor
        :return: [C,H,W] tensor,  [H,W] tensor
        """
        _, h, w = image.shape
        top = random.randint(0, h - self.mask_size)  # 随机到遮挡部分的top
        left = random.randint(0, w - self.mask_size)  # 随机到遮挡部分的left
        if random.uniform(0, 1) < 0.5:  # 随机遮挡
            image = TF.erase(image, top, left, self.mask_size, self.mask_size,
                             v=self.value, inplace=True)
        return image, label

    pass

三、常用的图像增强库

可以考虑使用已经成熟的图像增强库,比如iaa、Albumentations等。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苦行僧(csdn)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值