Python中的圖像增強技術
圖像增強是一種非常強大的技術,針對現有圖像人為創建各種變化以擴展圖像數據集,例如縮放現有圖像、將現有圖像旋轉幾度、剪切或裁剪圖像等等。在本文中,我們將使用 imgaug 庫探索 Python 中的圖像增強技術。
我們為什么需要圖像增強?
深度學習卷積神經網絡(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)