深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

今天就來一招搞定數據增強(data_Augmentation),讓你在機器學習/深度學習圖像處理的路上,從此不再為數據不夠而發愁。且來看圖片從

250張>>>>任意張的華麗增強,每一張都與眾不同。

開始之前呢,我們先把這件大事給細分下,一步一步的來:

首先,圖像讀取,需要對文件夾操作;

然後,增強圖像(重點,重點,重點);

最後,保存圖像。

來看下此次任務中,待增強的圖像和標籤,主要是為了做圖像分割做圖像準備。這個圖像懂的應該能看出來,這是一個嬰兒頭圍的醫學圖像,現實場景意義很強。上圖(以3張圖為例):

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

train_img

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

train_label

成雙成對,這樣在後續的文件讀取中會比較的方便(大神可以自己改改,練練動手能力)

那動手吧!!!

一.大殺氣之keras ImageDataGenerator

<code>from keras.preprocessing.image import ImageDataGenerator/<code>

ImageDataGenerator()是keras.preprocessing.image模塊中的圖片生成器,同時也可以在batch中對數據進行增強,擴充數據集大小,增強模型的泛化能力。比如進行旋轉,變形,歸一化等,它所能實現的功能且看下面的詳細部分吧。

<code>keras.preprocessing.image.ImageDataGenerator(               featurewise_center=False,                 samplewise_center=False,                featurewise_std_normalization=False,                samplewise_std_normalization=False,                zca_whitening=False,                zca_epsilon=1e-06,                rotation_range=0, #整數。隨機旋轉的度數範圍。               width_shift_range=0.0, #浮點數、一維數組或整數               height_shift_range=0.0, #浮點數。剪切強度(以弧度逆時針方向剪切角度)。               brightness_range=None,                shear_range=0.0,                zoom_range=0.0, #浮點數 或 [lower, upper]。隨機縮放範圍               channel_shift_range=0.0, #浮點數。隨機通道轉換的範圍。               fill_mode=nearest, # {"constant", "nearest", "reflect" or "wrap"} 之一。默認為 nearest。輸入邊界以外的點根據給定的模式填充:               cval=0.0,                horizontal_flip=False,                vertical_flip=False,                rescale=None,                preprocessing_function=None,                data_format=None,                validation_split=0.0,                dtype=None)/<code>

這裡就以單張圖片為例,詳述下這個圖像增強大殺器的具體用法,分別以旋轉(rotation_range),長寬上平移(width_shift_range,height_shift_range)

輸入圖像:

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

train_img

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

train_label

先來看下兩者合併後的圖像:

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

merge

到這裡,我們進行增強變換,演示下這裡增強部分是咋用的,且看:

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

(溫馨提示)
滑慢點,有GIF圖

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

(1)旋轉(rotation_range=1.2)

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

otation=1.2

(2)寬度變換(width_shift_range=0.05)

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

width_shift_range=0.05

(3)高度變換(height_shift_range=0.05)

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

eight_shift_range=0.05

這裡才只是演示了三個就那麼的強大,詳細,這要能增強多少圖片啊,想想都可怕,想都不敢想啊!!!

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

增強彙總

這裡是合併部分,單幅增強的大圖效果詳情看這裡:

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

merge改變通道排布方式

這裡,且看單幅圖像的增強代碼(建議去下載仔細看,往後看,有方式):

<code>import osfrom keras.preprocessing.image import ImageDataGenerator,load_img,img_to_array,array_to_imgclass Augmentation(object):    def __init__(self,img_type="png"):        self.datagen=ImageDataGenerator(            #rotation_range=1.2,            #width_shift_range=0.05,            height_shift_range=0.05,            # shear_range=0.05,            # zoom_range=0.05,            # horizontal_flip=True,            fill_mode=nearest)    def augmentation(self):        # 讀入3通道的train和label, 分別轉換成矩陣, 然後將label的第一個通道放在train的第2個通處, 做數據增強        print("運行 Augmentation")        # Start augmentation.....        img_t = load_img("../one/img/0.png")  # 讀入train        img_l = load_img("../one/label/0.png")  # 讀入label        x_t = img_to_array(img_t)  # 轉換成矩陣        x_l = img_to_array(img_l)        x_t[:, :, 2] = x_l[:, :, 0]  # 把label當做train的第三個通道        #x_t = x_t[..., [2,0,1]]#image-102,120,210        img_tmp = array_to_img(x_t)        img_tmp.save("../one/merge/0.png")  # 保存合併後的圖像        img = x_t        img = img.reshape((1,) + img.shape)  # 改變shape(1, 512, 512, 3)        savedir = "../one/aug_merge"  # 存儲合併增強後的圖像        if not os.path.lexists(savedir):            os.mkdir(savedir)        print("running %d doAugmenttaion" % 0)        self.do_augmentate(img, savedir, str(0))  # 數據增強    def do_augmentate(self, img, save_to_dir, save_prefix, batch_size=1, save_format=png, imgnum=30):        # augmentate one image        datagen = self.datagen        i = 0        for _ in datagen.flow(                img,                batch_size=batch_size,                save_to_dir=save_to_dir,                save_prefix=save_prefix,                save_format=save_format):            i += 1            if i > imgnum:                breakif __name__=="__main__":    aug=Augmentation()    aug.augmentation()/<code> 

這裡不做過多的解釋,打個廣告,歡迎關注:錢多多先森。對代碼中的詳細內容,我們且看第二部分

二.詳解單幅圖像增強

這裡先說下對圖像和標籤一起增強的步驟,有人該問為什麼還要標籤了。這裡針對的問題是圖像分割,pix2pix的任務,即輸入時一般圖像,輸出是目標分割後圖像,在上面就是train_img和train_label的一一對應關係,這裡開始分解步驟來說增強:

1.train_img+train_label=merge,也就是圖像+橢圓形的那個;2.對merge圖像進行增強;3.將merge圖像按通道拆分,1的逆過程。

前面只涉及步驟1和2,故先對這兩塊做詳述,如下:著重講下Augmentation類中augmentation函數部分和對單幅圖像增強部分。

1.讀取train_img,train_label;

<code> # load_imageimg_t = load_img("../one/img/0.png")img_l = load_img("../one/label/0.png")/<code>

2.因為要講上述img_t和img_l進行合併,採用矩陣形式進行操作,這裡將讀取到的圖像轉換為矩陣形式;

<code> # img_to_arrayx_t = img_to_array(img_t)         x_l = img_to_array(img_l)/<code>

3.train_img+train_label=merge.把label當做train的第三個通道

後面註釋部分,是對合並後的通道進行任意組合的形式,會出現不同的效果,如前文中三個特寫圖(具體自己可嘗試)

<code># 把label當做train的第三個通道x_t[:, :, 2] = x_l[:, :, 0]  #x_t = x_t[..., [2,0,1]]#image-102,120,210/<code>

4.為了保存merge後圖像,此時該從array_to_image了,然後保存圖像文件;

<code>img_tmp = array_to_img(x_t)img_tmp.save("../one/merge/0.png")  # 保存合併後的圖像/<code>

5.此時執行對merge圖像的增強操作;

開始前,既然我們要def do_augmentate(),我們先想想對一幅圖像的增強,需要些什麼:

image圖像文件;

save_to_dir保存增強後的文件夾地址;

批增強的數量。

至於別的,先看這裡

<code>flow(self, X, y, batch_size=32, shuffle=True, seed=None, save_to_dir=None, save_prefix=, save_format=png)x:樣本數據,秩應為4,在黑白圖像的情況下channel軸的值為1,在彩色圖像情況下值為3y:標籤batch_size:整數,默認32shuffle:布爾值,是否隨機打亂數據,默認為Truesave_to_dir:None或字符串,該參數能讓你將提升後的圖片保存起來,用以可視化save_prefix:字符串,保存提升後圖片時使用的前綴, 僅當設置了save_to_dir時生效save_format:"png"或"jpeg"之一,指定保存圖片的數據格式,默認"jpeg"yields:形如(x,y)的tuple,x是代表圖像數據的numpy數組.y是代表標籤的numpy數組.該迭代器無限循環.seed: 整數,隨機數種子/<code> 

flow:接收numpy數組和標籤為參數,生成經過數據提升或標準化後的batch數據,並在一個無限循環中不斷的返回batch數據

6.由於flow的輸入X需要一個秩為4的數組,所以需要對他變形,加上img.shape=3

<code># 改變shape(1, 512, 512, 3)img = img.reshape((1,) + img.shape)  /<code>

好了,這裡應該是對代碼部分描述的已經夠清楚了(哪裡還有不理解的,歡迎留言評論,大家一起進步哦)

三.最後的拆分分別保存train_img和train_label

話不多說,先看下拆分代碼部分,還是先說步驟:

1.讀取merge文件夾內圖片;2.按照之前組合的形式進行拆分為img_train和img_label,同時保存在兩個文件夾內,一一對應。

<code>    def split_merge(self):        # 讀入合併增強之後的數據(aug_merge), 對其進行分離, 分別保存至 aug_merge_img, aug_merge_label        print("running split_Merge_image")        # split merged image apart        path_merge = "../one/aug_merge"  # 合併增強之後的圖像        path_train = "../one/aug_merge_img"  # 增強之後分離出來的train        path_label = "../one/aug_merge_label"  # 增強之後分離出來的label        if not os.path.lexists(path_train):            os.mkdir(path_train)        if not os.path.lexists(path_label):            os.mkdir(path_label)        train_imgs = glob.glob(path_merge + "/*." + "png")  # 所有訓練圖像        savedir = path_train   # 保存訓練集的路徑        if not os.path.lexists(savedir):            os.mkdir(savedir)        savedir = path_label  # 保存label的路徑        if not os.path.lexists(savedir):            os.mkdir(savedir)        for imgname in train_imgs:  # rindex("/") 是返回/在字符串中最後一次出現的索引            midname = imgname[imgname.rindex("/") + 1:imgname.rindex("." + "png")]  # 獲得文件名(不包含後綴)            #print("midname:",midname)            img = cv2.imread(imgname)  # 讀入訓練圖像            img_train = img[:, :, 2]  # 訓練集是第2個通道, label是第0個通道            img_label = img[:, :, 0]            newname=midname.split(\\\\)[1]            #print("new:",new)            cv2.imwrite(path_train + "/"  + newname + "_train" + "." + "png", img_train)  # 保存訓練圖像和label            print(path_train + "/"  + "/" + newname + "_train" + "." + "png")            cv2.imwrite(path_label + "/" + newname + "_label" + "." + "png", img_label)            print(path_label + "/"  + "/" + newname + "_label" + "." + "png")/<code> 

代碼部分不做詳述了,和之前組合的形式差不多,著重說下這裡,是自己不懂的部分:

<code># 獲得文件名(不包含後綴)# rindex("/") 是返回/在字符串中最後一次出現的索引midname = imgname[imgname.rindex("/") + 1:imgname.rindex("." + "png")]  /<code>

Python rindex() 返回子字符串 str 在字符串中最後出現的位置,如果沒有匹配的字符串會報異常,你可以指定可選參數[beg:end]設置查找的區間。

舉個栗子:

<code>import globpath_merge = "../one/aug_merge"  # 合併增強之後的圖像print("imgname:",path_merge)print(path_merge.rindex("/"))/<code>
深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

打印的結果

現在,把上文中的一段專門來看下打印結果

<code>import globpath_merge = "../one/aug_merge"  # 合併增強之後的圖像train_imgs = glob.glob(path_merge + "/*." + "png")  # 所有訓練圖像for imgname in train_imgs:  # rindex("/") 是返回/在字符串中最後一次出現的索引    print("imgname:",imgname)    print("imgname.rindex:",imgname.rindex("." + "png"))    print(imgname.rindex("/"))    midname = imgname[imgname.rindex("/") + 1:imgname.rindex("." + "png")]  # 獲得文件名(不包含後綴)    print("midname===",midname)    print("*"*20)/<code>
深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

截取圖像地址

最後,看下拆分後的圖片保存的結果吧!!!

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

aug_train_img

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

aug_train_label

這裡特意說下,圖像的數量是自己設置的,在這裡,imgnum數量,決定了對單幅圖像增強的數量。(如果你需要對其中增強的多一些,就把這塊給修改下)

<code> def do_augmentate(self, img, save_to_dir, save_prefix, batch_size=1, save_format=png, imgnum=30):/<code>

四.圖像增強之批處理

這塊的內容,不想做太多的解釋了,只是由單幅圖像的讀取,改為對文件夾內所有圖片的讀取。

但是,會把結果圖片這裡放一下,具體的代碼部分,歡迎去Github詳閱,地址:https://github.com/QianLingjun/Keras_image_aug,

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

批處理部分train_img,2是文件名

深度學習計算機視覺中,解決醫學圖像分割中數據不足的問題

批處理部分train_label,14是文件名

最後,歡迎關注“錢多多先森”,一個關注更多AI、CV、數碼、個人理財領域知識的醫療行業從業者。關注我,一起成長。

在文章的最後,再重複一次。歡迎去Github詳閱,地址:https://github.com/QianLingjun/Keras_image_aug,碼字不易,給個免費的贊再走吧

。下期我們再見,拜


分享到:


相關文章: