数据读取与数据扩增理解

1、图像读取

Python中有很多库可以完成数据读取的操作,比较常见的有Pillow和OpenCV。
1.1 Pillow
Pillow是Python图像处理函式库(PIL)的一个分支。Pillow提供了常见的图像读取和处理的操作,而且可以与ipython notebook无缝集成,是应用比较广泛的库。
在这里插入图片描述
在这里插入图片描述
注:
Pillow的官方文档:https://pillow.readthedocs.io/en/stable/
1.2 OpenCV
OpenCV是一个跨平台的计算机视觉库,最早由Intel开源得来。OpenCV发展的非常早,拥有众多的计算机视觉、数字图像处理和机器视觉等功能。OpenCV在功能上比Pillow更加强大很多,学习成本也高很多。
在这里插入图片描述
OpenCV包含了众多的图像处理的功能。OpenCV还内置了很多的图像特征处理算法,如关键点检测、边缘检测和直线检测等。
注:
OpenCV官网:https://opencv.org/
OpenCV Github:https://github.com/opencv/opencv
OpenCV 扩展算法库:https://github.com/opencv/opencv_contrib

2、数据扩增方法

2.1 数据扩增介绍
数据扩增可以增加训练集的样本,同时也可以有效缓解模型过拟合的情况,也可以给模型带来的更强的泛化能力。
在这里插入图片描述
数据扩增用处:
在深度学习模型的训练过程中,数据扩增是必不可少的环节。现有深度学习的参数非常多,一般的模型可训练的参数量基本上都是万到百万级别,而训练集样本的数量很难有这么多。其次数据扩增可以扩展样本空间,假设现在的分类模型需要对汽车进行分类,左边的是汽车A,右边为汽车B。如果不使用任何数据扩增方法,深度学习模型会从汽车车头的角度来进行判别,而不是汽车具体的区别。
在这里插入图片描述
数据扩增方法:
数据扩增方法有很多:从颜色空间、尺度空间到样本空间,同时根据不同任务数据扩增都有相应的区别。
对于图像分类,数据扩增一般不会改变标签;对于物体检测,数据扩增会改变物体坐标位置;对于图像分割,数据扩增会改变像素标签。
2.2 常见的数据扩增方法
在常见的数据扩增方法中,一般会从图像颜色、尺寸、形态、空间和像素等角度进行变换。当然不同的数据扩增方法可以自由进行组合,得到更加丰富的数据扩增方法。
以torchvision为例,常见的数据扩增方法包括:
1、transforms.CenterCrop 对图片中心进行裁剪
2、transforms.ColorJitter 对图像颜色的对比度、饱和度和零度进行变换
3、transforms.FiveCrop 对图像四个角和中心进行裁剪得到五分图像
4、transforms.Grayscale 对图像进行灰度变换
5、transforms.Pad 使用固定值进行像素填充
6、transforms.RandomAffine 随机仿射变换
7、transforms.RandomCrop 随机区域裁剪
8、transforms.RandomHorizontalFlip 随机水平翻转
9、transforms.RandomRotation 随机旋转
10、transforms.RandomVerticalFlip 随机垂直翻转
在这里插入图片描述
在本次赛题中,任务是需要对图像中的字符进行识别,因此对于字符图片并不能进行翻转操作。比如字符6经过水平翻转就变成了字符9,会改变字符原本的含义。
2.3 常用的数据扩增库
torchvision
https://github.com/pytorch/vision
pytorch官方提供的数据扩增库,提供了基本的数据数据扩增方法,可以无缝与torch进行集成;但数据扩增方法种类较少,且速度中等;

imgaug
https://github.com/aleju/imgaug
imgaug是常用的第三方数据扩增库,提供了多样的数据扩增方法,且组合起来非常方便,速度较快;

albumentations
https://albumentations.readthedocs.io
是常用的第三方数据扩增库,提供了多样的数据扩增方法,对图像分类、语义分割、物体检测和关键点检测都支持,速度较快。

3、Pytorch读取数据

在Pytorch中数据是通过Dataset进行封装,并通过DataLoder进行并行读取。所以我们只需要重载一下数据读取的逻辑就可以完成数据的读取。

import os, sys, glob, shutil, json
import cv2

from PIL import Image
import numpy as np

import torch
from torch.utils.data.dataset import Dataset
import torchvision.transforms as transforms

class SVHNDataset(Dataset):
    def __init__(self, img_path, img_label, transform=None):
        self.img_path = img_path
        self.img_label = img_label 
        if transform is not None:
            self.transform = transform
        else:
            self.transform = None

    def __getitem__(self, index):
        img = Image.open(self.img_path[index]).convert('RGB')

        if self.transform is not None:
            img = self.transform(img)
        
        # 原始SVHN中类别10为数字0
        lbl = np.array(self.img_label[index], dtype=np.int)
        lbl = list(lbl)  + (5 - len(lbl)) * [10]
        
        return img, torch.from_numpy(np.array(lbl[:5]))

    def __len__(self):
        return len(self.img_path)

