Date: 2020-08-27
在機器視覺領域,想將深度學習應用於實際工程項目,並最終落地,會遇到很多問題:光照、遮擋等。而采集到的數據通常難以滿足各種現實環境,需要進行數據增強操作。 imgaug是一個基於OpenCV的更高級的API,包含很多集成好的圖像增強的方法。
安裝方式:
-
-
conda install imgaug
導入和增強圖像
輸入的圖像需要符合以下兩種規格之一:
-
可以是4D的numpy數組,形狀需要滿足“NHWC”原則,即(N, height, width, channels)
-
也可以是一個由3D numpy數組組成的列表list,3D numpy數組的形狀需要滿足(height, width, channels) 對於灰度圖像,其形狀必須滿足(height, width, 1)
並且所有的圖像必須是numpy數組的uint8格式,數值需要是在0-255之間。
uint8是所有API測試最徹底的數據類型,其余的格式例如float32,需要查看imgaug API的文檔是否支持。
圖像導入函數
imgaug只是進行圖像增強的庫函數,其中並沒有相關圖像的讀取和輸出的函數。因此,需要使用其他的庫進行圖像的導入:
-
imageio
-
cv2.imread()
另外,值得注意的是,cv2.imread()函數返回的圖像顏色空間是BGR,而不是RGB,因此,需要手動改變其通道組成: cv2.imread(path)[:, :, ::-1]
因此,提倡使用imageio進行圖像的導入。
導入並增強一張圖片
imagio.imread("/path/to/the/file.jpg")
windows: imagio.imread("C:\path\to\the\file.jpg") 返回的是一個uint8格式的numpy數組,形狀為HWC--RGB空間。
1 import imageio 2 import imgaug as ia 3 %matplotlib inline 4 5 image = imageio.imread("./pick1.jpg") # Image格式 6 7 print("Original") 8 ia.imshow(image)
Original
imgaug沒有讀圖像的語句,但是有顯示圖像的語句。
1 # 增強 2 from imgaug import augmenters as iaa 3 4 ia.seed(4) 5 6 rotate = iaa.Affine(rotate=(-25, 25)) # 旋轉 7 image_aug = rotate(image=image) # 處理后是numpy數組格式 8 9 print("Augmented:") 10 ia.imshow(image_aug)
Augmented:
可以看出,圖像發生了[-25, 25]之間角度的旋轉。
在使用imgaug中包含的數據增強功能時,需要先通過傳參生成某種數據增強的實例,再通過實例對圖像進行處理。
-
嘗試一下ia.seed(4),觀察是否可以讓旋轉的角度相同。
1 ia.seed(4) 2 image_aug = rotate(image=image) 3 4 print("Re-Augmented:") 5 ia.imshow(image_aug)
Re-Augmented:
仿佛每次的結果都是一樣的。
-
再試試更改一下數值。
1 ia.seed(5) 2 image_aug = rotate(image=image) 3 4 print("Augmented:") 5 ia.imshow(image_aug)
Augmented:
結果發生了隨機性的變化。
增強一個batch數量的圖像
實際使用中,我們通常需要處理更多份的圖像數據,而不是一張。此時,可以將圖形數據按照NHWC的形式或者由列表組成的HWC的形式對批量的圖像進行處理。
如下述代碼,將一份圖像存儲多次形成一個batch數量的圖像。經過處理后,使用np.hstack()對處理后的圖像進行顯示。
1 import numpy as np 2 3 images = [image, image, image, image, image] 4 images_aug = rotate(images=images) 5 6 print("Augmented batch:") 7 ia.imshow(np.hstack(images_aug))
Augmented batch:
同時使用多種增強技術
之前使用的方法僅僅在一張圖像或者多張圖像上使用了一種Affine的增強技術,在實際深度學習模型訓練中,往往需要同時使用多種圖像增強技術,從而讓模型適應變化的外界條件。
在使用多種圖像增強技術時,可以使用imgaug中類似keras和Pytorch中Sequential方法,將多種增強技術拼接在一起。如下所示:
1 seq = iaa.Sequential([iaa.Affine(rotate=(-25, 25)), 2 iaa.AdditiveGaussianNoise(scale=(10, 60)), 3 iaa.Crop(percent=(0, 0.2)) 4 ]) 5 6 images_aug = seq(images=images) 7 8 print("Augmented:") 9 ia.imshow(np.hstack(images_aug))
Augmented:
Crop()默認會保持輸入圖像的尺寸,如果將keep_size=False,輸入輸出的尺寸將可能會發生變化。即該參數表示是否保持圖像尺寸一致。
下述代碼在Sequential中設置了random_order=True,並使用單張圖片重復8次得到的結果。該參數表示是否啟用隨機順序增強。
1 seq = iaa.Sequential([iaa.Affine(rotate=(-25, 25)), 2 iaa.AdditiveGaussianNoise(scale=(30, 90)), 3 iaa.Crop(percent=(0, 0.4))], random_order=True) 4 5 images_aug = [seq(image=image) for _ in range(8)] 6 7 print("Augmented:") 8 ia.imshow(ia.draw_grid(images_aug, cols=4, rows=2))
Augmented:
增強圖像(不同尺寸)
在收集訓練集時,訓練集的尺寸往往難以做到統一尺寸。之前的示例中也總是使用的相同尺寸的圖像。下述代碼介紹了不同尺寸圖像的處理和展示。
對於不同尺寸的圖像,肯定不能使用numpy數組組成NHWC的形式,只能將不同尺寸的圖像存儲於列表中。
1 seq = iaa.Sequential([ 2 iaa.CropAndPad(percent=(-0.2, 0.2), pad_mode="edge"), # crop and pad images 3 iaa.AddToHueAndSaturation((-60, 60)), # change their color 4 iaa.ElasticTransformation(alpha=90, sigma=9), # water-like effect 5 iaa.Cutout() # replace one squared area within the image by a constant intensity value 6 ], random_order=True) 7 8 # load images with different sizes 9 images_different_sizes = [ 10 imageio.imread("./pick1.jpg"), 11 imageio.imread("./flower.jpg"), 12 imageio.imread("./samoye.jpg") 13 ] 14 15 # augment them as one batch 16 images_aug = seq(images=images_different_sizes) 17 18 # visualize the results 19 print("Image 0 (input shape: %s, output shape: %s)" % (images_different_sizes[0].shape, images_aug[0].shape)) 20 ia.imshow(np.hstack([images_different_sizes[0], images_aug[0]])) 21 22 print("Image 1 (input shape: %s, output shape: %s)" % (images_different_sizes[1].shape, images_aug[1].shape)) 23 ia.imshow(np.hstack([images_different_sizes[1], images_aug[1]])) 24 25 print("Image 2 (input shape: %s, output shape: %s)" % (images_different_sizes[2].shape, images_aug[2].shape)) 26 ia.imshow(np.hstack([images_different_sizes[2], images_aug[2]]))
Image 0 (input shape: (313, 500, 3), output shape: (313, 500, 3))
Image 1 (input shape: (621, 500, 3), output shape: (621, 500, 3))
Image 2 (input shape: (406, 500, 3), output shape: (406, 500, 3))
整理總結
本節教程主要包含以下幾個方面的內容:
-
在利用imgaug圖像增強的方法中,如何讀取和顯示圖像; imageio.imread() imgaug.imshow() 不推薦使用opencv,因為其讀入圖像默認為BGR模式;
-
單/多張圖像如何利用一/多種圖像增強方法;
-
如何將不同尺寸的圖像組合在一起進行圖像增強。
本節教程中包含的圖像增強的方法:
-
iaa.Affine(rotate=(-25, 25))
-
實現仿射變換,本節僅利用了其中的旋轉操作;
-
-
iaa.AdditiveGaussianNoise(scale=(10, 60))
-
添加高斯白噪聲
-
-
iaa.Crop(percent=(0, 0.2))
-
實現裁剪,參數為裁剪比例
-
-
iaa.CropAndPad(percent=(-0.2, 0.2), pad_mode="edge")
-
實現裁剪和邊緣補充
-
-
iaa.AddToHueAndSaturation((-60, 60))
-
Hue空間調整飽和度
-
-
iaa.ElasticTransformation(alpha=90, sigma=9)
-
隨機彈性變換(仿射變換的一種)
-
-
iaa.Cutout()
-
圖像增強之 cutout 生成遮擋塊
-
* CropAndPad使用效果:*
1 import imageio 2 import imgaug as ia 3 from imgaug import augmenters as iaa 4 import numpy as np 5 %matplotlib inline 6 7 image = imageio.imread("./pick1.jpg") 8 9 crop = iaa.CropAndPad(percent=(-0.2, 0.2), pad_mode="edge") 10 img_aug = crop(image=image) 11 12 print("Original") 13 ia.imshow(np.hstack([image, img_aug])) 14 #ia.imshow(image) 15 #ia.imshow(img_aug)
Original
* AddToHueAndSaturation使用效果 *
1 import imageio 2 import imgaug as ia 3 from imgaug import augmenters as iaa 4 %matplotlib inline 5 6 image = imageio.imread("./pick1.jpg") 7 8 hue = iaa.AddToHueAndSaturation((-60, 60)) 9 img_aug = hue(image=image) 10 11 print("Original") 12 ia.imshow(np.hstack([image, img_aug])) 13 #ia.imshow(image) 14 #ia.imshow(img_aug)
Original
* ElasticTransformation使用效果 *
1 import imageio 2 import imgaug as ia 3 from imgaug import augmenters as iaa 4 %matplotlib inline 5 6 image = imageio.imread("./pick1.jpg") 7 8 trans = iaa.ElasticTransformation(alpha=90, sigma=9) 9 img_aug = trans(image=image) 10 11 print("Original") 12 ia.imshow(np.hstack([image, img_aug])) 13 #ia.imshow(image) 14 #ia.imshow(img_aug)
Original