【KERAS/直方图均衡化】图像数据集扩充
原網(wǎng)址:
https://blog.csdn.net/sinat_36458870/article/details/78903092
一、我遇到了啥子問(wèn)題撒~?
我現(xiàn)在寫的文章都是因?yàn)橛龅絾?wèn)題了,然后把解決過(guò)程給大家呈現(xiàn)出來(lái)
那么,現(xiàn)在我遇到了一個(gè)醫(yī)學(xué)圖像處理問(wèn)題。
最近在處理醫(yī)學(xué)圖像的問(wèn)題,發(fā)現(xiàn)DataSet一共只有400張圖像,還是分為四類。
那怎么辦呢??
可能你會(huì)說(shuō):這還不簡(jiǎn)單,遷移學(xué)習(xí)啊?
soga,小伙子可以啊,不過(guò)今天我們不講它(因?yàn)槲疫€沒實(shí)踐過(guò))
在這篇文章中,我們將討論并解決此問(wèn)題:
二、我怎么解決的嘞?
- 圖像增強(qiáng):它是什么?它為什么如此重要?
- Keras:如何將它用于基本的圖像增強(qiáng)。
- 直方圖均衡化:這是什么?它有什么用處?
- 實(shí)現(xiàn)直方圖均衡技術(shù):修改keras.preprocessing image.py文件的一種方法。
三、我怎么做的嘞?
接下來(lái)我會(huì)從這四方面來(lái)討論解決數(shù)據(jù)不足的問(wèn)題
1.圖像增強(qiáng):它是什么?它為什么如此重要?
深度神經(jīng)網(wǎng)絡(luò),尤其是卷積神經(jīng)網(wǎng)絡(luò)(CNN),尤其擅長(zhǎng)圖像分類任務(wù)。最先進(jìn)的CNN甚至已經(jīng)被證明超過(guò)了人類在圖像識(shí)別方面的表現(xiàn)。
image source:https://www.eff.org/ai/metrics- 1
- 2
如果想克服收集數(shù)以千計(jì)的訓(xùn)練圖像的高昂費(fèi)用,圖像增強(qiáng)則就是從現(xiàn)有數(shù)據(jù)集生成訓(xùn)練數(shù)據(jù)。?
圖像增強(qiáng)是將已經(jīng)存在于訓(xùn)練數(shù)據(jù)集中的圖像進(jìn)行處理,并對(duì)其進(jìn)行處理以創(chuàng)建相同圖像的許多改變的版本。
這既提供了更多的圖像來(lái)訓(xùn)練,也可以幫助我們的分類器暴露在更廣泛的倆個(gè)都和色彩情況下,從而使我們的分類器更具有魯棒性,以下是imgaug庫(kù)中不同增強(qiáng)的一些示例
source image:https://github.com/aleju/imgaug
2.使用Keras進(jìn)行基本圖像增強(qiáng)
有很多方法來(lái)預(yù)處理圖像,在這篇文章中,我借鑒使用keras深度學(xué)習(xí)庫(kù)為增強(qiáng)圖像提供的一些最常用的開箱即用方法,然后演示如何修改keras.preprocessing image.py文件以啟用直方圖均衡化方法。
我們將使用keras自帶的cifar10數(shù)據(jù)集。但是,我們只會(huì)使用數(shù)據(jù)集中的貓和狗的圖像,以便保持足夠小的任務(wù)在CPU上執(zhí)行。
- 加載 和 格式化數(shù)據(jù)
我們要做的第一件事就是加載cifar10數(shù)據(jù)集并格式化圖像,為CNN做準(zhǔn)備。?
我們還會(huì)仔細(xì)查看一些圖像,以確保數(shù)據(jù)已正確加載
先偷看一下長(zhǎng)什么樣?
16]: from __future__ import print_function import keras from keras.datasets import cifar10 from keras import backend as K import matplotlib from matplotlib import pyplot as plt import numpy as np# input image dimensions img_rows, img_cols = 32, 32 # the data, shuffled and split between train and test sets (x_train, y_train), (x_test, y_test) = cifar10.load_data() # Only look at cats [=3] and dogs [=5] train_picks = np.ravel(np.logical_or(y_train==3,y_train==5)) test_picks = np.ravel(np.logical_or(y_test==3,y_test==5)) y_train = np.array(y_train[train_picks]==5,dtype=int) y_test = np.array(y_test[test_picks]==5,dtype=int)x_train = x_train[train_picks] x_test = x_test[test_picks]... ... ...images = range(0,9)for i in images:plt.subplot(330 + 1 + i)plt.imshow(x_train[i], cmap=pyplot.get_cmap('gray')) # show the plot plt.show()- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
此處代碼參考鏈接地址:https://github.com/ryanleeallred/Image_Augmentation/blob/master/Histogram_Modification.ipynb
cifar10圖像只有32 x 32像素,所以在這里放大時(shí)看起來(lái)有顆粒感,但是CNN并不知道它有顆粒感,只能看到數(shù)據(jù), 嗯,還是人類牛逼。
- 從ImageDataGenerator()創(chuàng)建一個(gè)圖像生成器
用keras增強(qiáng) 圖像數(shù)據(jù) 非常簡(jiǎn)單。 Jason Brownlee?對(duì)此提供了一個(gè)很好的教程。
首先,我們需要通過(guò)調(diào)用ImageDataGenerator()函數(shù)來(lái)創(chuàng)建一個(gè)圖像生成器,并將它傳遞給我們想要在圖像上執(zhí)行的變化的參數(shù)列表。
然后,我們將調(diào)用fit()我們的圖像生成器的功能,這將逐批地應(yīng)用到圖像的變化。默認(rèn)情況下,這些修改將被隨機(jī)應(yīng)用,所以并不是每一個(gè)圖像都會(huì)被改變。大家也可以使用keras.preprocessing導(dǎo)出增強(qiáng)的圖像文件到一個(gè)文件夾,以便建立一個(gè)巨大的數(shù)據(jù)集的改變圖像,如果你想這樣做,可以參考keras文檔。
- 隨機(jī)旋轉(zhuǎn)圖像
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 垂直翻轉(zhuǎn)圖像
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
備注:我感覺這里需要針對(duì)數(shù)據(jù)集,因?yàn)楹苌儆腥税压贩^(guò)來(lái)看,或者拍照(hahhhh)
- 將圖像垂直或水平移動(dòng)20%
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
3.直方圖均衡技術(shù)
直方圖均衡化是指對(duì)比度較低的圖像,并增加圖像相對(duì)高低的對(duì)比度,以便在陰影中產(chǎn)生細(xì)微的差異,并創(chuàng)建較高的對(duì)比度圖像。結(jié)果可能是驚人的,特別是對(duì)于灰度圖像,如圖
使用圖像增強(qiáng)技術(shù)來(lái)提高圖像的對(duì)比度,此方法有時(shí)也被稱為“ 直方圖拉伸?
”,因?yàn)樗鼈儾捎孟袼貜?qiáng)度的分布和拉伸分布來(lái)適應(yīng)更寬范圍的值,從而增加圖像的最亮部分和最暗部分之間的對(duì)比度水平。
直方圖均衡?
直方圖均衡通過(guò)檢測(cè)圖像中像素密度的分布并將這些像素密度繪制在直方圖上來(lái)增加圖像的對(duì)比度。然后分析該直方圖的分布,并且如果存在當(dāng)前未被使用的像素亮度范圍,則直方圖被“拉伸”以覆蓋這些范圍,然后被“?
反投影 ”到圖像上以增加總體形象的對(duì)比
自適應(yīng)均衡?
自適應(yīng)均衡與常規(guī)直方圖均衡的不同之處在于計(jì)算幾個(gè)不同的直方圖,每個(gè)直方圖對(duì)應(yīng)于圖像的不同部分;?
然而,在其他無(wú)趣的部分有過(guò)度放大噪聲的傾向。
下面的代碼來(lái)自于sci-kit圖像庫(kù)的文檔,并且已經(jīng)被修改為在我們的cifar10數(shù)據(jù)集的第一個(gè)圖像上執(zhí)行上述三個(gè)增強(qiáng)。
首先,我們將從sci-kit圖像(skimage)庫(kù)中導(dǎo)入必要的模塊,然后修改sci-kit圖像文檔中的代碼以查看數(shù)據(jù)集第一幅圖像上的增強(qiáng)
# Import skimage modules from skimage import data, img_as_float from skimage import exposure # Lets try augmenting a cifar10 image using these techniques from skimage import data, img_as_float from skimage import exposure # Load an example image from cifar10 dataset img = images[0] # Set font size for images matplotlib.rcParams['font.size'] = 8 # Contrast stretching p2, p98 = np.percentile(img, (2, 98)) img_rescale = exposure.rescale_intensity(img, in_range=(p2, p98)) # Histogram Equalization img_eq = exposure.equalize_hist(img) # Adaptive Equalization img_adapteq = exposure.equalize_adapthist(img, clip_limit=0.03) #### Everything below here is just to create the plot/graphs #### # Display results fig = plt.figure(figsize=(8, 5)) axes = np.zeros((2, 4), dtype=np.object) axes[0, 0] = fig.add_subplot(2, 4, 1) for i in range(1, 4):axes[0, i] = fig.add_subplot(2, 4, 1+i, sharex=axes[0,0], sharey=axes[0,0]) for i in range(0, 4):axes[1, i] = fig.add_subplot(2, 4, 5+i) ax_img, ax_hist, ax_cdf = plot_img_and_hist(img, axes[:, 0]) ax_img.set_title('Low contrast image') y_min, y_max = ax_hist.get_ylim() ax_hist.set_ylabel('Number of pixels') ax_hist.set_yticks(np.linspace(0, y_max, 5)) ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_rescale, axes[:, 1]) ax_img.set_title('Contrast stretching') ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_eq, axes[:, 2]) ax_img.set_title('Histogram equalization') ax_img, ax_hist, ax_cdf = plot_img_and_hist(img_adapteq, axes[:, 3]) ax_img.set_title('Adaptive equalization') ax_cdf.set_ylabel('Fraction of total intensity') ax_cdf.set_yticks(np.linspace(0, 1, 5)) # prevent overlap of y-axis labels fig.tight_layout() plt.show()- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
4.修改keras.preprocessing以啟用直方圖均衡技術(shù)。
現(xiàn)在我們已經(jīng)成功地從cifar10數(shù)據(jù)集中修改了一個(gè)圖像,我們將演示如何修改keras.preprocessing?
image.py文件,以執(zhí)行這些不同的直方圖修改技術(shù),就像我們開箱即可使用的keras增強(qiáng)使用ImageDataGenerator()。
以下是我們將要執(zhí)行此功能的一般步驟:
- 在你自己的機(jī)器上找到keras.preprocessing image.py文件。
- 將image.py文件復(fù)制到您的文件或筆記本中。
- 為每個(gè)均衡技術(shù)添加一個(gè)屬性到DataImageGenerator()init函數(shù)。
- 將IF語(yǔ)句子句添加到random_transform方法,以便在我們調(diào)用時(shí)實(shí)現(xiàn)增強(qiáng)datagen.fit()。
對(duì)keras.preprocessing
image.py文件進(jìn)行修改的最簡(jiǎn)單方法之一就是將其內(nèi)容復(fù)制并粘貼到我們的代碼中。這將刪除需要導(dǎo)入它。為了確保您抓取的是之前導(dǎo)入的文件的相同版本,最好抓取image.py您計(jì)算機(jī)上已有的文件。?
運(yùn)行print(keras.__file__)將打印出機(jī)器上keras庫(kù)的路徑。路徑(對(duì)于mac用戶)可能如下所示:
- 1
- 2
這給了我們?cè)诒镜貦C(jī)器上keras的路徑。
繼續(xù)前進(jìn),在那里導(dǎo)航,然后進(jìn)入preprocessing文件夾。在里面preprocessing你會(huì)看到image.py文件。然后您可以將其內(nèi)容復(fù)制到您的代碼中。該文件很長(zhǎng),但對(duì)于初學(xué)者來(lái)說(shuō),這可能是最簡(jiǎn)單的方法之一。
編輯 image.py
在image.py的頂部,你可以注釋掉這行:from ..import backend as K如果你已經(jīng)包含在上面。
此時(shí),請(qǐng)仔細(xì)檢查以確保您正在導(dǎo)入必要的scikit-image模塊,以便復(fù)制的模塊image.py可以看到它們。
from skimage import data, img_as_float from skimage import exposure- 1
- 2
- 3
我們現(xiàn)在需要在ImageDataGenerator類的?_ init _?
方法中添加六行代碼,以便它具有三個(gè)代表我們要添加的增強(qiáng)類型的屬性。下面的代碼是從我目前的image.py中復(fù)制的。與#####側(cè)面的線是我已經(jīng)添加的線
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
該random_transform()(下)函數(shù)來(lái)響應(yīng)我們一直傳遞到的參數(shù)ImageDataGenerator()功能。
如果我們已經(jīng)設(shè)置了contrast_stretching,adaptive_equalization或者h(yuǎn)istogram_equalization參數(shù)True,當(dāng)我們調(diào)用ImageDataGenerator()時(shí)(就像我們對(duì)其他圖像增強(qiáng)一樣)random_transform()將會(huì)應(yīng)用所需的圖像增強(qiáng)。
def random_transform(self, x):img_row_axis = self.row_axis - 1img_col_axis = self.col_axis - 1img_channel_axis = self.channel_axis - 1 # use composition of homographies # to generate final transform that needs to be appliedif self.rotation_range:theta = np.pi / 180 * np.random.uniform(-self.rotation_range, self.rotation_range)else:theta = 0if self.height_shift_range:tx = np.random.uniform(-self.height_shift_range, self.height_shift_range) * x.shape[img_row_axis]else:tx = 0if self.width_shift_range:ty = np.random.uniform(-self.width_shift_range, self.width_shift_range) * x.shape[img_col_axis]else:ty = 0if self.shear_range:shear = np.random.uniform(-self.shear_range, self.shear_range)else:shear = 0if self.zoom_range[0] == 1 and self.zoom_range[1] == 1:zx, zy = 1, 1else:zx, zy = np.random.uniform(self.zoom_range[0], self.zoom_range[1], 2) transform_matrix = Noneif theta != 0:rotation_matrix = np.array([[np.cos(theta), -np.sin(theta), 0],[np.sin(theta), np.cos(theta), 0],[0, 0, 1]])transform_matrix = rotation_matrixif tx != 0 or ty != 0:shift_matrix = np.array([[1, 0, tx],[0, 1, ty],[0, 0, 1]])transform_matrix = shift_matrix if transform_matrix is None else np.dot(transform_matrix, shift_matrix)if shear != 0:shear_matrix = np.array([[1, -np.sin(shear), 0],[0, np.cos(shear), 0],[0, 0, 1]])transform_matrix = shear_matrix if transform_matrix is None else np.dot(transform_matrix, shear_matrix)if zx != 1 or zy != 1:zoom_matrix = np.array([[zx, 0, 0],[0, zy, 0],[0, 0, 1]])transform_matrix = zoom_matrix if transform_matrix is None else np.dot(transform_matrix, zoom_matrix)if transform_matrix is not None:h, w = x.shape[img_row_axis], x.shape[img_col_axis]transform_matrix = transform_matrix_offset_center(transform_matrix, h, w)x = apply_transform(x, transform_matrix, img_channel_axis,fill_mode=self.fill_mode, cval=self.cval)if self.channel_shift_range != 0:x = random_channel_shift(x, self.channel_shift_range, img_channel_axis)if self.horizontal_flip:if np.random.random() < 0.5:x = flip_axis(x, img_col_axis)if self.vertical_flip:if np.random.random() < 0.5:x = flip_axis(x, img_row_axis)if self.contrast_stretching: #####if np.random.random() < 0.5: #####p2, p98 = np.percentile(x, (2, 98)) #####x = exposure.rescale_intensity(x, in_range=(p2, p98)) #####if self.adaptive_equalization: #####if np.random.random() < 0.5: #####x = exposure.equalize_adapthist(x, clip_limit=0.03) #####if self.histogram_equalization: #####if np.random.random() < 0.5: #####x = exposure.equalize_hist(x) #####return x- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
現(xiàn)在我們擁有所有必要的代碼,并且可以調(diào)用ImageDataGenerator()來(lái)執(zhí)行我們的直方圖修改技術(shù)。如果我們將所有三個(gè)值都設(shè)置為,則這是幾張圖片的樣子True
# Initialize Generator datagen = ImageDataGenerator(contrast_stretching=True, adaptive_equalization=True, histogram_equalization=True) # fit parameters from data datagen.fit(x_train) # Configure batch size and retrieve one batch of images for x_batch, y_batch in datagen.flow(x_train, y_train, batch_size=9):# Show the first 9 imagesfor i in range(0, 9):pyplot.subplot(330 + 1 + i)pyplot.imshow(x_batch[i].reshape(img_rows, img_cols, 3))# show the plotpyplot.show()break- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 培訓(xùn)并驗(yàn)證您的Keras CNN
最后一步是訓(xùn)練CNN并驗(yàn)證模型model.fit_generator(),以便在增強(qiáng)圖像上訓(xùn)練和驗(yàn)證我們的神經(jīng)網(wǎng)絡(luò).
from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten from keras.layers import Conv2D, MaxPooling2D batch_size = 64 num_classes = 2 epochs = 10 model = Sequential() model.add(Conv2D(4, kernel_size=(3, 3),activation='relu',input_shape=input_shape)) model.add(Conv2D(8, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(16, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(2, activation='softmax'))model.compile(loss=keras.losses.categorical_crossentropy,optimizer=keras.optimizers.Adadelta(),metrics=['accuracy']) datagen.fit(x_train) history = model.fit_generator(datagen.flow(x_train, y_train, batch_size=batch_size),steps_per_epoch=x_train.shape[0] // batch_size,epochs=20,validation_data=(x_test, y_test))- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
End 總結(jié)
這是我最后的測(cè)試結(jié)果
左上、增強(qiáng)測(cè)試圖片 右上、增強(qiáng)結(jié)果
左下、原始數(shù)據(jù)標(biāo)簽 右下、原始數(shù)據(jù)
大家自己嘗試一下哈,加油!
總結(jié)
以上是生活随笔為你收集整理的【KERAS/直方图均衡化】图像数据集扩充的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Keras学习手册(一)
- 下一篇: MATLAB 优化程序【profile简