文章來自:微信公眾號【機器學習煉丹術】。歡迎關注支援原創
也歡迎新增作者微信:cyx645016617.
參考目錄:
老樣子,先看官方對torchvision.transforms
的介紹:
這個Transforms是常見的影像的轉換(包含影像增強等), 然後不同的transforms可以通過Compose
函式連線起來(類似於Sequence
把網路層連線起來一樣的感覺)。後面的是關於影像分割任務了的介紹,因為入門PyTorch主要是影像分類,所以後面先不提了。
1 基本函式
1.1 Compose
【程式碼】
torchvision.transforms.Compose(transforms)
【介紹】
將不同的transform壓縮在一起,這是非常重要的函式
【程式碼舉例】
transforms.Compose([
transforms.CenterCrop(10),
transforms.ToTensor(),
])
1.2 RandomChoice
【程式碼】
torchvision.transforms.RandomChoice(transforms)
【介紹】
用法和Compose相同,是在transform的list中隨機選擇1個transform進行執行。
1.3 RandomOrder
【程式碼】
torchvision.transforms.RandomOrder(transforms)
【介紹】
用法和Compose相同,是亂序list中的transform。
之前的課程提到了,在torchvision官方的資料集中,提供的資料是PIL格式的資料,然後我們需要轉成FloatTensor形式的資料。因此這裡影像增強的處理也分成在PIL圖片上操作的和在FloatTensor張量上操作的兩種。
2 PIL上的操作
2.1 中心切割CenterCrop
【程式碼】
torchvision.transforms.CenterCrop(size)
【介紹】
以PIL圖片中心為中心,進行圖片切割。比較常用
【引數】
size (sequence or int) – 想要切割出多大的圖片。如果size是一個整數,那麼就切割一個正方形;如果是一個(height,width)的tuple,那麼就切割一個長方形。
【程式碼舉例】
transforms.Compose([
transforms.CenterCrop(10),
transforms.ToTensor(),
])
2.2 隨機切割RandomCrop
【程式碼】
torchvision.transforms.RandomCrop(size, padding=None, pad_if_needed=False, fill=0, padding_mode='constant')
【介紹】
和CenterCrop類似,但是是隨機選取中心進行切割的
【引數】
- size也是可以是int可以是tuple(height,width)
- padding就是是否對圖片進行填充,你可以輸入2元組,表示左右填充和上下填充,也可以輸入四元組,表示左上右下的填充;
- pad_if_needed是boolean,一般是True。隨機選取如果選取的比較邊緣,超出了邊界,那麼是否進行填充
- fill (int),你選擇填充的是0(黑色),還是255(白色)呢?這個盡在padding_mode='constant'時有效
- padding_mode表示填充的方法。有四種:'constant', 'edge', 'reflect' or 'symmetric' . 預設是constant常數填充。edge是填充邊緣的那個畫素值,一般效果比constant強一些,自己做的專案中;reflect和symmetric都是表示以邊界為軸進行映象的填充,區別在於:
- reflect:[1,2,3,4,5]進行padding=2的時候,那麼就是[3,2,1,2,3,4,5,4,3]
- symmetric:[1,2,3,4,5]進行padding=2的時候,那麼就是[2,1,1,2,3,4,5,5,4]
- 區別是否重複邊界的哪一個元素。兩種方法差別不大。
2.3 隨機比例切割
【程式碼】
torchvision.transforms.RandomResizedCrop(size, scale=(0.08, 1.0), ratio=(0.75, 1.3333), interpolation=2)
【介紹】
這個比較有意思,隨機大小切割圖片,然後再resize到設定的size大小。
引數中scale控制切割圖片的大小是原圖的比例,然後ratio控制切割圖片的高寬比(縱橫比),預設是從3/4 到 4/3。切割完成後再resize到設定的size大小。這個方法一般用在訓練inception網路。
2.4 顏色震顫ColorJitter
【程式碼】
torchvision.transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0)
【介紹】
隨機修改亮度brightness,對比度contrast, 飽和度saturation,色相hue
【引數】
-
brightness (float or tuple (min, max)) – 如果輸入是一個float,那麼建議在選取一個小於1的浮點數。亮度係數會從區間\([max(0, 1 - brightness), 1 + brightness]\)均勻選取,如果我使用這個,我設定brightness是0.1的話,那麼這個係數就是\([0.9,1.1]\)之間隨機選取。如果輸入時一個tuple的話,那麼就是在 \([min,max]\) 中選取。
-
contrast (float or tuple (min, max)) – 和上面一樣,也是一個係數的選取。
-
saturation (float or tuple (min, max)) – 和上面一樣,也是一個係數的選取。
-
hue (float or tuple (min, max)) – hue是色相。這裡色相的取值應該小於0.5。如果輸入時一個float,那麼取值應該\(0<= hue <= 0.5\),係數在\([-hue, hue]\) 選取;如果是tuple,那麼就是\([min, max]\)
2.5 隨機旋轉RandomRotation
【程式碼】
torchvision.transforms.RandomRotation(degrees, resample=False, expand=False, center=None, fill=None)
【介紹】
就是隨機的按照角度宣傳圖片
【引數】
-
degrees (int or tuple (min,max)) – 老規矩了,整數旋轉角度就是[-int,int],tuple就是[min,max]
-
expand (bool, optional) – True就是讓擴大圖片,讓圖片可以包括所有內容(圖片旋轉的話,四個角的資訊其實是旋轉到了圖片的外面,這個是擴大圖片的畫素尺寸,如果True在後面還要接一個resize的transforms); 預設是False,旋轉後的圖片和輸入圖片是同樣的尺寸。
-
center (2-tuple, optional) – 可以設定成非圖片中心的旋轉
-
fill (n-tuple or int or float) – 設定填充畫素值的,預設是0,一般也會選取0.
2.6 灰度化Grayscale
【程式碼】
torchvision.transforms.Grayscale(num_output_channels=1)
【介紹】
這個函式雖然不重要,但是會用的話可以提高變成速度哈哈。就是把圖片轉換成灰度的。
【引數】
- num_output_channels (int) – 正常情況下灰度圖片是單通道的,但是這裡你可以設定成3,這樣的話,會輸出3個通道的灰度圖片(三個通道的特徵值相同),這樣的話,你就不用修改torchvision的預訓練模型中的輸入介面了。(因為之前提到的,預訓練模型使用ImageNet訓練的,輸入都是三通道彩色圖)
2.7 size
【程式碼】
torchvision.transforms.Resize(size, interpolation=2)
【介紹】
把PIL圖片resize成指定大小
【引數】
- size (tuple(height,width) or int) – tuple的話就直接resize成指定大小;int的話,就按照比例,讓圖片的短邊長度變成int大小。
- interpolation (int, optional) – 插值方法,一般都使用預設的PIL.Image.BILINEAR雙重線性插值。
2.8 概率隨機(常用)
影像增強有:變成灰度,映象,翻轉,平移,旋轉等。
【程式碼】
# 變成灰度,輸入輸出通道數預設相同
torchvision.transforms.RandomGrayscale(p=0.1)
# 隨機水平翻轉
torchvision.transforms.RandomHorizontalFlip(p=0.5)
# 隨機豎直翻轉
torchvision.transforms.RandomVerticalFlip(p=0.5)
【引數】
- p:表示執行這個transform的概率
3 Tensor上的操作
3.1 標準化Normalize
【程式碼】
torchvision.transforms.Normalize(mean, std, inplace=False)
【引數】
- mean和std都是list,[mean_1,...,mean_n]和[std_1,...,std_n],n為通道數。每一個通道都應該有一個mean和std。計算的方法是,就是常用的那種:
\(output[channel] = \frac{(input[channel] - mean[channel]) } {std[channel]}\)
4 PIL,Tensor轉換函式
4.1 ToPILImage
torchvision.transforms.ToPILImage(mode=None)
【介紹】
把一個tensor或者np的array轉換成PIL。值得注意的是,如果輸入時Tensor,那麼維度應該是 C x H x W ,如果是numpy的話,是 H x W x C。 (這是一個一般不會出現,但是一旦出現很難想到的問題。)
4.2 ToTensor
torchvision.transforms.ToTensor
【介紹】
把PIL或者numpy轉換成Tensor。PIL和Numpy (格式H x W x C,範圍[0,255]),轉換成Tensor(格式C x H x W,範圍[0,1])
5 案例程式碼分析
from PIL import Image
from torchvision import transforms
def loadImage():
# 讀取圖片
im = Image.open("brunch.jpg")
im = im.convert("RGB")
im.show()
return im
im = loadImage()
圖片是我在英國留學的時候,有一道菜叫無花果土司,雖然不好吃但是好看,原圖:
#從中心裁剪一個600*600的影像
output = transforms.CenterCrop(600)(im)
output.show()
# 從中心裁一個長為600,寬為800的影像
output = transforms.CenterCrop((600,800))(im)
output.show()
#隨機裁剪一個600*600的影像
output = transforms.RandomCrop(600)(im)
output.show()
#隨機裁剪一個600*800的影像
output = transforms.RandomCrop((600,800))(im)
output.show()
#從上、下、左、右、中心各裁一個300*300的影像
outputs = transforms.FiveCrop(300)(im)
outputs[4].show()
類似的圖片,就不佔用painful了
#p預設為0.5,這裡設成1,那麼就肯定會水平翻轉
output = transforms.RandomHorizontalFlip(p=1.0)(im)
output.show()
output = transforms.RandomVerticalFlip(p=1)(im)
output.show()
#在(-30,30)之間選擇一個角度進行旋轉
output = transforms.RandomRotation(30)(im)
output.show()
#在60-90之間選擇一個角度進行旋轉
output = transforms.RandomRotation((60,90))(im)
output.show()
output = transforms.Resize((400,500))(im)
output.show()
這個影像一樣就尺寸變小了,就不放圖了。
trans = transforms.Compose([transforms.CenterCrop(300),
transforms.RandomRotation(30),
])
output = trans(im)
output.show()