澳门银河www.yh.cc

  首页   |  澳门银河www.yh.cc   |  澳门银河上网导航   |  澳门银河娱乐城   |  澳门银河贵宾登入
最新更新
相关文章
> 澳门银河www.yh.cc > 文章内容
澳门银河www.yh.cc用Keras跟“直方图平衡”为深度进修完成“图像裁减”
用Keras和“直方图均衡”为深度学习完成“图像扩充”

原题目:用Keras和“直方图均衡”为深度进修完成“图像扩充”

雷锋网按:本文由图普科技编译自《Image Augmentation for Deep Learning using Keras and Histogram Equalization》,雷锋网独家首发。

在这篇文章中,我们将要讨论的内容是:

  • 什么是“图像增强”?其重要性何在?

  • 如何使用Keras完成根本的“图像增强”?

  • 什么是“直方图均衡”?如何施展其感化?

  • 直方图平衡法--修正keras.preprocessing image.py文件的方法之一

  • 什么是“图像加强”?其主要性安在?

深度神经网络,尤其是卷积神经网络(CNN),非常擅擅长图像分类。现实证实,最进步的卷积神经网络在图像识别方面的机能曾经超越了人类水平。

https://www.eff.org/ai/metrics

但是,正如我们在杨建师长教师的“Hot Dog, Not Hot Dog”App(在一个叫做“Silicon Valley”的热点电视节目中的食品辨认App)中懂得到的,将图像搜集起来作为训练数据使用,是一项非常昂贵且耗时的任务。

假如你对“Silicon Valley”这个电视节目不太熟习,请留神以下视频中的言语是NSFW:

我们经过扩充图像数据的方式,从一个已有的数据库中天生更多新的训练图像,以下降搜集训练图像的本钱。“图像扩充”实在就是从已有的练习数据集中掏出一些图像,而后依据这些图像创立出很多修改版本的图像。这样做不只可能取得更多的训练数据,还能让我们的分类器应答光照跟颜色愈加庞杂的情况,从而使我们的分类器功效越来越强盛。以下是来自imgaug的不同的图像扩充例子:

https://github.com/aleju/imgaug

  • 用Keras完成基础的图像扩充

图像预处置的方法有良多。在本文中,我们将讨论一些罕见的、富有创意的方法,这些方法也是Keras深度学习库为扩充图像数据所提供的。之后我们将讨论如何转换keras预处理图像文件,以启用直方图均衡法。我们将使用Keras附带的cifar10数据集,但是为了使义务小到能够顺遂在CPU上执行,我们将只会使用其中的猫和狗的图像。

  • 数据加载及数据格式化

起首,我们须要加载cifar10数据集并格局化此中的图像,为卷积神经收集做好预备。我们还要检讨一下部门图像,确保数据曾经实现了准确的加载。

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]if K.image_data_format() == 'channels_first':
   x_train = x_train.reshape(x_train.shape[0], 3, img_rows, img_cols)
   x_test = x_test.reshape(x_test.shape[0], 3, img_rows, img_cols)
   input_shape = (3, img_rows, img_cols)
else:
   x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 3)
   x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 3)
   input_shape = (img_rows, img_cols, 3)x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')#Convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(np.ravel(y_train), num_classes)
y_test = keras.utils.to_categorical(np.ravel(y_test), num_classes)#Look at the first 9 images from the dataset
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()

Cifar10数据集中的图像都是32x 32像素巨细的,因而缩小来看,它们都浮现出颗粒状。但是对卷积神经网络来说,它看到的不是颗粒,而是数据。

  • 使用ImageDataGenerator函数创建一个图像生成器

用Keras停止图像数据的扩充是十分简略的,在这里,我们应当感激Jason Brownlee,因为是他给我们供给了一个无比片面、到位的Keras图像扩充教程。图象扩充的进程如下:首先,我们需要使用 ImageDataGenerator()函数来创建一个图像生成器,而且输出一系列描写图像更转业为的参数;之后,我们将在这个图像生成器中执行fit()函数,它将会一批一批地对图像停止更改。在默许情形下,图像的更改是恣意的,所以并不是一切图像每次城市被更改。你还可以用 keras.preprocessing 函数将扩充的图像导出到一个文件夹,以便树立一个更宏大的扩充图像数据集。

在本文中,我们将看一些更直不雅、风趣的扩充图像。你可以在Keras文件中检查一切的ImageDataGenerator参数,以及keras.preprocessing中的其余方法。

  • 恣意地扭转图像

# Rotate images by 90 degrees
datagen = ImageDataGenerator(rotation_range=90)# 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 9 images
   for i in range(0, 9):
       pyplot.subplot(330 + 1 + i)
       pyplot.imshow(X_batch[i].reshape(img_rows, img_cols, 3))
   # show the plot
   pyplot.show()
   break

  • 垂直翻转图片

