1. 程式人生 > 實用技巧 >Image Processing 必備(一): Imgaug之匯入和增強影象

Image Processing 必備(一): Imgaug之匯入和增強影象

Date: 2020-08-27

官方教程:https://nbviewer.jupyter.org/github/aleju/imgaug-doc/blob/master/notebooks/A01%20-%20Load%20and%20Augment%20an%20Image.ipynb

在機器視覺領域,想將深度學習應用於實際工程專案,並最終落地,會遇到很多問題:光照、遮擋等。而採集到的資料通常難以滿足各種現實環境,需要進行資料增強操作。 imgaug是一個基於OpenCV的更高階的API,包含很多整合好的影象增強的方法。

安裝方式:

  1. conda config --add channels conda-forge

  2. conda install imgaug

匯入和增強影象

輸入的影象需要符合以下兩種規格之一:

  1. 可以是4D的numpy陣列,形狀需要滿足“NHWC”原則,即(N, height, width, channels)

  2. 也可以是一個由3D numpy陣列組成的列表list,3D numpy陣列的形狀需要滿足(height, width, channels) 對於灰度影象,其形狀必須滿足(height, width, 1)

並且所有的影象必須是numpy陣列的uint8格式,數值需要是在0-255之間。

uint8是所有API測試最徹底的資料型別,其餘的格式例如float32,需要檢視imgaug API的文件是否支援。

影象匯入函式

imgaug只是進行影象增強的庫函式,其中並沒有相關影象的讀取和輸出的函式。因此,需要使用其他的庫進行影象的匯入:

  1. imageio

  2. 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))

整理總結

本節教程主要包含以下幾個方面的內容:

  1. 在利用imgaug影象增強的方法中,如何讀取和顯示影象; imageio.imread() imgaug.imshow() 不推薦使用opencv,因為其讀入影象預設為BGR模式;

  2. 單/多張影象如何利用一/多種影象增強方法;

  3. 如何將不同尺寸的影象組合在一起進行影象增強。

本節教程中包含的影象增強的方法:

  1. iaa.Affine(rotate=(-25, 25))

    • 實現仿射變換,本節僅利用了其中的旋轉操作;

  2. iaa.AdditiveGaussianNoise(scale=(10, 60))

    • 新增高斯白噪聲

  3. iaa.Crop(percent=(0, 0.2))

    • 實現裁剪,引數為裁剪比例

  4. iaa.CropAndPad(percent=(-0.2, 0.2), pad_mode="edge")

    • 實現裁剪和邊緣補充

  5. iaa.AddToHueAndSaturation((-60, 60))

    • Hue空間調整飽和度

  6. iaa.ElasticTransformation(alpha=90, sigma=9)

    • 隨機彈性變換(仿射變換的一種)

  7. 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