Python中的圖像增強(qiáng)技術(shù)
圖像增強(qiáng)是一種非常強(qiáng)大的技術(shù),針對(duì)現(xiàn)有圖像人為創(chuàng)建各種變化以擴(kuò)展圖像數(shù)據(jù)集,例如縮放現(xiàn)有圖像、將現(xiàn)有圖像旋轉(zhuǎn)幾度、剪切或裁剪圖像等等。在本文中,我們將使用 imgaug 庫(kù)探索 Python 中的圖像增強(qiáng)技術(shù)。
我們?yōu)槭裁葱枰獔D像增強(qiáng)?
深度學(xué)習(xí)卷積神經(jīng)網(wǎng)絡(luò)(CNN)需要大量圖像才能有效訓(xùn)練模型。通過更好的增強(qiáng)有助于提高模型的性能,從而減少過度擬合??捎糜诜诸惡蛯?duì)象檢測(cè)數(shù)據(jù)集的最流行的數(shù)據(jù)集具有數(shù)千到數(shù)百萬(wàn)個(gè)圖像。
歸納是指在模型訓(xùn)練期間根據(jù)以前從未見過的數(shù)據(jù)進(jìn)行評(píng)估模型的性能測(cè)試或驗(yàn)證。由于 CNN 具有不變性,即使在不同大小,方向或不同照明下可見時(shí),它也可以對(duì)對(duì)象進(jìn)行分類。因此,我們可以獲取圖像的小型數(shù)據(jù)集,并通過放大或縮小,垂直或水平翻轉(zhuǎn)它們或更改亮度來(lái)改變對(duì)象的大小。這樣,我們可以創(chuàng)建豐富、多樣化的圖像數(shù)據(jù)集。
圖像增強(qiáng)可以從一小組圖像中創(chuàng)建豐富多樣的圖像集,以進(jìn)行圖像分類,目標(biāo)檢測(cè)或圖像分割。在仔細(xì)了解問題域之后,需要采用增加訓(xùn)練數(shù)據(jù)集大小的增強(qiáng)策略。
什么時(shí)候需要應(yīng)用圖像增強(qiáng)?
在我們訓(xùn)練模型之前,可以將圖像增強(qiáng)用作預(yù)處理。
- 離線或預(yù)處理增強(qiáng)
增強(qiáng)被用作預(yù)處理步驟,以增加數(shù)據(jù)集的大小。通常,當(dāng)我們有一個(gè)小的訓(xùn)練數(shù)據(jù)集要擴(kuò)展時(shí),便可以完成此操作。
在較小的數(shù)據(jù)集上生成擴(kuò)充很有幫助,但在應(yīng)用于較大的數(shù)據(jù)集時(shí),我們需要考慮磁盤空間。
- 在線或?qū)崟r(shí)增強(qiáng)
顧名思義,增強(qiáng)是實(shí)時(shí)應(yīng)用的。這通常適用于較大的數(shù)據(jù)集,因?yàn)槲覀儾恍枰獙⒃鰪?qiáng)的映像保存在磁盤上。
在這種情況下,我們?cè)谛∨恐袘?yīng)用轉(zhuǎn)換,然后將其輸入模型。
在線增強(qiáng)模型將在每個(gè)時(shí)期看到不同的圖像。在“離線增強(qiáng)”中,增強(qiáng)圖像是訓(xùn)練集的一部分,它會(huì)根據(jù)時(shí)期數(shù)多次查看增強(qiáng)圖像。
該模型可通過在線增強(qiáng)更好地推廣,因?yàn)樗谕ㄟ^在線數(shù)據(jù)增強(qiáng)進(jìn)行訓(xùn)練期間會(huì)看到更多樣本。
我們將使用 imgaug 類來(lái)演示圖像增強(qiáng)。
基本圖像處理技術(shù)
- 翻轉(zhuǎn):垂直或水平翻轉(zhuǎn)圖像
- 旋轉(zhuǎn):將圖像旋轉(zhuǎn)指定的角度。
- 剪切:像平行四邊形一樣移動(dòng)圖像的一部分
- 裁剪:對(duì)象以不同比例出現(xiàn)在圖像中的不同位置
- 放大,縮小
- 改變亮度或?qū)Ρ榷?/li>
現(xiàn)在,我們將使用 imgaug 庫(kù)探索這些數(shù)據(jù)增強(qiáng)技術(shù)
Imgaug
imgaug 是一個(gè)用于圖像增強(qiáng)以及關(guān)鍵點(diǎn) / 地標(biāo),邊界框,熱圖和分段圖的庫(kù)。
- pip install imgaug
在某些情況下,我們會(huì)遇到 Shapely 錯(cuò)誤,在這種情況下,我們可以嘗試使用以下命令
- pip install imgaug — upgrade — no-deps
我們將拍攝一張圖像,并使用基本的數(shù)據(jù)增強(qiáng)技術(shù)對(duì)其進(jìn)行轉(zhuǎn)換實(shí)踐。
導(dǎo)入所需的庫(kù):
- 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)
旋轉(zhuǎn)影像
我們可以通過指定旋轉(zhuǎn)角度來(lái)旋轉(zhuǎn)圖像。我們將圖像旋轉(zhuǎn) -50 度到 30 度
- rotate=iaa.Affine(rotate=(-50, 30))
- rotated_image=rotate.augment_image(image)
- ia.imshow(rotated_image)
給圖像添加噪點(diǎn)
我們將從高斯分布采樣的不同噪聲值添加到圖像。
- gaussian_noise=iaa.AdditiveGaussianNoise(10,20)
- noise_image=gaussian_noise.augment_image(image)
- ia.imshow(noise_image)
裁剪圖像
修剪會(huì)刪除圖像側(cè)面的像素列 / 行。在下面的示例中,我們將圖像的一側(cè)裁剪了 30%
- crop = iaa.Crop(percent=(0, 0.3)) # crop image
- corp_image=crop.augment_image(image)
- ia.imshow(corp_image)
扭曲圖像
設(shè)置 0 到 40 度
- shear = iaa.Affine(shear=(0,40))
- shear_image=shear.augment_image(image)
- ia.imshow(shear_image)
翻轉(zhuǎn)圖像
我們可以垂直或水平翻轉(zhuǎn)圖像。Fliplr 水平翻轉(zhuǎn)圖像
- #flipping image horizontally
- flip_hr=iaa.Fliplr(p=1.0)
- flip_hr_image= flip_hr.augment_image(image)
- ia.imshow(flip_hr_image)
垂直翻轉(zhuǎn)圖像
- flip_vr=iaa.Flipud(p=1.0)
- flip_vr_image= flip_vr.augment_image(image)
- ia.imshow(flip_vr_image)
改變圖像的亮度
我們使用 GammaContrast 通過縮放像素值來(lái)調(diào)整圖像亮度。在 gamma =(0.5,2.0)范圍內(nèi)的值似乎是明智的。我們也可以使用 SigmoidContrast 或 LinearContrast 來(lái)更改圖像的亮度
- image = imageio.imread(“.\img Aug\car2.jpeg”)
- contrast=iaa.GammaContrast(gamma=2.0)
- contrast_image =contrast.augment_image(image)
- ia.imshow(contrast_image)
縮放圖像
我們可以使用縮放來(lái)放大或縮小圖像。我們已將圖像縮放到圖像高度 / 寬度的 150%至 80%。我們可以獨(dú)立縮放每個(gè)軸
增強(qiáng)物體檢測(cè)
我們繪制邊界框以進(jìn)行對(duì)象檢測(cè)。當(dāng)我們放大圖像時(shí),我們希望包圍盒也相應(yīng)地更新。
imgaug 支持邊界框。當(dāng)我們旋轉(zhuǎn),剪切或裁剪圖像時(shí),對(duì)象周圍的邊界框也會(huì)相應(yīng)更新。
從 imgaug 導(dǎo)入邊界框
- 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 移動(dòng)圖像,擴(kuò)大邊界框并將其應(yīng)用于圖像上
- 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))
應(yīng)用圖像增強(qiáng)后在圖像外部處理邊界框
邊框有時(shí)可能會(huì)超出圖像,因此我們需要其他代碼來(lái)處理這種情況
我們旋轉(zhuǎn)圖像,并嘗試在對(duì)象周圍繪制邊框
- 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))
邊界框的部分在圖像外部。在下面的代碼中,我們將將邊框完全或部分移出圖像
裁剪部分位于外部的邊界框,使其完全位于圖像內(nèi)部
我們創(chuàng)建一個(gè) padding 函數(shù),以 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
然后,我們?cè)趫D像上繪制邊界框。我們首先將圖像平面擴(kuò)展 BORDER 像素,然后標(biāo)記圖像平面內(nèi)的邊界框
- 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
現(xiàn)在,我們對(duì)圖像應(yīng)用相同的旋轉(zhuǎn)并繪制邊界框
- 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)