# Flip images vertically
datagen = ImageDataGenerator(vertical_flip=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 9 images
   for i in range(0, 9):
       pyplot.subplot(330 + 1 + i)
       pyplot.imshow(X_batch[i].reshape(img_rows, img_cols, 3))
   # show the plot
   pyplot.show()
   break

程度翻转图片异样是为分类器生成更少数据的一种经典方式。这么做异常简单,但是我在这里省略了代码和图像,是因为我们在不看到原始图像的情况下,无奈断定一张猫狗的图像能否被水平翻转了。

  • 将图像垂直或水平挪动20%

# Shift images vertically or horizontally
# Fill missing pixels with the color of the nearest pixel
datagen = ImageDataGenerator(width_shift_range=.2,
                            height_shift_range=.2,
                            fill_mode='nearest')# 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 9 images
   for i in range(0, 9):
       pyplot.subplot(330 + 1 + i)
       pyplot.imshow(X_batch[i].reshape(img_rows, img_cols, 3))
   # show the plot
   pyplot.show()

 

  •    break直方图均衡法

直方图均衡,即取一张低对比度图像,并提高图像中最亮和最暗部分之间的对比度,以找出暗影的轻微差异,并创建一个更高对比度的图像。使用这个方法所发生的结果相称惊人,尤其是针对那些灰度图像。以下是一些例子:

https://www.bruzed.com/2009/10/contrast-stretching-and-histogram-equalization/

http://www-classes.usc.edu/engr/ee-s/569/qa2/Histogram%20Equalization.htm

https://studentathome.wordpress.com/2013/03/27/local-histogram-equalization/

在本文中,我们将讨论三种用于进步图像比较度的图像扩充方法。这些方法有时也被称作“直方图拉伸”,由于它们会应用像素强度的分布,并扩大这些散布以顺应更年夜范畴的值,从而提高图像中最亮和最暗部分之间的对照度。

  • 直方图均衡

直方图均衡法经过检测图像的像素强度分布,并绘制出一个像素强度直方图,从而提高图像的对比度。之后,这个直方图的分布会被停止分析,如果分析成果显示还有未被利用的像素亮度规模,那么这个直方图就会被“扩展”,以涵盖这些未被利用的范围。然后直方图将被“投射”到图像上,以提高图像的全体对比度。

  • 对比度扩展 

“对比度扩展”的过程首先是剖析图像中的像素强度分布,然后从新调理图像,使图像可以涵盖在2%至98%之间的一切像素强度。

  • 自顺应均衡

在直方图盘算方面,“自顺应均衡”与常规的直方图均衡有很大的差别。惯例的直方图均衡法中,每个被计算的直方图都与图像中的一个部分绝对应;然而,它有着在非畸形图像部分适度扩充噪声的趋向。

上面的代码来自于sci-kit图像库的文件。为了使这些代码能够在我们cifar10数据集的第一张图像上执行以上三种图像扩充,我们对代码停止了转换和修改。首先,我们将输出sic-kit图像库中的需要单位,然后对sci-kit图像文件中的代码停止修改和调整,澳门银河www.yh.cc,以便检查数据集第一张图片的扩充图像集。

# 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[:,澳门银河www.yh.cc, 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()

Here are the modified images of a low contrast cat from the cifar10 dataset. As you can see, the results are not as striking as they might be with a low contrast grayscale image, but still help improve the quality of the images.

上面这张图是一张修改后的图像,是由cifar10数据集中的一张对比度较低的猫咪图片修改失掉的。正如你所看到的,最后修改的图像结果可能并不像在低对比度灰度图像中失掉的图像成果那么令人冷艳,但总的来说图像的画质仍是失掉了提高。

  • 修改Keras.preprocessing以启用“直方图均衡法”

当初,我们曾经胜利地修改了cifar10数据集中的一张图像,咱们接上去将要探讨若何调剂或转变keras,澳门银河www.yh.cc.preprocessing图像文件,从而履行这些分歧的直方图修改方式,就像我们应用ImageDataGenerator()函数停止keras图像裁减一样。以下是我们将采用的多少个步调:

  • 步骤概述

  • 找出keras.preprocessing image py文件

  • 把image py文件复制到你的文件或许笔记本上。

  • 给每个均衡方法增添一个属性到ImageDataGenerator()init函数中。

  • 把“IF”的表白语句添加到随即转换的方法中,这样,我们在使用datagenfit()函数的时分,图像扩充就会被执行。

对keras.preprocessing的图像py文件停止修改和调整的最简单的方式之一就是将文件中的内容复制、粘贴到我们的代码中。这么做的利益是省略了我们下一个输出文件内容的步骤。你可以点击此处检查github上的图像文件。但是,为了确保你拿到的文件是之前输出的文件的雷同版本,你最好取你的机器上已有的图像文件。

运转print(keras._file_)将会打印出你机器上的keras库的路径,其路径(针对IMac用户)大抵如下:

/usr/local/lib/python3.5/dist-packages/keras/__init__.pyc

这给我们提供了本机机械上的路径,沿着门路导航,然落后入preprocessing文件夹;在preprocessing文件夹中你就会看到图像py文件,你可以将其中的内容复制到你的代码中。这个文件有点长,但对于初学者来说,这应该是最简单的方法了。

  • 编纂图像

你能够在图片顶部增加一行解释:from..import backend as K

到这里,你还需要再次检查,以确保你输出的是必需的scikit-image单元,这样复制的image.py才干识别出。

from skimage import data, img_as_float
from skimage import exposure

现在,我们需要给ImageDataGenerator类的方法添加六行代码,这样它就有三个属性来表现我们将要添加的图像扩充类型。上面的代码是从我现在的image.py中复制得来的:

 def __init__(self,
contrast_stretching=False, #####
histogram_equalization=False,#####
adaptive_equalization=False, #####
featurewise_center=False,
samplewise_center=False,
featurewise_std_normalization=False,
samplewise_std_normalization=False,
zca_whitening=False,
rotation_range=0.,
width_shift_range=0.,
height_shift_range=0.,
shear_range=0.,
zoom_range=0.,
channel_shift_range=0.,
fill_mode=’nearest’,
cval=0.,
horizontal_flip=False,
vertical_flip=False,
rescale=None,
preprocessing_function=None,
data_format=None):
if data_format is None:
data_format = K.image_data_format()
self.counter = 0
self.contrast_stretching = contrast_stretching, #####
self.adaptive_equalization = adaptive_equalization #####
self.histogram_equalization = histogram_equalization #####
self.featurewise_center = featurewise_center
self.samplewise_center = samplewise_center
self.featurewise_std_normalization = featurewise_std_normalization
self.samplewise_std_normalization = samplewise_std_normalization
self.zca_whitening = zca_whitening
self.rotation_range = rotation_range
self.width_shift_range = width_shift_range
self.height_shift_range = height_shift_range
self.shear_range = shear_range
self.zoom_range = zoom_range
self.channel_shift_range = channel_shift_range
self.fill_mode = fill_mode
self.cval = cval
self.horizontal_flip = horizontal_flip
self.vertical_flip = vertical_flip
self.rescale = rescale
self.preprocessing_function = preprocessing_function

上面的random_transform()函数响应我们之前传输至ImageDataGenerator函数的参数。如果我们把“对比度扩展”、“自顺应均衡”或“直方图均衡”的参数设置为“True”,那么当我们调用ImageDataGenerator函数的时分,random_transform()函数就会执行所需的图像扩充。

def random_transform(self, x):
 img_row_axis = self.row_axis - 1
 img_col_axis = self.col_axis - 1
 img_channel_axis = self.channel_axis - 1# use composition of homographies
# to generate final transform that needs to be applied
 if self.rotation_range:
    theta = np.pi / 180 * np.random.uniform(-self.rotation_range, self.rotation_range)
 else:
    theta = 0  if self.height_shift_range:
    tx = np.random.uniform(-self.height_shift_range, self.height_shift_range) * x.shape[img_row_axis]
 else:
    tx = 0  if self.width_shift_range:
    ty = np.random.uniform(-self.width_shift_range, self.width_shift_range) * x.shape[img_col_axis]
 else:
    ty = 0  if self.shear_range:
    shear = np.random.uniform(-self.shear_range, self.shear_range)
 else:
    shear = 0  if self.zoom_range[0] == 1 and self.zoom_range[1] == 1:
    zx, zy = 1, 1
 else:
    zx, zy = np.random.uniform(self.zoom_range[0], self.zoom_range[1], 2)transform_matrix = None
  if 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_matrix  if 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

现在,一切必备的代码都曾经筹备停当了,那么我们就可以挪用ImageDataGenerator()函数执行直方图修改的办法了。当我们将一切的参数设置为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 images
   for i in range(0, 9):
       pyplot.subplot(330 + 1 + i)
       pyplot.imshow(x_batch[i].reshape(img_rows, img_cols, 3))
   # show the plot
   pyplot.show()
   break

我不推举在任何给定的数据集中将一个以上的参数设置为True,你需要确保你的数据集试验有助于你提高分类器的正确性。对黑色图像,我发明“对比度扩展”的功效优于“直方图修改”或“自顺应均衡”的效果。

  • 训练并且验证你的keras卷积神经网络

最后一步,训练我们的卷积神经网络,并使用 model.fit_generator() 函数验证这个模子,从而完成在扩充图像上的神经网络的训练和验证。

from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2Dbatch_size = 64
num_classes = 2
epochs = 10model = 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))


↑返回顶部 | 关闭窗口