翻譯 | 王文剛
我們為什麼需要圖像增強?
深度學習卷積神經網絡(CNN)需要大量圖像才能有效訓練模型。通過更好的增強有助于提高模型的性能,進而減少過度拟合。可用于分類和對象檢測資料集的最流行的資料集具有數千到數百萬個圖像。
歸納是指在模型訓練期間根據以前從未見過的資料進行評估模型的性能測試或驗證。由于 CNN 具有不變性,即使在不同大小,方向或不同照明下可見時,它也可以對對象進行分類。是以,我們可以擷取圖像的小型資料集,并通過放大或縮小,垂直或水準翻轉它們或更改亮度來改變對象的大小。這樣,我們可以建立豐富、多樣化的圖像資料集。
圖像增強可以從一小組圖像中建立豐富多樣的圖像集,以進行圖像分類,目标檢測或圖像分割。在仔細了解問題域之後,需要采用增加訓練資料集大小的增強政策。
什麼時候需要應用圖像增強?
在我們訓練模型之前,可以将圖像增強用作預處理。
- 離線或預處理增強
增強被用作預處理步驟,以增加資料集的大小。通常,當我們有一個小的訓練資料集要擴充時,便可以完成此操作。
在較小的資料集上生成擴充很有幫助,但在應用于較大的資料集時,我們需要考慮磁盤空間。
- 線上或實時增強
顧名思義,增強是實時應用的。這通常适用于較大的資料集,因為我們不需要将增強的映像儲存在磁盤上。
在這種情況下,我們在小批量中應用轉換,然後将其輸入模型。
線上增強模型将在每個時期看到不同的圖像。在“離線增強”中,增強圖像是訓練集的一部分,它會根據時期數多次檢視增強圖像。
該模型可通過線上增強更好地推廣,因為它在通過線上資料增強進行訓練期間會看到更多樣本。
我們将使用 imgaug 類來示範圖像增強。
基本圖像處理技術
- 翻轉:垂直或水準翻轉圖像
- 旋轉:将圖像旋轉指定的角度。
- 剪切:像平行四邊形一樣移動圖像的一部分
- 裁剪:對象以不同比例出現在圖像中的不同位置
- 放大,縮小
- 改變亮度或對比度
現在,我們将使用 imgaug 庫探索這些資料增強技術
Imgaug
imgaug 是一個用于圖像增強以及關鍵點 / 地标,邊界框,熱圖和分段圖的庫。
pip install imgaug
在某些情況下,我們會遇到 Shapely 錯誤,在這種情況下,我們可以嘗試使用以下指令
pip install imgaug — upgrade — no-deps
我們将拍攝一張圖像,并使用基本的資料增強技術對其進行轉換實踐。
導入所需的庫
import imageio
import imgaug as ia
import imgaug.augmenters as iaa
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib
%matplotlib inline
顯示原始圖像
我們使用 imageio 顯示原始圖像
image = imageio.imread(“.\\car2.jpeg”)
ia.imshow(image)

