6.3.3 隨機顏色和明暗
作為Gamma值進(jìn)行變換。
6.3.4 多進(jìn)程調(diào)用加速處理
做數(shù)據(jù)增加時如果樣本量本身就不小,則處理起來可能會很耗費時間,所以可以考慮利用多進(jìn)程并行處理。比如我們的例子中,設(shè)定使用場景是輸入一個文件夾路徑,該文件夾下包含了所有原始的數(shù)據(jù)樣本。用戶指定輸出的文件夾和打算增加圖片的總量。執(zhí)行程序的時候,通過os.listdir()獲取所有文件的路徑,然后按照上一章講過的多進(jìn)程平均劃分樣本的辦法,把文件盡可能均勻地分給不同進(jìn)程,進(jìn)行處理。
6.3.5 代碼:圖片數(shù)據(jù)增加小工具
按照前面4個部分的思路和方法,這節(jié)來實現(xiàn)這么一個圖片數(shù)據(jù)增加小工具,首先對于一些基礎(chǔ)的操作,我們定義在一個叫做image_augmentation.py的文件里:
import numpy as np
import cv2
'''
定義裁剪函數(shù),四個參數(shù)分別是:
左上角橫坐標(biāo)x0
左上角縱坐標(biāo)y0
裁剪寬度w
裁剪高度h
'''
crop_image = lambda img, x0, y0, w, h: img[y0:y0+h, x0:x0+w]
'''
隨機裁剪
area_ratio為裁剪畫面占原畫面的比例
hw_vari是擾動占原高寬比的比例范圍
'''
def random_crop(img, area_ratio, hw_vari):
h, w = img.shape[:2]
hw_delta = np.random.uniform(-hw_vari, hw_vari)
hw_mult = 1 + hw_delta
# 下標(biāo)進(jìn)行裁剪,寬高必須是正整數(shù)
w_crop = int(round(w*np.sqrt(area_ratio*hw_mult)))
# 裁剪寬度不可超過原圖可裁剪寬度
if w_crop > w:
w_crop = w
h_crop = int(round(h*np.sqrt(area_ratio/hw_mult)))
if h_crop > h:
h_crop = h
# 隨機生成左上角的位置
x0 = np.random.randint(0, w-w_crop+1)
y0 = np.random.randint(0, h-h_crop+1)
return crop_image(img, x0, y0, w_crop, h_crop)
'''
定義旋轉(zhuǎn)函數(shù):
angle是逆時針旋轉(zhuǎn)的角度
crop是個布爾值,表明是否要裁剪去除黑邊
'''
def rotate_image(img, angle, crop):
h, w = img.shape[:2]
# 旋轉(zhuǎn)角度的周期是360°
angle %= 360
# 用OpenCV內(nèi)置函數(shù)計算仿射矩陣
M_rotate = cv2.getRotationMatrix2D((w/2, h/2), angle, 1)
# 得到旋轉(zhuǎn)后的圖像
img_rotated = cv2.warpAffine(img, M_rotate, (w, h))
# 如果需要裁剪去除黑邊
if crop:
# 對于裁剪角度的等效周期是180°
angle_crop = angle % 180
# 并且關(guān)于90°對稱
if angle_crop > 90:
angle_crop = 180 - angle_crop
# 轉(zhuǎn)化角度為弧度
theta = angle_crop * np.pi / 180.0
# 計算高寬比
hw_ratio = float(h) / float(w)
# 計算裁剪邊長系數(shù)的分子項
tan_theta = np.tan(theta)
numerator = np.cos(theta) + np.sin(theta) * tan_theta
# 計算分母項中和寬高比相關(guān)的項
r = hw_ratio if h > w else 1 / hw_ratio
# 計算分母項
denominator = r * tan_theta + 1
# 計算最終的邊長系數(shù)
crop_mult = numerator / denominator
# 得到裁剪區(qū)域
w_crop = int(round(crop_mult*w))
h_crop = int(round(crop_mult*h))
x0 = int((w-w_crop)/2)
y0 = int((h-h_crop)/2)
img_rotated = crop_image(img_rotated, x0, y0, w_crop, h_crop)
return img_rotated
'''
隨機旋轉(zhuǎn)
angle_vari是旋轉(zhuǎn)角度的范圍[-angle_vari, angle_vari)
p_crop是要進(jìn)行去黑邊裁剪的比例
'''
def random_rotate(img, angle_vari, p_crop):
angle = np.random.uniform(-angle_vari, angle_vari)
crop = False if np.random.random() > p_crop else True
return rotate_image(img, angle, crop)
'''
定義hsv變換函數(shù):
hue_delta是色調(diào)變化比例
sat_delta是飽和度變化比例
val_delta是明度變化比例
'''
def hsv_transform(img, hue_delta, sat_mult, val_mult):
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV).astype(np.float)
img_hsv[:, :, 0] = (img_hsv[:, :, 0] + hue_delta) % 180
img_hsv[:, :, 1] *= sat_mult
img_hsv[:, :, 2] *= val_mult
img_hsv[img_hsv > 255] = 255
return cv2.cvtColor(np.round(img_hsv).astype(np.uint8), cv2.COLOR_HSV2BGR)
'''
隨機hsv變換
hue_vari是色調(diào)變化比例的范圍
sat_vari是飽和度變化比例的范圍
val_vari是明度變化比例的范圍
'''
def random_hsv_transform(img, hue_vari, sat_vari, val_vari):
hue_delta = np.random.randint(-hue_vari, hue_vari)
sat_mult = 1 + np.random.uniform(-sat_vari, sat_vari)
val_mult = 1 + np.random.uniform(-val_vari, val_vari)
return hsv_transform(img, hue_delta, sat_mult, val_mult)
'''
定義gamma變換函數(shù):
gamma就是Gamma
'''
def gamma_transform(img, gamma):
gamma_table = [np.power(x / 255.0, gamma) * 255.0 for x in range(256)]
gamma_table = np.round(np.array(gamma_table)).astype(np.uint8)
return cv2.LUT(img, gamma_table)
'''
隨機gamma變換
gamma_vari是Gamma變化的范圍[1/gamma_vari, gamma_vari)
'''
def random_gamma_transform(img, gamma_vari):
log_gamma_vari = np.log(gamma_vari)
alpha = np.random.uniform(-log_gamma_vari, log_gamma_vari)
gamma = np.exp(alpha)
return gamma_transform(img, gamma)
評論
查看更多