在進行模型訓練的時候會遇到數據量小的問題。針對一些小數據集可以進行離線數據增強,一定程度上能防止模型過擬合。
下面是一些使用opencv庫進行圖片數據增強的方法。
具體函數使用方法,調參啥的可以自查opencv函數手冊,也可以百度具體方法。
https://docs.opencv.org/
1、翻轉
# 翻轉
def flip(pic):
img = []
h_pic = cv2.flip(pic, 1) # 水平翻轉
v_pic = cv2.flip(pic, 0) # 垂直翻轉
hv_pic = cv2.flip(pic, -1) # 水平垂直翻轉
img.append(h_pic)
img.append(v_pic)
img.append(hv_pic)
return img
2、旋轉
# 旋轉
def rotate(pic):
scale = 1.0
rows, cols = pic.shape[:2]
img = []
angle = [45, 90, 135, 180, 225, 275, 320]
center = (cols / 2, rows / 2) # 取圖像的中點
for a in angle:
M = cv2.getRotationMatrix2D(center, a, scale) # 獲得圖像繞着某一點的旋轉矩陣
pic = cv2.warpAffine(pic, M, (cols, rows), borderValue=(255, 255, 255))# cv2.warpAffine()的第二個參數是變換矩陣,第三個參數是輸出圖像的大小
img.append(pic)
return img
3、加噪聲
# 噪聲
def noise(pic):
for i in range(1500):
pic[random.randint(0, pic.shape[0] - 1)][random.randint(0, pic.shape[1] - 1)][:] = 255
return pic
# random.randint(a, b)
# 用於生成一個指定範圍內的整數。其中參數a是下限,參數b是上限,生成的隨機數n: a <= n <= b
4、模糊
# 高斯模糊
def gussian(pic):
img = []
temp = cv2.GaussianBlur(pic, (9, 9), 1.5) #高斯模糊
dst = cv2.blur(pic, (11, 11), (-1, -1)) #均值濾波
# cv2.GaussianBlur(圖像,卷積核,標準差)
img.append(temp)
img.append(dst)
return img
5、光照
# 光照
def light(pic):
img = []
contrast = 1 #對比度
brightness = 100 #亮度
pic_turn1 = cv2.addWeighted(pic,contrast,pic,0,brightness)
pic_turn2 = cv2.addWeighted(pic, 1.5, pic, 0, 50)
img.append(pic_turn1)
img.append(pic_turn2)
# cv2.addWeighted(對象,對比度,對象,對比度)
#cv2.addWeighted()實現的是圖像透明度的改變與圖像的疊加
return img
6、仿射
# 仿射
def fangshe(pic):
rows, cols = pic.shape[:2]
point1 = np.float32([[50, 50], [300, 50], [50, 200]])
point2 = np.float32([[10, 100], [300, 50], [100, 250]])
M = cv2.getAffineTransform(point1, point2)
dst = cv2.warpAffine(pic, M, (cols, rows), borderValue=(255, 255, 255))
# 對圖像進行變換(三點得到一個變換矩陣)
# 我們知道三點確定一個平面,我們也可以通過確定三個點的關係來得到轉換矩陣
# 然後再通過warpAffine來進行變換
return dst
批量增強
遍歷文件下面的圖片,每張都增強一遍。需要注意的是,我採用的方法將每張圖片都使用了一樣的增強方法。如果對文件下圖片進行隨機賦予不同的增強方式,模型訓練效果會更好,比如imgaug這個庫就能實現。後續我會更新數據增強2.0版本。不過具體還是要結合自己的數據集,有些使用imgaug效果不一定會好,可能它變太多,加入的噪聲太多了。
if __name__ == '__main__':
print('讀取圖像開始')
cate=['D:/me/animal/test/186/']
img_all = []
for idx, folder in enumerate(cate):
folder1 = folder.split('/')
id = folder1[4]
print(id, folder)
p = path_re + id + '/' #保存路徑
for im in glob.glob(folder + '/*.jpg'): #遍歷文件夾下的圖片
try:
img = cv2.imread(im)
#img = cv2.resize(img,(224,224)) 裁剪
noi = noise(img) # 噪聲
fli = flip(img) # 翻轉
rot = rotate(img) # 旋轉
guss = gussian(img) # 模糊
li = light(img) # 光線
fan = fangshe(img) # 仿射
img_all.append(img)
img_all.append(fan)
img_all = img_all + rot + fli +li + guss
img_all.append(noi)
im = im.split('\\')
im = im[1].split('.')[0]
for k, imge in zip(range(len(img_all)), img_all):
imge = cv2.resize(imge,(224,224))
cv2.imwrite(p + im + str(k) + '_.jpg', imge) #保存圖片
except:
print(im)
img_all = []
結果示例:
需要數據增強的文件:
增強之後:
根據上面貼的代碼,我在每種方法上都會通過調整多變幾張。
本篇鏈接:
https://blog.csdn.net/weixin_42385606/article/details/105956416