數據讀取與擴增

數據讀取

數據擴增方法

讀取給定數據

1、數據讀取

這次比賽主要是識別圖像中的字符,所以首先需要完成對數據的讀取操作,在Python中有很多庫可以完成數據讀取的操作,比較常見的有Pillow和OpenCV。
Pillow是Python圖像處理函式庫(PIL)的一個分支,提供了常見的圖像讀取和處理的操作,而且可以與ipython notebook無縫集成。pillow文檔

# 導入Pillow庫
from PIL import Image,ImageFilter

# 讀取圖片
im =Image.open('qq.JPG')

# 應用模糊濾鏡:
im2 = im.filter(ImageFilter.BLUR)
im2.save('blur.jpg', 'jpeg')

OpenCV是一個跨平臺的計算機視覺庫,擁有衆多的計算機視覺、數字圖像處理和機器視覺等功能。OpenCV包含了衆多的圖像處理的功能,內置了很多的圖像特徵處理算法,如關鍵點檢測、邊緣檢測和直線檢測等。

2、數據擴增方法

在深度學習中數據擴增可以增加訓練集的樣本,同時也可以有效緩解模型過擬合的情況,也可以給模型帶來的更強的泛化能力。
在深度學習模型的訓練過程中,需要大量的數據,但是訓練集樣本的數量有限,通過數據擴增可以增加樣本,也可以對一個圖片的多維特徵進行分析識別,但是本次是識別圖片中字符,不能進行旋轉燈方法來擴增數據,會改變圖片中字符原有的含義;
數據擴增方法如:從顏色空間、尺度空間到樣本空間,同時根據不同任務數據擴增都有相應的區別。對於圖像分類,數據擴增一般不會改變標籤;對於物體檢測,數據擴增會改變物體座標位置;對於圖像分割,數據擴增會改變像素標籤。
在常見的數據擴增方法中,一般會從圖像顏色、尺寸、形態、空間和像素等角度進行變換。當然不同的數據擴增方法可以自由進行組合,得到更加豐富的數據擴增方法。

以torchvision爲例,常見的數據擴增方法:

transforms.CenterCrop 對圖片中心進行裁剪
transforms.ColorJitter 對圖像顏色的對比度、飽和度和零度進行變換
transforms.FiveCrop 對圖像四個角和中心進行裁剪得到五分圖像
transforms.Grayscale 對圖像進行灰度變換
transforms.Pad 使用固定值進行像素填充
transforms.RandomAffine 隨機仿射變換
transforms.RandomCrop 隨機區域裁剪
transforms.RandomHorizontalFlip 隨機水平翻轉
transforms.RandomRotation 隨機旋轉
transforms.RandomVerticalFlip 隨機垂直翻轉

常見數據擴增庫有以下三種:
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 
os.environ["CUDA_VISIBLE_DEVICES"] = '0'
import cv2
from PIL import Image
import numpy as np
from tqdm import tqdm, tqdm_notebook
import torch
torch.manual_seed(0) 
torch.backends.cudnn.deterministic = False 
torch.backends.cudnn.benchmark = True
import torchvision.models as models
import torchvision.transforms as transforms 
import torchvision.datasets as datasets 
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
from torch.utils.data.dataset import Dataset
import matplotlib.pyplot as plt
import json
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('../tianchi/mchar_train/*.png')
train_path.sort()
train_json = json.load(open('../tianchi/mchar_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,對Dataset進行封裝,提供批量讀取的迭代讀取。加入DataLoder後,數據讀取代碼改爲如下:

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('../tianchi/mchar_train/*.png')
train_path.sort()
train_json = json.load(open('../tianchi/mchar_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])
1:圖像文件,爲batchsize * chanel * height * width次序;2:字符標籤。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章