<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          數(shù)據(jù)讀取與數(shù)據(jù)擴(kuò)增方法(附代碼)

          共 11314字,需瀏覽 23分鐘

           ·

          2022-12-17 21:36

          本文約5000字,建議閱讀10分鐘
          本文對圖像數(shù)據(jù)讀取及圖像數(shù)據(jù)擴(kuò)增方法進(jìn)行了總結(jié)。


          本文對圖像數(shù)據(jù)讀取及圖像數(shù)據(jù)擴(kuò)增方法進(jìn)行了總結(jié),并以阿里天池零基礎(chǔ)入門CV賽事為實(shí)踐,利用Pytorch對數(shù)據(jù)進(jìn)行了讀取和擴(kuò)增講解。


          數(shù)據(jù)及背景


          https://tianchi.aliyun.com/competition/entrance/531795/introduction(阿里天池-零基礎(chǔ)入門CV賽事)


          數(shù)據(jù)讀取方法


          接下來將簡單介紹五種目前較為主流的Python圖像庫的基本使用方法:matplotlib、PIL(pillow)、OpenCV、skimage、imageio。


          1. matplotlib


          matplotlib是Python的繪圖庫,與numpy一起使用可以算是一種matlab開源替代方案,在科學(xué)繪圖領(lǐng)域被廣泛使用。當(dāng)然,用來讀取圖像自然不在話下。


          使用plt.imread()讀取圖片將其儲(chǔ)存為一個(gè)RGB像素值矩陣,再進(jìn)行處理。故其可以與opencv或pillow結(jié)合使用,只需要傳入像素值矩陣,matplotlib便可以接手處理接下來想要完成的操作。


          import matplotlib.pyplot as plt #導(dǎo)入matplotlib庫import numpy as np #導(dǎo)入numpy庫
          img = plt.imread('PicPath/PicName.jpg') # 讀取圖片print(img.shape) # 輸出(高度h,寬度w,通道數(shù)c)print(img.size) # 輸出像素總數(shù)目print(img.dtype) # 輸出圖片類型,uint8為[0-255]print(img) # 輸出所有像素的RGB值,一個(gè)像素RGB為[0-255 0-255 0-255]plt.imshow(img) # 將圖片img插入畫布plt.axis('off') # 坐標(biāo)軸刻度不顯示plt.show() # 展示畫布
          imgR = image[:,:,0] # R通道,熱量圖plt.imshow(imgR) # 將熱量圖插入畫布plt.show() # 展示畫布
          plt.imshow(imgR,cmap='Greys_r') # 將灰度圖插入畫布plt.show() # 展示畫布
          figure = plt.figure(figsize=(80,40)) # 調(diào)整顯示畫布寬80,高40/英寸img1 = plt.imread('PicPath/PicName1.jpg') # 讀取圖片1img2 = plt.imread('PicPath/PicName2.jpg') # 讀取圖片2
          plt.axis("off") # 畫布坐標(biāo)軸刻度不顯示ax = figure.add_subplot(121) # 畫布以1行2列的形式顯示,設(shè)置圖片定位為序列1plt.axis('off') # 子圖1坐標(biāo)軸刻度不顯示ax.imshow(img1) # 將圖片1插入子圖1ax.set_title('title1') # 給子圖1加標(biāo)題ax = figure.add_subplot(122) # 畫布以1行2列的形式顯示,設(shè)置圖片定位為序列2plt.axis('off') # 子圖2坐標(biāo)軸刻度不顯示ax.imshow(img2) # 將圖片2插入子圖2ax.set_title('title2') # 給子圖2加標(biāo)題plt.savefig('PicX.jpg') # 保存畫布命名為PicX.jpgplt.show() # 展示畫布

          2. PIL(pillow)


          PIL即Python Imaging Library,而pillow是PIL的一個(gè)分支。pillow提供了常見的圖像讀取和處理的操作,它比opencv更為輕巧,且可以與ipython notebook無縫集成。


          使用Image.open()讀取圖片儲(chǔ)存為一個(gè)對象,并非是numpy矩陣。


          from PIL import Image # 導(dǎo)入PIL庫import numpy as np # 導(dǎo)入numpy庫
          img = Image.open('PicPath/PicName.jpg') # 讀取圖片imgL = Image.open('PicName.jpg').convert('L') # 讀取圖片灰度圖imgL.show() # 展示灰度圖img1 = img.copy() # 復(fù)制圖片print(img.format) # 輸出圖片格式print(img.size) # 輸出圖片(寬度w,高度h)print(img.mode) # 輸出圖片類型,L為灰度圖,RGB為真彩色,RGBA為RGB+Alpha透明度im.show() # 展示畫布
          imgData = np.array(img) # 將對象img轉(zhuǎn)化為RGB像素值矩陣print(imgData.shape) # 輸出圖片(寬度w,高度h,通道c)print(imgData.dtype) # 輸出圖片類型,uint8為[0-255]print(imgData) # 輸出所有像素的RGB值imgN = Image.fromarray(imgData) # 將RGB像素值矩陣轉(zhuǎn)化為對象imgNimgN.save('PicName.jpg') # 儲(chǔ)存為文件PicName.jpg
          r, g, b = img.split() # 分離通道img = Image.merge("RGB", (b, g, r)) # 合并通道
          # ROI(region of interest),只對ROI區(qū)域操作roi = img.crop((0,0,300,300)) # (左上x,左上y,右下x,右下y)坐標(biāo)roi.show() # 展示ROI區(qū)域
          #捕捉異IOError,為讀取圖片失敗try: img = Image.open('PicName.jpg')except IOError: print('image failed to load')

          3. OpenCV


          OpenCV是一個(gè)跨平臺(tái)的計(jì)算機(jī)視覺庫。其發(fā)展非常早,擁有眾多的計(jì)算機(jī)視覺、數(shù)字圖像處理和機(jī)器視覺等功能,OpenCV是今天介紹得所有圖像庫中最全面也最強(qiáng)大的庫,學(xué)習(xí)成本也相對要高很多。


          使用cv2.imread讀取圖片將其儲(chǔ)存為一個(gè)BGR像素值矩陣,故若要結(jié)合使用matplotlib則要先進(jìn)行轉(zhuǎn)化。


          import cv2 # 導(dǎo)入OpenCV庫import numpy as np # 導(dǎo)入numpy庫
          img = cv2.imread('PicName.jpg',0) # 讀取圖片:灰度模式img = cv2.imread('PicName.jpg',-1) # 讀取圖片:BRGA模式(BRG+Alpha通道)img = cv2.imread('PicName.jpg',1) # 讀取圖片:BRG模式img = cv2.imread('PicName.jpg') # 讀取圖片:第二參數(shù)默認(rèn)為1,BRG模式img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) # 將顏色通道從BRG轉(zhuǎn)為RGBif img == None: # 讀取圖片失敗 print('image failed to load')cv2.imshow('src',img) # 圖片源src為imgprint(img.shape) # 輸出圖片(高度h,寬度w,通道c)print(img.size) # 像素總數(shù)目print(img.dtype) # 輸出圖片類型,uint8為[0-255]print(img) # 輸出所有像素的RGB值cv2.waitKey() # 按鍵關(guān)閉窗口# waitKey(delay)函數(shù)的功能是不斷刷新圖像,頻率時(shí)間為delay,單位為ms,返回值為當(dāng)前鍵盤按鍵值# waitKey() 是在一個(gè)給定的時(shí)間內(nèi)(單位ms)等待用戶按鍵觸發(fā); 如果用戶沒有按下鍵,則接續(xù)等待(循環(huán))
          imgL = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 讀取img灰度圖cv2.imshow('gray',imgL) # 圖片源gray為imgLcv2.imwrite('imgL.jpg',imgL) # 將imgL儲(chǔ)存名為imgL.jpg的圖片print(imgL.shape) # 輸出圖片(高度h,寬度w)print(imgL.size) # 像素總數(shù)目print(imgL) # 輸出所有像素的灰度值cv2.waitKey() # 按鍵關(guān)閉窗口
          img = img.transpose(2,0,1) # 圖片矩陣變換為(通道c,高度h,寬度w)img = np.expand_dims(img, axis=0) # 圖片矩陣擴(kuò)展維度添加在第一維print(img.shape) # (1,通道c,高度h,寬度w)
          # 圖片歸一化處理img = cv2.imread('PicName.jpg') img = img.astype("float") / 255.0 # 轉(zhuǎn)化數(shù)據(jù)類型為float后進(jìn)行歸一化print(img.dtype) # 輸出為:float64print(img) # 輸出為[0-1 0-1 0-1]

          print(img[10,10]) # 訪問圖片img像素[10,10],輸出 [0-255 0-255 0-255]print(imgL[10,10]) # 訪問灰色圖片img像素[10,10],輸出 0-255img[10,10] = [255,255,255] # 修改圖片img像素點(diǎn)[10,10]為[255,255,255]imgL[10,10] = 255 # 修改灰色圖片img像素點(diǎn)[10,10]為255img[:,:,2] = 0 # 將R通道全部修改為0
          roi = img[200:550,100:450,:] # ROI操作,坐標(biāo)(高度范圍,寬度范圍,通道范圍)cv2.imshow('roi',roi) # 圖片源roi為roicv2.waitKey() # 按鍵關(guān)閉窗口

          4. skimage


          skimage包的全稱是scikit-image SciKit (toolkit for SciPy) ,它對scipy.ndimage進(jìn)行了擴(kuò)展,提供了更多的圖片處理功能。它是由python語言編寫的,由scipy 社區(qū)開發(fā)和維護(hù)。skimage包由許多的子模塊組成,各個(gè)子模塊提供不同的功能。


          使用io.imread()讀取圖片將其儲(chǔ)存為一個(gè)RGB像素值矩陣。


          from skimage import io #導(dǎo)入skimage庫from skimage import colorimport numpy as np #導(dǎo)入numpy庫
          img = io.imread('PicName.jpg') #讀取圖片imgL = io.imread('PicName.jpg',as_grey=True) #讀取圖片:灰度模式print(img.shape) #輸出圖片img(高度h,寬度w,通道c)print(imgL.shape) #輸出圖片imgL(高度h,寬度w)print(img.size) #img像素總數(shù)目print(img.dtype) #輸出img圖片類型,uint8為[0-255]print(imgL.dtype) #輸出imgL圖片類型,float64為[0-1],已經(jīng)被歸一化print(img) #輸出img所有像素的RGB值print(imgL) #輸出imgL所有灰度值,長度為imgL.size的numpy數(shù)組io.imsave('img.png',img) #將img儲(chǔ)存名為img.png的圖片io.imshow(img) #圖片img插入畫板io.show() #展示畫板
          imgl = io.imread('PicName.jpg') #讀取圖片imgl = color.rgb2grey(imgl) #轉(zhuǎn)換為灰度模式print(imgl.dtype) #以下數(shù)據(jù)同imgLprint(imgl.size)print(imgl.shape)io.imshow(imgl)io.show()
          '''skimage.color.rgb2grey(rgb)skimage.color.rgb2hsv(rgb)skimage.color.rgb2lab(rgb)skimage.color.gray2rgb(image)skimage.color.hsv2rgb(hsv)skimage.color.lab2rgb(lab)'''

          5. imageio


          Imageio是一個(gè)Python庫,提供了一個(gè)簡單的接口用于讀取和寫入各種圖像數(shù)據(jù),包括動(dòng)畫圖像,視頻,體積數(shù)據(jù)和科學(xué)格式。


          使用io.imread()讀取圖片將其儲(chǔ)存為一個(gè)RGB像素值矩陣。


          import imageio #導(dǎo)入imageio庫img = imageio.imread('PicName.jpg') # 讀取圖片imageio.imsave('img.png',img)# 將img儲(chǔ)存名為img.png的文件print(img.shape) # 輸出圖片img(高度h,寬度w,通道c)print(img.size) # img像素總數(shù)目print(img.dtype) # 輸出img圖片類型,uint8為[0-255]print(img) # 輸出img所有像素的RGB值plt.imshow(img) # 圖片img插入畫板plt.show() #展示畫板

          6. 總結(jié)


          其他圖像庫讀取彩色圖片都以RGB形式儲(chǔ)存,而OpenCV則是以BGR形式存儲(chǔ)。其他圖像庫讀取圖片都以numpy十六進(jìn)制彩色值形式儲(chǔ)存,而PIL讀取圖片是以對象形式儲(chǔ)存。


          數(shù)據(jù)擴(kuò)增


          為了增加數(shù)據(jù)量、豐富數(shù)據(jù)多樣性、提高模型的泛化能力,同時(shí)也可以有效緩解模型過擬合的情況,給模型帶來的更強(qiáng)的泛化能力。我們可以不實(shí)際增加原始數(shù)據(jù),只是對原始數(shù)據(jù)做一些變換,從而創(chuàng)造出更多的數(shù)據(jù)。我們只需要對現(xiàn)有數(shù)據(jù)集進(jìn)行微小改動(dòng),例如裁剪或灰度變換或翻轉(zhuǎn)(數(shù)字6與9翻轉(zhuǎn)會(huì)發(fā)生交換) 。無論如何,我們的神經(jīng)網(wǎng)絡(luò)會(huì)認(rèn)為這些是不同的圖像。從而完成數(shù)據(jù)擴(kuò)增(Data Augmentation)操作。



          1. 數(shù)據(jù)擴(kuò)增為什么有用?


          在深度學(xué)習(xí)模型的訓(xùn)練過程中,數(shù)據(jù)擴(kuò)增是必不可少的環(huán)節(jié)?,F(xiàn)有深度學(xué)習(xí)的參數(shù)非常多,一般的模型可訓(xùn)練的參數(shù)量基本上都是萬到百萬級(jí)別,而訓(xùn)練集樣本的數(shù)量很難有這么多。


          其次數(shù)據(jù)擴(kuò)增可以擴(kuò)展樣本空間,假設(shè)現(xiàn)在的分類模型需要對汽車進(jìn)行分類,左邊的是汽車A,右邊為汽車B。如果不使用任何數(shù)據(jù)擴(kuò)增方法,深度學(xué)習(xí)模型會(huì)從汽車車頭的角度來進(jìn)行判別,而不是汽車具體的區(qū)別。


          2. 有哪些數(shù)據(jù)擴(kuò)增方法?


          數(shù)據(jù)擴(kuò)增方法有很多:從顏色空間、尺度空間到樣本空間,同時(shí)根據(jù)不同任務(wù)數(shù)據(jù)擴(kuò)增都有相應(yīng)的區(qū)別。


          對于圖像分類,數(shù)據(jù)擴(kuò)增一般不會(huì)改變標(biāo)簽;對于物體檢測,數(shù)據(jù)擴(kuò)增會(huì)改變物體坐標(biāo)位置;對于圖像分割,數(shù)據(jù)擴(kuò)增會(huì)改變像素標(biāo)簽。


          torchvision.transforms為例,首先整體了解數(shù)據(jù)擴(kuò)增的方法,包括:


          2.1  裁剪


          • 中心裁剪:transforms.CenterCrop;

          • 隨機(jī)裁剪:transforms.RandomCrop;

          • 隨機(jī)長寬比裁剪:transforms.RandomResizedCrop;

          • 上下左右中心裁剪:transforms.FiveCrop;

          • 上下左右中心裁剪后翻轉(zhuǎn): transforms.TenCrop。


          2.2  翻轉(zhuǎn)和旋轉(zhuǎn)


          • 依概率p水平翻轉(zhuǎn):transforms.RandomHorizontalFlip(p=0.5);

          • 依概率p垂直翻轉(zhuǎn):transforms.RandomVerticalFlip(p=0.5);

          • 隨機(jī)旋轉(zhuǎn):transforms.RandomRotation。


          2.3  隨機(jī)遮擋


          • 對圖像進(jìn)行隨機(jī)遮擋: transforms.RandomErasing。


          2.4  圖像變換


          • 尺寸變換:transforms.Resize;

          • 標(biāo)準(zhǔn)化:transforms.Normalize;

          • 填充:transforms.Pad;

          • 修改亮度、對比度和飽和度:transforms.ColorJitter;

          • 轉(zhuǎn)灰度圖:transforms.Grayscale;

          • 依概率p轉(zhuǎn)為灰度圖:transforms.RandomGrayscale;

          • 線性變換:transforms.LinearTransformation();

          • 仿射變換:transforms.RandomAffine;

          • 將數(shù)據(jù)轉(zhuǎn)換為PILImage:transforms.ToPILImage;

          • 轉(zhuǎn)為tensor,并歸一化至[0-1]:transforms.ToTensor;

          • 用戶自定義方法:transforms.Lambda。


          2.5  對transforms操作,使數(shù)據(jù)增強(qiáng)更靈活


          • transforms.RandomChoice(transforms): 從給定的一系列transforms中選一個(gè)進(jìn)行操作;

          • transforms.RandomApply(transforms, p=0.5): 給一個(gè)transform加上概率,依概率進(jìn)行操作;

          • transforms.RandomOrder: 將transforms中的操作隨機(jī)打亂。


          3. 常用的數(shù)據(jù)擴(kuò)增庫?


          3.1  torchvision


          pytorch官方提供的數(shù)據(jù)擴(kuò)增庫,提供了基本的數(shù)據(jù)擴(kuò)增方法,可以無縫與torch進(jìn)行集成;但數(shù)據(jù)擴(kuò)增方法種類較少,且速度中等;

          鏈接:
          https://github.com/pytorch/vision


          3.2  imgaug


          imgaug是常用的第三方數(shù)據(jù)擴(kuò)增庫,提供了多樣的數(shù)據(jù)擴(kuò)增方法,且組合起來非常方便,速度較快;

          鏈接:

          https://github.com/aleju/imgaug


          3.3  albumentations


          是常用的第三方數(shù)據(jù)擴(kuò)增庫,提供了多樣的數(shù)據(jù)擴(kuò)增方法,對圖像分類、語義分割、物體檢測和關(guān)鍵點(diǎn)檢測都支持,速度較快。

          鏈接:

          https://albumentations.readthedocs.io


          Pytorch讀取數(shù)據(jù)


          由于本次賽題我們使用Pytorch框架講解具體的解決方案,接下來將是解決賽題的第一步使用Pytorch讀取賽題數(shù)據(jù)。


          在Pytorch中數(shù)據(jù)是通過Dataset進(jìn)行封裝,并通過DataLoder進(jìn)行并行讀取。所以我們只需要重載一下數(shù)據(jù)讀取的邏輯就可以完成數(shù)據(jù)的讀取。


          import os, sys, glob, shutil, jsonimport cv2from PIL import Imageimport numpy as npimport torchfrom torch.utils.data.dataset import Datasetimport 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為數(shù)字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)), # 隨機(jī)顏色變換 transforms.ColorJitter(0.2, 0.2, 0.2), # 加入隨機(jī)旋轉(zhuǎn) transforms.RandomRotation(5), # 將圖片轉(zhuǎn)換為pytorch 的tesntor # transforms.ToTensor(), # 對圖像像素進(jìn)行歸一化 # transforms.Normalize([0.485,0.456,0.406],[0.229,0.224,0.225]) ]))


          通過上述代碼,可以將賽題的圖像數(shù)據(jù)和對應(yīng)標(biāo)簽進(jìn)行讀取,在讀取過程中的進(jìn)行數(shù)據(jù)擴(kuò)增,效果如下所示:



          接下來我們將在定義好的Dataset基礎(chǔ)上構(gòu)建DataLoder,你可以會(huì)問有了Dataset為什么還要有DataLoder?其實(shí)這兩個(gè)是兩個(gè)不同的概念,是為了實(shí)現(xiàn)不同的功能。


          • Dataset:對數(shù)據(jù)集的封裝,提供索引方式的對數(shù)據(jù)樣本進(jìn)行讀取

          • DataLoder:對Dataset進(jìn)行封裝,提供批量讀取的迭代讀取


          加入DataLoder后,數(shù)據(jù)讀取代碼改為如下:


          import os, sys, glob, shutil, jsonimport cv2from PIL import Imageimport numpy as npimport torchfrom torch.utils.data.dataset import Datasetimport 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為數(shù)字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, # 每批樣本個(gè)數(shù) shuffle=False, # 是否打亂順序 num_workers=10, # 讀取的線程個(gè)數(shù))for data in train_loader: break


          在加入DataLoder后,數(shù)據(jù)按照批次獲取,每批次調(diào)用Dataset讀取單個(gè)樣本進(jìn)行拼接。此時(shí)data的格式為:

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


          前者為圖像文件,為batchsize * chanel * height * width次序;后者為字符標(biāo)簽。


          編輯:于騰凱

          瀏覽 83
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产女生被男生操网站 | 亚洲人成小说 | 99久久精品互换人妻 | 99在线免费视频 | 青青草蜜桃 |