通用數據增強方法(Data Augmentation)

通用數據增強方法(Data Augmentation)

1、前言

  機器學習尤其是深度學習中,爲了防止模型過擬合,數據增強也是一種非常有效的方法,好多牛逼的模型除了網絡結構精妙意外,在數據(比較喫數據的有監督深度學習)上也做了不可忽視的工作,纔有state of the art的效果。來看一張圖:

C10和C100是沒有經過數據增強的訓練效果,C10+和C100+則是經過數據增強的效果,提升非常明顯……,這個是分類的錯誤率。在目標檢測領域,好的算法都採用了精妙的數據增強,如YOLOv2&v3、SSD、Faster-RCNN和MASK-RCNN等。

2、數據增強

2.1 隨機裁切(random crop)

   隨機裁切幾乎是所有深度學習框架訓練都具有的數據增強方法,在很多有名的深度學習網絡(VGG,AlexNet,GoogleNet,ResNet……)的訓練中,對輸入256*256的圖像,通常會以224或227的窗口隨機獲得子圖像作爲訓練,而在測試時則是以圖像中心的子塊(Patch)。最終使用則直接將圖像resize到訓練時用的crop size大小。實現也是比較簡單,在紅色區域內隨機取點作爲滑窗左上角頂點。

Python實現:

import numpy.random as npr

def randomCrop(img,size_h,size_w):

    rows,cols=img.shape[:2]

    left_h=npr.randint(0,rows-size_h)

    left_w=npr.randint(0,cols-size_w)

    crop_img=img[left_h:left_h+size_h,left_w:left_w+size_w]

    return crop_img

2.2 翻轉(左右上下)

   左右翻轉也叫做水平翻轉或鏡像(mirror),將圖像的左右部分以圖像垂直中軸線爲中心進行鏡像對換。假設原圖像高度爲h,寬度爲w,原圖像某一像素點P(x0,y0), 經過水平鏡像變換後爲P(w-1-x0,y0),矩陣表示:

Python代碼(左右鏡像):

#水平翻轉
def  horizontalFlip(img):
    size = img.shape  # 獲得圖像的形狀
    iLR = img.copy()  # 獲得一個和原始圖像相同的圖像,注意這裏要使用深度複製
    h = size[0]
    w = size[1]
    for i in range(h):  # 元素循環
        for j in range(w):
            iLR[i, w - 1 - j] = img[i, j]
    return iLR

#垂直翻轉
def verticalFlip(img):
    size = img.shape  # 獲得圖像的形狀
    iLR = img.copy()  # 獲得一個和原始圖像相同的圖像,注意這裏要使用深度複製
    h = size[0]
    w = size[1]
    for i in range(h):  # 元素循環
        for j in range(w):
            iLR[ h- 1 - i,j] = img[i, j]
    return iLR

2.3 顏色抖動(color jitter)

  顏色抖動是指對圖像的曝光度(exposure)、飽和度(saturation)和色調(hue)進行隨機變化形成不同光照及顏色下的圖片,達到數據增強的目的,儘可能使得模型能夠使用不同光照條件小的情形,提高模型泛化能力。

  YOLOv2-v3的目標檢測就用到了這一數據增強方法,YOLO在訓練的每一Batch中對訓練數據進行在線數據增強(包括顏色抖動) ,實現上首先將圖像變換到HSV顏色空間,然後對圖像在HSV顏色空間中隨機的改變圖像的曝光度、飽和度和色調,然後再將變換後的圖像轉到RGB空間。具體實現代碼可以參考YOLO源碼(image.c),

void random_distort_image(image im, float hue, float saturation, float exposure)

{

    float dhue = rand_uniform_strong(-hue, hue);

    float dsat = rand_scale(saturation);

    float dexp = rand_scale(exposure);

    distort_image(im, dhue, dsat, dexp);

}

void distort_image(image im, float hue, float sat, float val)

{

    rgb_to_hsv(im);

    scale_image_channel(im, 1, sat);//改變S通道,該通道的像素值乘上隨機sat值

    scale_image_channel(im, 2, val);//改變V通道,該通道的像素值乘上隨機val值

    int i;

    for(i = 0; i < im.w*im.h; ++i){

        im.data[i] = im.data[i] + hue;//改變H通道,該通道像素值加隨機hue值

        if (im.data[i] > 1) im.data[i] -= 1;

        if (im.data[i] < 0) im.data[i] += 1;

    }

    hsv_to_rgb(im);

    constrain_image(im);

}

對於部分任務也可以借鑑該方法,對樣本進行離線或者在線的數據增強。

2.4 噪聲(高斯噪聲)

一般對圖像加入高斯噪聲可以使得圖像變得模糊,從而模擬模糊情況。Python實現

from skimage import util
def gaussNoise(img):

    noise_img=util.random_noise(img,mode='gaussian')

    result=util.img_as_ubyte(noise_img)

    return result

2.5 旋轉