train_path = glob.glob('../input/train/*.png')
train_path.sort()
train_json = json.load(open('../input/train.json'))
train_label = [train_json[x]['label'] for x in train_json]

data = SVHNDataset(train_path, train_label,
          transforms.Compose([
              # 缩放到固定尺寸
              transforms.Resize((64, 128)),

              # 随机颜色变换
              transforms.ColorJitter(0.2, 0.2, 0.2),

              # 加入随机旋转
              transforms.RandomRotation(5),

              # 将图片转换为pytorch 的tesntor
              # transforms.ToTensor(),

              # 对图像像素进行归一化
              # transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225])
            ]))

上述代码可以将赛题的图像数据和对应标签进行读取,在读取过程中的进行数据扩增,效果如下:
在这里插入图片描述
接下来我们将在定义好的Dataset基础上构建DataLoder,Dataset:对数据集的封装,提供索引方式的对数据样本进行读取;
DataLoder:对Dataset进行封装,提供批量读取的迭代读取。
加入DataLoder后,数据读取代码改为如下:

import os, sys, glob, shutil, json
import cv2

from PIL import Image
import numpy as np

import torch
from torch.utils.data.dataset import Dataset
import torchvision.transforms as transforms

class SVHNDataset(Dataset):
    def __init__(self, img_path, img_label, transform=None):
        self.img_path = img_path
        self.img_label = img_label 
        if transform is not None:
            self.transform = transform
        else:
            self.transform = None

    def __getitem__(self, index):
        img = Image.open(self.img_path[index]).convert('RGB')

        if self.transform is not None:
            img = self.transform(img)
        
        # 原始SVHN中类别10为数字0
        lbl = np.array(self.img_label[index], dtype=np.int)
        lbl = list(lbl)  + (5 - len(lbl)) * [10]
        
        return img, torch.from_numpy(np.array(lbl[:5]))

    def __len__(self):
        return len(self.img_path)

train_path = glob.glob('../input/train/*.png')
train_path.sort()
train_json = json.load(open('../input/train.json'))
train_label = [train_json[x]['label'] for x in train_json]

train_loader = torch.utils.data.DataLoader(
        SVHNDataset(train_path, train_label,
                   transforms.Compose([
                       transforms.Resize((64, 128)),
                       transforms.ColorJitter(0.3, 0.3, 0.2),
                       transforms.RandomRotation(5),
                       transforms.ToTensor(),
                       transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
            ])), 
    batch_size=10, # 每批样本个数
    shuffle=False, # 是否打乱顺序
    num_workers=10, # 读取的线程个数
)

for data in train_loader:
    break

在加入DataLoder后,数据按照批次获取,每批次调用Dataset读取单个样本进行拼接。此时data的格式为:

torch.Size([10, 3, 64, 128]), torch.Size([10, 6])

前者为图像文件,为batchsize * chanel * height * width次序;后者为字符标签。

4、总结

此处进行了数据读取相关操作的总结,以及数据扩增方法和使用,并使用Pytorch框架对本次赛题的数据进行读取。

