資料增廣之詳細理解
資料增廣之詳細理解
燕小花 只有腳踏實地的人,才能夠說:路,就在我的腳下引言
資料增廣是深度學習中常用的技巧之一,主要用於增加訓練資料集,讓資料集儘可能的多樣化,使得訓練的模型具有更強的泛化能力.現有的各大深度學習框架都已經自帶了資料增廣,但是平時在用的使用只是直接呼叫了對應的介面函式,而沒有進行詳細的分析.在實際應用中,並非所有的增廣方式都適用當前的訓練資料,你需要根據自己的資料集特徵來確定應該使用哪幾種資料增廣方式.這篇文章的目的是為了更好地理解各種增廣方式及其背後的真正原理.
目前資料增廣主要包括:水平/垂直翻轉,旋轉,縮放,裁剪,剪下,平移,對比度,色彩抖動,噪聲等,這裡因為時間問題,有部分還每有完成,後續會進行更新.
資料增廣
所有的資料增廣在操作的時候預設是以影象中心點進行的.從數學角度來看,任何操作都可以分成以下幾個步驟:1). 首先將旋轉點移動到原點處 ;2). 執行如2所描述的繞原點的旋轉;3). 再將旋轉點移回到原來的位置;這裡為了更好地理解,給出一個示例:
假設影象的原始座標為,平移後的座標為,則平移前和平移後的座標關係為:
影象平移
平移是指所有的畫素在x和y方向各平移和,平移變換對應的數學矩陣為
這裡給出平移後的具體例項(這裡平移後我採用的是倒映填充):
影象翻轉(影象映象)
影象翻轉包括水平翻轉和垂直翻轉.水平翻轉的變換矩陣為:
垂直翻轉的變換矩陣為:
這裡給出翻轉後的具體例項(這裡平移後我採用的是倒映填充):
影象旋轉
影象旋轉是指以某個點(預設為影象中心點)為中心進行任意角度的旋轉,其變換矩陣為:
這裡給出旋轉後的具體例項(這裡平移後我採用的是倒映填充):
影象縮放
影象縮放是指對當前影象進行任意尺度的縮放,其變換矩陣為:
這裡給出縮放後的具體例項(這裡平移後我採用的是倒映填充):
影象錯切
影象,其變換矩陣為:
這裡給出錯切後的具體例項(這裡平移後我採用的是倒映填充):
影象裁剪
深度學習的裁剪的常用做法是將圖片縮放到原圖的1.1倍,然後在縮放後的影象上進行裁剪操作,具體的裁剪例項如下:
組合變換
在深度學習中的資料增廣一般會採用多種增廣方式的組合,這裡就會涉及到矩陣乘法運算,根據其運算的規則,可以知道不同的組合順序結果是不一樣的,即線性代數中的,當然特例除外.
為了更好地解釋,假設給定平移變換矩陣,旋轉矩陣,縮放矩陣,為了說明這裡我給出兩個不同的組合變換.對於組合變換一,其組合後的矩陣如下:;對於組合變換二,其組合後的矩陣如下:,對於兩種不同的組合其結果如下:
資料增廣之原始碼實現
這裡使用python和opencv來實現上述中的各種變換,具體的原始碼如下:
#coding=utf-8
################################################
# 資料增廣,包括
# 2018.09.02 add
################################################
import numpy as np
import os
import cv2
import copy
class DataAugment:
def __init__(self,debug=False):
self.debug=debug
print("Data augment...")
def basic_matrix(self,translation):
"""基礎變換矩陣"""
return np.array([[1,0,translation[0]],[0,1,translation[1]],[0,0,1]])
def adjust_transform_for_image(self,img,trans_matrix):
"""根據影象調整當前變換矩陣"""
transform_matrix=copy.deepcopy(trans_matrix)
height, width, channels = img.shape
transform_matrix[0:2, 2] *= [width, height]
center = np.array((0.5 * width, 0.5 * height))
transform_matrix = np.linalg.multi_dot([self.basic_matrix(center), transform_matrix, self.basic_matrix(-center)])
return transform_matrix
def apply_transform(self,img,transform):
"""仿射變換"""
output = cv2.warpAffine(img, transform[:2, :], dsize=(img.shape[1], img.shape[0]),
flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_REFLECT, borderValue=0,) #cv2.BORDER_REPLICATE,cv2.BORDER_TRANSPARENT
return output
def apply(self,img,trans_matrix):
"""應用變換"""
tmp_matrix=self.adjust_transform_for_image(img, trans_matrix)
out_img=self.apply_transform(img, tmp_matrix)
if self.debug:
self.