圖像旋轉一般是以圖像中心爲旋轉中心進行隨機旋轉(一般有一個正負角度約束),而。Python實現

from skimage.transform import rotate
def img_rotate(img,angle):

    return rotate(img,angle)
rotate_limit=(-30, 30)

theta = np.pi / 180 * np.random.uniform(rotate_limit[0], rotate_limit[1]) #逆

img_rot = img_rotate(img, theta)
#opencv實現
def cv_rotate(img,center,angle,scale):

    rows,cols=img.shape[:2]

    M = cv2.getRotationMatrix2D(center, angle, scale)

    dst = cv2.warpAffine(img, M, (cols, rows))

    return dst

2.6 平移

   1)圖像沿着X軸或Y軸的平移有以下四種情況:

def move_right(img,dis):

    size = img.shape  # 獲得圖像的形狀

    iLR = img.copy()  # 獲得一個和原始圖像相同的圖像,注意這裏要使用深度複製

    h = size[0]

    w = size[1]

    for i in range(h):

        for j in range(w):

            if j-dis>0:

                iLR[i,j]=img[i,j-dis]

            else:

                iLR[i, j] =0

    return iLR



def move_left(img,dis):

    size = img.shape  # 獲得圖像的形狀

    iLR = img.copy()  # 獲得一個和原始圖像相同的圖像,注意這裏要使用深度複製

    h = size[0]

    w = size[1]

    for i in range(h):

        for j in range(w):

            if j+dis<w-1:

                iLR[i,j]=img[i,j+dis]

            else:

                iLR[i, j] =0

    return iLR



def move_up(img,dis):

    size = img.shape  # 獲得圖像的形狀

    iLR = img.copy()  # 獲得一個和原始圖像相同的圖像,注意這裏要使用深度複製

    h = size[0]

    w = size[1]

    for i in range(h):

        for j in range(w):

            if i+dis<h-1:

                iLR[i,j]=img[i+dis,j]

            else:

                iLR[i, j] =0

    return iLR



def move_down(img,dis):

    size = img.shape  # 獲得圖像的形狀

    iLR = img.copy()  # 獲得一個和原始圖像相同的圖像,注意這裏要使用深度複製

    h = size[0]

    w = size[1]

    for i in range(h):

        for j in range(w):

            if i-dis>0:

                iLR[i,j]=img[i-dis,j]

            else:

                iLR[i, j] =0

    return iLR

2)圖像沿着任意向量平移

參考:https://blog.csdn.net/sty945/article/details/79387054

def translate(image, x, y): #3

    M = np.float32([[1, 0, x], [0, 1, y]]) #4  //X軸移動x, Y中移動y

    shifted = cv2.warpAffine(image, M, (image.shape[1], image.shape[0])) #5

    return shifted #6

2.7 縮放

   全卷積網絡對於尺度沒有嚴格要求,如目標檢測算法yolov2-v3在訓練過程中會對樣本進行隨機尺度變換(每隔10步變換一次),實現多尺度訓練,進而跨尺度特徵融合。同時也使得模型對於不同尺度的圖像有更強的適應性。

from skimage.transform import rescale
def image_resize(img,scale):

    result=rescale(img,scale)

    return result

2.8 PCA jitter

PCA jitter是實際上對RGB顏色空間添加擾動,從而達到對RGB顏色添加噪聲的目的,具體爲對RGB空間做PCA,然後對主成分做一個(0, 0.1)的高斯擾動。最早使用是在2012年的AlexNet,從論文實驗中可以看出,PCA jitter對於分類的性能提升比較顯著。

def PCA_Jittering (img):

    img = np.asanyarray(img, dtype='float32')

    img = img / 255.0

    img_size = img.size // 3  # 轉換爲單通道

    img1 = img.reshape(img_size, 3)

    img1 = np.transpose(img1)  # 轉置

    img_cov = np.cov([img1[0], img1[1], img1[2]])  # 協方差矩陣

    lamda, p = np.linalg.eig(img_cov)  # 得到上述協方差矩陣的特徵向量和特徵值


    # p是協方差矩陣的特徵向量

    p = np.transpose(p)  # 轉置回去



    # 生成高斯隨機數********可以修改

    alpha1 = random.gauss(0, 1)

    alpha2 = random.gauss(0, 1)

    alpha3 = random.gauss(0, 1)


    # lamda是協方差矩陣的特徵值

    v = np.transpose((alpha1 * lamda[0], alpha2 * lamda[1], alpha3 * lamda[2]))  # 轉置


    # 得到主成分

    add_num = np.dot(p, v)


    # 在原圖像的基礎上加上主成分

    img2 = np.array([img[:, :, 0] + add_num[0], img[:, :, 1] + add_num[1], img[:, :, 2] + add_num[2]])


    # 現在是BGR,要轉成RBG再進行保存

    img2 = np.swapaxes(img2, 0, 2)

    img2 = np.swapaxes(img2, 0, 1)

    return img2

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章