數據增廣imgaug庫的使用


記錄一下這兩天用imgaug庫做數據增廣的代碼,由於是算用算學的,所以只能把代碼寫出來,具體每種增廣算法的原理和一些參數就不得而知了,不過我覺得也沒必要把這么些個算法搜搞懂,畢竟重點是擴種數據。所以,如果你想深入的學習imgaug這個庫的話那么這篇文章不適合你。不過這里有官方文檔傳送門,還有一篇非常詳細的博文,同時本文就是參考以上博文才寫出的代碼。而本文主要是一個數據增廣的實際案例,代碼完整,可供參考。

查看每種增廣操作的效果

由於本人在進行寫代碼的時候想看看每種操作作用完之后的效果,所以就想着寫了一段代碼,直接將增廣操作復制到指定位置后運行就可直接輸出作用前后的效果對比圖。代碼如下:

'''
該程序用於查看imgaug中的增廣算法的作用效果
1. 修改代碼第四行的 op 后的增廣算法
2. 修改操作的圖片的路徑
3. 通過顯示的圖像課觀察到增廣效果
4. 該效果是經過op 和 op_ 兩種操作疊加而成的圖片
5. op_ 操作為剪切和填充
6. 如果想單獨看 op 效果可以將代碼12行[op, op_]中的op_去掉
'''

from imgaug import augmenters as iaa
import imgaug as ia

op = iaa.CoarseDropout(0.02, size_percent=0.15, per_channel=0.5) # 可修改成別的增廣算法

op_ = iaa.CropAndPad(
    percent=(0, 0.2),
    pad_mode=["constant", "edge"], 
    pad_cval=(0, 255)
)

seq = iaa.Sequential([ op , op_])
imgList = [cv2.imread("NewNewImage/22.jpg"),cv2.imread("NewNewImage/52.jpg")] # 修改成圖片路徑
img_aug = seq.augment_images(imgList)
import matplotlib.pyplot as plt
import cv2
plt.figure(figsize=(8,8))
plt.subplot(2,2,1)
plt.imshow(cv2.cvtColor(imgList[0],cv2.COLOR_BGR2RGB))
plt.subplot(2,2,2)
plt.imshow(cv2.cvtColor(img_aug[0],cv2.COLOR_BGR2RGB))
plt.subplot(2,2,3)
plt.imshow(cv2.cvtColor(imgList[1],cv2.COLOR_BGR2RGB))
plt.subplot(2,2,4)
plt.imshow(cv2.cvtColor(img_aug[1],cv2.COLOR_BGR2RGB))
plt.show()

實例代碼

定義多種增廣操作

from imgaug import augmenters as iaa
import imgaug as ia

# 將圖像轉換為HSV,然后將每個像素的H值增加10到50
op_1 = iaa.WithColorspace(
    to_colorspace="HSV",
    from_colorspace="RGB",
    children=iaa.WithChannels(0, iaa.Add((10, 50)))
)

op_2 = iaa.WithChannels(0, iaa.Add((10,50))) # BGR中的B值隨機增加10-50,因為cv2讀取的圖片為BGR順序,下同
op_3 = iaa.WithChannels(1, iaa.Add((10,50))) # BGR中的G值隨機增加10-50
op_4 = iaa.WithChannels(2, iaa.Add((10,50))) # BGR中的R值隨機增加10-50

op_5 = iaa.WithChannels(0, iaa.Affine((10, 180))) # BGR中的B值隨機旋轉10-180°
op_6 = iaa.WithChannels(1, iaa.Affine((10, 180))) # BGR中的G值隨機旋轉10-180°
op_7 = iaa.WithChannels(2, iaa.Affine((10, 180))) # BGR中的R值隨機旋轉10-180°

op_8 = iaa.Noop() # 無操作增廣

# 用黑色像素替換每個圖像的每5行 
def img_func(images, random_state, parents, hooks):
    for img in images:
        img[::5] = 0
    return images
def keypoint_func(keypoints_on_images, random_state, parents, hooks):
    return keypoints_on_images
op_9 = iaa.Lambda(img_func, keypoint_func)

# 裁剪並填充 負則裁剪,正則填充
op_10 = iaa.CropAndPad(percent=(-0.2, 0.2))

op_11 = iaa.CropAndPad(
    percent=(0, 0.2), # 每邊填充0至20%
    pad_mode=["constant", "edge"], # 填充方式為恆定值(constant)或邊緣值(edge)
    pad_cval=(0, 255) # 若為恆定值,則從0-255中隨機取值
)

op_12 = iaa.CropAndPad(
    px=((0, 30), (0, 10), (0, 30), (0, 10)), # 頂部填充0-30px,右側0-10px,底部0-30px,左側0-10px
    pad_mode=ia.ALL,
    pad_cval=(0, 255)
)