<think>好的,我现在需要帮助用户寻找关于目标检测数据扩增的方法及对应的脚本示例代码。首先,我要理解用户的需求。用户提到他们正在处理目标检测的数据准备,特别是解析XML标注文件到JSON,可能是在使用YOLO或其他模型进行训练,现在需要数据扩增的方法和代码示例。用户引用了两篇资料,其中一篇提到了YOLO的改进和应用,另一篇是关于数据准备的,所以可能需要结合这些信息来给出相关的扩增方法。 首先,数据扩增在目标检测中非常重要,因为它可以增加数据多样性,防止过拟合,并提升模型的泛化能力。常见的方法包括几何变换(如翻转、旋转、缩放)、颜色变换(调整亮度、对比度、饱和度)、添加噪声、随机裁剪等。需要注意的是,在应用这些变换时,不仅要处理图像,还要相应地调整标注框的位置,确保标注图像变换后的目标一致。 接下来,我需要考虑用户可能需要具体的代码示例。用户可能使用Python,常见的库有Albumentations和imgaug,这两个库都支持目标检测的数据扩增,并且能够处理标注框的同步变换。另外,用户提到他们之前解析了XML到JSON,因此在扩增后可能需要将新的标注信息保存回JSON或XML格式,但用户可能需要的是如何在扩增过程中处理标注数据。 然后,我需要检查用户提供的引用内容。引用[1]提到将XML标注转为JSON,引用[2]是关于改进YOLO网络的应用,所以数据扩增可能用于YOLO训练。因此,可能需要推荐YOLO兼容的扩增方法,或者展示如何将扩增后的数据输入到YOLO训练流程中。 接下来,我应该整理常用的数据扩增方法,并给出代码示例。例如,使用Albumentations库,因为它对目标检测任务支持较好,且代码简洁。同时,需要展示如何读取图像和标注,应用扩增,然后保存结果。可能还需要提到处理标注框的格式转换,比如从YOLO格式(归一化的中心坐标和宽高)转换为Albumentations所需的格式(像素坐标的边界框),扩增后再转换回去。 另外,用户可能需要了解不同扩增方法的效果,比如Mosaic增强在YOLOv4中的应用,或者混合图像(MixUp)等方法。不过,这些高级方法可能需要更复杂的实现,所以可能需要分层次给出基础示例和进阶方法。 最后,生成相关问题需要考虑用户可能的后续需求,比如如何处理标注文件、如何选择扩增参数、评估扩增效果,或者特定场景下的扩增技巧,比如小目标检测中的扩增方法,这可能用户提到的无人机视角下的小目标检测相关。</think>以下关于目标检测数据扩增的方法及代码示例的详细说明: ### 一、数据扩增核心方法 1. **几何变换类** - 水平/垂直翻转:$x' = width - x_{min}$(水平翻转时框的横坐标变换) - 随机旋转:需计算旋转后包围框的新坐标 - 随机裁剪:保持目标完整性,过滤过小目标 ```python import albumentations as A transform = A.Compose([ A.HorizontalFlip(p=0.5), A.Rotate(limit=15, p=0.3), A.RandomSizedBBoxSafeCrop(height=416, width=416, p=0.5) ], bbox_params=A.BboxParams(format='yolo')) ``` 2. **颜色空间变换** - HSV调整:$H_{new} = H \times (1 \pm \Delta)$ - 高斯噪声:$I'(x,y) = I(x,y) + \mathcal{N}(0,\sigma^2)$ ```python A.Compose([ A.HueSaturationValue(hue_shift_limit=20, sat_shift_limit=30, val_shift_limit=20, p=0.5), A.GaussNoise(var_limit=(10, 50), p=0.3) ]) ``` 3. **复合增强策略** YOLOv4使用的Mosaic增强将4张图拼接训练: $$ \text{loss} = \sum_{i=1}^4 \lambda_i \cdot \text{loss}_i $$ 其中$\lambda_i$为各图的损失权重[^2] ### 二、完整代码示例 ```python import cv2 import json import albumentations as A # 标注转换函数(YOLO格式 -> [x_center,y_center,width,height]) def yolo_to_albument(bbox, img_w, img_h): x_c, y_c, w, h = bbox return [x_c*img_w - w*img_w/2, # x_min y_c*img_h - h*img_h/2, # y_min x_c*img_w + w*img_w/2, # x_max y_c*img_h + h*img_h/2, # y_max ] transform = A.Compose([ A.RandomBrightnessContrast(p=0.5), A.HorizontalFlip(p=0.5), A.RandomSnow(snow_point_lower=0.1, snow_point_upper=0.3, p=0.2) ], bbox_params=A.BboxParams(format='yolo')) # 加载数据 with open('annotations.json') as f: anns = json.load(f) for ann in anns: img = cv2.imread(ann['image_path']) bboxes = [yolo_to_albument(box, img.shape[1], img.shape[0]) for box in ann['boxes']] transformed = transform(image=img, bboxes=bboxes) aug_img = transformed['image'] aug_boxes = transformed['bboxes'] # 保存增强后的数据 cv2.imwrite(f"aug_{ann['image_id']}.jpg", aug_img) # 转换回YOLO格式并保存新标注 ``` ### 三、特殊场景处理技巧 1. **小目标增强** - 复制-粘贴策略:将小目标随机复制到图像空白区域 ```python A.Compose([ A.RandomSmallObjectPaste(p=0.5, objects_count=3, objects_size=(10,30)) ]) ``` 2. **遮挡增强** 使用随机擦除模拟遮挡: $$ \text{erase\_prob} = 0.5 \times \frac{\text{object\_size}}{\text{image\_size}} $$ 确保小目标的擦除概率更低 ### 四、工程实践建议 1. 使用$k$-折交叉验证评估扩增效果: $$ \text{mAP}_{aug} = \frac{1}{k}\sum_{i=1}^k \text{mAP}_i $$ 2. 建立扩增流水线时注意: - 先执行几何变换再颜色变换 - 裁剪操作后必须验证标注有效性 - 保持类别分布平衡
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值