旋轉影像
我們可以通過指定旋轉角度來旋轉圖像。我們将圖像旋轉 -50 度到 30 度
rotate=iaa.Affine(rotate=(-50, 30))
rotated_image=rotate.augment_image(image)
ia.imshow(rotated_image)
給圖像添加噪點
我們将從高斯分布采樣的不同噪聲值添加到圖像。
gaussian_noise=iaa.AdditiveGaussianNoise(10,20)
noise_image=gaussian_noise.augment_image(image)
ia.imshow(noise_image)
裁剪圖像
修剪會删除圖像側面的像素列 / 行。在下面的示例中,我們将圖像的一側裁剪了 30%
crop = iaa.Crop(percent=(0, 0.3)) # crop image
corp_image=crop.augment_image(image)
ia.imshow(corp_image)
扭曲圖像
設定 0 到 40 度
shear = iaa.Affine(shear=(0,40))
shear_image=shear.augment_image(image)
ia.imshow(shear_image)
翻轉圖像
我們可以垂直或水準翻轉圖像。Fliplr 水準翻轉圖像
#flipping image horizontally
flip_hr=iaa.Fliplr(p=1.0)
flip_hr_image= flip_hr.augment_image(image)
ia.imshow(flip_hr_image)
垂直翻轉圖像
flip_vr=iaa.Flipud(p=1.0)
flip_vr_image= flip_vr.augment_image(image)
ia.imshow(flip_vr_image)
改變圖像的亮度
我們使用 GammaContrast 通過縮放像素值來調整圖像亮度。在 gamma =(0.5,2.0)範圍内的值似乎是明智的。我們也可以使用 SigmoidContrast 或 LinearContrast 來更改圖像的亮度
image = imageio.imread(“.\\img Aug\\car2.jpeg”)
contrast=iaa.GammaContrast(gamma=2.0)
contrast_image =contrast.augment_image(image)
ia.imshow(contrast_image)
縮放圖像
我們可以使用縮放來放大或縮小圖像。我們已将圖像縮放到圖像高度 / 寬度的 150%至 80%。我們可以獨立縮放每個軸
增強物體檢測
我們繪制邊界框以進行對象檢測。當我們放大圖像時,我們希望包圍盒也相應地更新。
imgaug 支援邊界框。當我們旋轉,剪切或裁剪圖像時,對象周圍的邊界框也會相應更新。
從 imgaug 導入邊界框
from imgaug.augmentables.bbs import BoundingBox, BoundingBoxesOnImage
初始化原始圖像周圍的邊界框
bbs = BoundingBoxesOnImage([
BoundingBox(x1=10, x2=520, y1=10, y2=300)
], shape=image.shape)
在原始圖像上方顯示邊框
ia.imshow(bbs.draw_on_image(image, size=2))
在下面的代碼中,我們使用 translate_percentage 移動圖像,擴大邊界框并将其應用于圖像上
move=iaa.Affine(translate_percent={"x": 0.1}, scale=0.8)
image_aug, bbs_aug = move(image=image, bounding_boxes=bbs)
ia.imshow(bbs_aug.draw_on_image(image_aug, size=2))
應用圖像增強後在圖像外部處理邊界框
邊框有時可能會超出圖像,是以我們需要其他代碼來處理這種情況
我們旋轉圖像,并嘗試在對象周圍繪制邊框
rotate_bb=iaa.Affine(rotate=(-50, 30))
image_aug, bbs_aug = rotate_bb(image=image, bounding_boxes=bbs)
ia.imshow(bbs_aug.draw_on_image(image_aug, size=2))
邊界框的部分在圖像外部。在下面的代碼中,我們将
- 将邊框完全或部分移出圖像
- 裁剪部分位于外部的邊界框,使其完全位于圖像内部
我們建立一個 padding 函數,以 1 像素的白色邊框和 1 像素的黑色邊框填充圖像:
def pad(image, by):
image_border1 = ia.pad(image, top=1, right=1, bottom=1, left=1,
mode="constant", cval=255)
image_border2 = ia.pad(image_border1, top=by-1, right=by-1,
bottom=by-1, left=by-1,
mode="constant", cval=0)
return image_border2
然後,我們在圖像上繪制邊界框。我們首先将圖像平面擴充 BORDER 像素,然後标記圖像平面内的邊界框
def draw_bbs(image, bbs, border):
GREEN = [0, 255, 0]
ORANGE = [255, 140, 0]
RED = [255, 0, 0]
image_border = pad(image, border)
for bb in bbs.bounding_boxes:
if bb.is_fully_within_image(image.shape):
color = GREEN
elif bb.is_partly_within_image(image.shape):
color = ORANGE
else:
color = RED
image_border = bb.shift(left=border, top=border)\
.draw_on_image(image_border, size=2, color=color)
return image_border
現在,我們對圖像應用相同的旋轉并繪制邊界
rotate=iaa.Affine(rotate=(-50, 30))
image_aug, bbs_aug = rotate(image=image, bounding_boxes=bbs)
image_after = draw_bbs(image_aug, bbs_aug.remove_out_of_image().clip_out_of_image(), 100)
ia.imshow(image_after)
阿裡巴巴開源大資料技術團隊成立Apache Spark中國技術社群,定期推送精彩案例,技術專家直播,問答區近萬人Spark技術同學線上提問答疑,隻為營造純粹的Spark氛圍,歡迎釘釘掃碼加入!
對開源大資料和感興趣的同學可以加小編微信(下圖二維碼,備注“進群”)進入技術交流微信群。