op_13 = iaa.Fliplr() # 水平翻轉所有圖片
op_14 = iaa.Flipud() # 垂直反轉所有圖片

# 每個圖像生成16到128個超像素。 用平均像素顏色替換每個超像素的概率在10到50%之間(每個圖像采樣一次)
op_15 = iaa.Superpixels(p_replace=(0.1, 0.5), n_segments=(16, 128))

# 將圖像更改為灰度,並通過改變強度將其與原始圖像疊加,有效地刪除0到80%的顏色
op_16 = iaa.Grayscale(alpha=(0.0, 0.8))

op_17 = iaa.GaussianBlur(sigma=(0.0, 2.0)) # 高斯模糊,σ=0-2

# 在圖像中添加-50到50之間的隨機值。 
#在50%的圖像中,每個通道的值不同(3個采樣值)。 
#在剩下的50%圖像中,所有通道的值都相同
op_18 = iaa.Add((-50, 50),per_channel=0.5) 

# 添加高斯噪音 
# 每個像素從正態分布N(0,s)采樣一次,s對每個圖像采樣並在0和0.1 * 255之間變化
op_19 = iaa.AdditiveGaussianNoise(scale=(0, 0.1*255))

# 丟棄2%的圖像,但是在具有原始大小的50%的圖像的較低分辨率版本上執行此操作,丟棄2x2個正方形。 
# 此外,在50%的圖像通道中執行此操作,以便僅將某些通道的信息設置為0,而其他通道保持不變
op_20 = iaa.CoarseDropout(0.02, size_percent=0.15, per_channel=0.5)

operation_list = [op_1, op_7, op_8, op_9, op_10,
                  op_11, op_12, op_13, op_14, op_16, op_17, op_18, op_19, op_20,]

將圖片分批

new_image_text.txt這個文本文件是圖像列表,其中每一行保存的是一個圖片的路徑和對應的類別。

例如NewImage/10.jpg 7表示該圖片的路徑為NewImage/10.jpg,其類別屬於7

## 將數據分批,每批含有batch_size個圖像
with open("new_image_text.txt") as img_info:
    batch_size = 10 # 每個batch的大小
    img_batchs = []
    img_label_batchs = []
    flag = 0
    while True:
        if flag % batch_size == 0:
            img_batchs.append([])
            img_label_batchs.append([])
        img = img_info.readline()
        if(img == ""):
            break
        img = img.split(" ")
        img_batchs[-1].append(img[0]) 
        img_label_batchs[-1].append(int(img[1]))
        flag += 1
        if flag >=10000: # 避免進入死循環而必須重啟項目
            break
    if img_batchs[-1] == []:
        img_batchs.pop()
        img_label_batchs.pop()

數據增廣

先了解一下Sequential()SomeOf()兩種方法之間的區別 ;

iaa.Sequential(children=None,
               random_order=False,
               name=None,
               deterministic=False,
               random_state=None)
  • children: 想要應用在圖像上的Augmenter或者Augmenter集合。默認None
  • random_order: bool類型, 默認False。是否對每個batch的圖片應用不同順序的Augmenter list。當設置為True時,不同batch之間圖片的處理順序都會不一樣,但是同一個batch內順序相同。
  • deterministic: bool類型, 默認False。
iaa.SomeOf(n=None,
           children=None,
           random_order=False,
           name=None,
           deterministic=False,
           random_state=None)
  • n: 從總的Augmenters中選擇多少個。可以是一個int, tuple, list或者隨機值。
  • random_order: 是否每次順序不一樣。
# 數據增廣,每張圖片擴充30張
img_name = 1000 # 每張圖片的名字,依次遞增
with open("new_image_text.txt","a") as img_text:
    for epoch in range(20): # 原始圖片循環增廣20次
        for someof_n in [1, 1, 2, 2]: # 對應於SomeOf中的參數someof_n
            seq = iaa.SomeOf(someof_n, operation_list) # 使用的是SomeOf,區別於Sequential
            for batch_ind, img_batch in enumerate(img_batchs):
                img_batch = [cv2.imread(path) for path in img_batch]
                imgs_aug = seq.augment_images(img_batch)
                for i, save_img in enumerate(imgs_aug):
                    save_img_path = f"NewImage/{str(img_name)}.jpg" # 保存路徑
                    save_img_label = img_label_batchs[batch_ind][i]
                    cv2.imwrite(save_img_path, save_img) # 保存圖片
                    img_text.write(save_img_path+" "+str(save_img_label)+"\n") # 保存圖像列表
                    img_name += 1

看看效果

參考

  1. imgaug學習筆記
  2. imgaug數據增強神器:增強器一覽


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM