首页 » SEO优化 » phpblurimage技巧_在Keras上实现GAN构建消除图片模糊的应用

phpblurimage技巧_在Keras上实现GAN构建消除图片模糊的应用

访客 2024-11-21 0

扫一扫用手机浏览

文章目录 [+]

Keras代码地址:https://github.com/RaphaelMeudec/deblur-gan

此外,请查阅DeblurGAN的原始论文(https://arxiv.org/pdf/1711.07064.pdf)及其Pytorch版本实现:https://github.com/KupynOrest/DeblurGAN/。

phpblurimage技巧_在Keras上实现GAN构建消除图片模糊的应用

天生对抗网络简介

phpblurimage技巧_在Keras上实现GAN构建消除图片模糊的应用
(图片来自网络侵删)

在天生对抗网络中,有两个网络相互进行演习。
天生器通过天生逼真的虚假输入来误导判别器,而判别器会分辨输入是真实的还是人造的。

GAN演习流程

演习过程中有三个关键步骤:

利用天生器根据噪声创造虚假输入;

利用真实输入和虚假输入演习判别器;

演习全体模型:该模型是判别器和天生器连接所构建的。

请把稳,判别器的权重在第三步中被冻结。

对两个网络进行连接的缘故原由是不存在单独对天生器输出的反馈。
我们唯一的衡量标准是判别器是否能接管天生的样本。

以上,我们简要先容了GAN的架构。
如果你以为不足详尽,可以参考这篇精良的先容:天生对抗网络初学入门:一文读懂GAN的基本事理(附资源)。

数据

Ian Goodfellow首先运用GAN模型天生MNIST数据。
而在本教程中,我们将天生对抗网络运用于图像去模糊。
因此,天生器的输入不是噪声,而是模糊的图像。

根据场景的不同,该数据集在不同子文件夹等分类。

你可以下载大略版:HTTPS://drive.google.com/file/d/1H0PIXvJH4c40pk7ou6nAwoxuR4Qh_Sa2/view

或完全版:HTTPS://drive.google.com/file/d/1SlURvdQsokgsoyTosAaELc4zRjQz9T2U/view

我们首先将图像分配到两个文件夹A(模糊)B(清晰)中。
这种A&B的架构对应于原始的pix2pix论文。
为此我创建了一个自定义的脚本在github中实行这个任务,请按照README的解释去利用它:

https://github.com/RaphaelMeudec/deblur-gan/blob/master/organize_gopro_dataset.py

模型

演习过程保持不变。
首先,让我们看看神经网络的架构吧!

天生器

该天生器旨在重现清晰的图像。
该网络基于ResNet模块,它不断地追踪关于原始模糊图像的演化。
本文同样利用了一个基于UNet的版本,但我还没有实现这个版本。
这两种模块该当都适宜图像去模糊。

DeblurGAN天生器网络架构,源论文“DeblurGAN:Blind Motion Deblurring Using Conditional Adversarial Networks”。

其核心是运用于原始图像上采样的9个ResNet模块。
让我们来看看Keras上的代码实现!

from keras.layers import Input, Conv2D, Activation, BatchNormalizationfrom keras.layers.merge import Addfrom keras.layers.core import Dropoutdef res_block(input, filters, kernel_size=(3,3), strides=(1,1), use_dropout=False): \"大众\"大众\"大众 Instanciate a Keras Resnet Block using sequential API. :param input: Input tensor :param filters: Number of filters to use :param kernel_size: Shape of the kernel for the convolution :param strides: Shape of the strides for the convolution :param use_dropout: Boolean value to determine the use of dropout :return: Keras Model \"大众\"大众\"大众 x = ReflectionPadding2D((1,1))(input) x = Conv2D(filters=filters, kernel_size=kernel_size, strides=strides,)(x) x = BatchNormalization()(x) x = Activation('relu')(x) if use_dropout: x = Dropout(0.5)(x) x = ReflectionPadding2D((1,1))(x) x = Conv2D(filters=filters, kernel_size=kernel_size, strides=strides,)(x) x = BatchNormalization()(x) # Two convolution layers followed by a direct connection between input and output merged = Add()([input, x]) return merged

该ResNet层基本是卷积层,其输入和输出都被添加以形成终极的输出。

from keras.layers import Input, Activation, Addfrom keras.layers.advanced_activations import LeakyReLUfrom keras.layers.convolutional import Conv2D, Conv2DTransposefrom keras.layers.core import Lambdafrom keras.layers.normalization import BatchNormalizationfrom keras.models import Modelfrom layer_utils import ReflectionPadding2D, res_blockngf = 64input_nc = 3output_nc = 3input_shape_generator = (256, 256, input_nc)n_blocks_gen = 9def generator_model(): \公众\"大众\公众Build generator architecture.\"大众\"大众\"大众 # Current version : ResNet block inputs = Input(shape=image_shape) x = ReflectionPadding2D((3, 3))(inputs) x = Conv2D(filters=ngf, kernel_size=(7,7), padding='valid')(x) x = BatchNormalization()(x) x = Activation('relu')(x) # Increase filter number n_downsampling = 2 for i in range(n_downsampling): mult = 2i x = Conv2D(filters=ngfmult2, kernel_size=(3,3), strides=2, padding='same')(x) x = BatchNormalization()(x) x = Activation('relu')(x) # Apply 9 ResNet blocks mult = 2n_downsampling for i in range(n_blocks_gen): x = res_block(x, ngfmult, use_dropout=True) # Decrease filter number to 3 (RGB) for i in range(n_downsampling): mult = 2(n_downsampling - i) x = Conv2DTranspose(filters=int(ngf mult / 2), kernel_size=(3,3), strides=2, padding='same')(x) x = BatchNormalization()(x) x = Activation('relu')(x) x = ReflectionPadding2D((3,3))(x) x = Conv2D(filters=output_nc, kernel_size=(7,7), padding='valid')(x) x = Activation('tanh')(x) # Add direct connection from input to output and recenter to [-1, 1] outputs = Add()([x, inputs]) outputs = Lambda(lambda z: z/2)(outputs) model = Model(inputs=inputs, outputs=outputs, name='Generator') return model

天生器架构的Keras实现

按照操持,9个ResNet模块会运用于输入的上采样版本。
我们在个中添加了从输入到输出的连接,并对结果除以2以保持标准化输出。

这便是天生器的架构!
让我们连续看看判别器怎么做吧。

判别器

判别器的目标是判断输入图像是否是人造的。
因此,判别器的体系构造是卷积以及输出单一值。

from keras.layers import Inputfrom keras.layers.advanced_activations import LeakyReLUfrom keras.layers.convolutional import Conv2Dfrom keras.layers.core import Dense, Flattenfrom keras.layers.normalization import BatchNormalizationfrom keras.models import Modelndf = 64output_nc = 3input_shape_discriminator = (256, 256, output_nc)def discriminator_model(): \"大众\公众\"大众Build discriminator architecture.\"大众\公众\公众 n_layers, use_sigmoid = 3, False inputs = Input(shape=input_shape_discriminator) x = Conv2D(filters=ndf, kernel_size=(4,4), strides=2, padding='same')(inputs) x = LeakyReLU(0.2)(x) nf_mult, nf_mult_prev = 1, 1 for n in range(n_layers): nf_mult_prev, nf_mult = nf_mult, min(2n, 8) x = Conv2D(filters=ndfnf_mult, kernel_size=(4,4), strides=2, padding='same')(x) x = BatchNormalization()(x) x = LeakyReLU(0.2)(x) nf_mult_prev, nf_mult = nf_mult, min(2n_layers, 8) x = Conv2D(filters=ndfnf_mult, kernel_size=(4,4), strides=1, padding='same')(x) x = BatchNormalization()(x) x = LeakyReLU(0.2)(x) x = Conv2D(filters=1, kernel_size=(4,4), strides=1, padding='same')(x) if use_sigmoid: x = Activation('sigmoid')(x) x = Flatten()(x) x = Dense(1024, activation='tanh')(x) x = Dense(1, activation='sigmoid')(x) model = Model(inputs=inputs, outputs=x, name='Discriminator') return model

判别器架构的Keras实现

末了一步是构建完全的模型本文中这个天生对抗网络的分外性在于:其输入是实际图像而非噪声因此,对付天生器的输出,我们能得到直接的反馈。

from keras.layers import Inputfrom keras.models import Modeldef generator_containing_discriminator_multiple_outputs(generator, discriminator): inputs = Input(shape=image_shape) generated_images = generator(inputs) outputs = discriminator(generated_images) model = Model(inputs=inputs, outputs=[generated_images, outputs]) return model

让我们一起看看,如何利用两个丢失函数来充分利用这种分外性。

演习过程

丢失函数

我们在两个级别提取丢失函数:天生器的末端和全体模型的末端。

前者是一种知觉丢失(perceptual loss),它直接根据天生器的输出打算而来。
这种丢失函数确保了GAN模型面向一个去模糊任务。
它比较了VGG第一批卷积的输出值。

import keras.backend as Kfrom keras.applications.vgg16 import VGG16from keras.models import Modelimage_shape = (256, 256, 3)def perceptual_loss(y_true, y_pred): vgg = VGG16(include_top=False, weights='imagenet', input_shape=image_shape) loss_model = Model(inputs=vgg.input, outputs=vgg.get_layer('block3_conv3').output) loss_model.trainable = False return K.mean(K.square(loss_model(y_true) - loss_model(y_pred)))

而后者是对全体模型的输出实行的Wasserstein丢失,它取的是两个图像差异的均值。
这种丢失函数可以改进天生对抗网络的收敛性。

import keras.backend as Kdef wasserstein_loss(y_true, y_pred): return K.mean(y_truey_pred)

演习过程

第一步是加载数据并初始化所有模型。
我们利用我们的自定义函数加载数据集,同时在我们的模型中添加Adam优化器。
我们通过设置Keras的可演习选项防止判别器进行演习。

# Load datasetdata = load_images('./images/train', n_images)y_train, x_train = data['B'], data['A']# Initialize modelsg = generator_model()d = discriminator_model()d_on_g = generator_containing_discriminator_multiple_outputs(g, d)# Initialize optimizersg_opt = Adam(lr=1E-4, beta_1=0.9, beta_2=0.999, epsilon=1e-08)d_opt = Adam(lr=1E-4, beta_1=0.9, beta_2=0.999, epsilon=1e-08)d_on_g_opt = Adam(lr=1E-4, beta_1=0.9, beta_2=0.999, epsilon=1e-08)# Compile modelsd.trainable = Trued.compile(optimizer=d_opt, loss=wasserstein_loss)d.trainable = Falseloss = [perceptual_loss, wasserstein_loss]loss_weights = [100, 1]d_on_g.compile(optimizer=d_on_g_opt, loss=loss, loss_weights=loss_weights)d.trainable = True

然后,我们启动epoch并将数据集分身分歧批量。

for epoch in range(epoch_num): print('epoch: {}/{}'.format(epoch, epoch_num)) print('batches: {}'.format(x_train.shape[0] / batch_size)) # Randomize images into batches permutated_indexes = np.random.permutation(x_train.shape[0]) for index in range(int(x_train.shape[0] / batch_size)): batch_indexes = permutated_indexes[indexbatch_size:(index+1)batch_size] image_blur_batch = x_train[batch_indexes] image_full_batch = y_train[batch_indexes]

末了,根据两种丢失,我们先后演习判别器和天生器。
我们用天生器产生虚假输入,然后演习判别器来区分虚假输入和真实输入,并演习全体模型。

for epoch in range(epoch_num): for index in range(batches): # [Batch Preparation] # Generate fake inputs generated_images = g.predict(x=image_blur_batch, batch_size=batch_size) # Train multiple times discriminator on real and fake inputs for _ in range(critic_updates): d_loss_real = d.train_on_batch(image_full_batch, output_true_batch) d_loss_fake = d.train_on_batch(generated_images, output_false_batch) d_loss = 0.5 np.add(d_loss_fake, d_loss_real) d.trainable = False # Train generator only on discriminator's decision and generated images d_on_g_loss = d_on_g.train_on_batch(image_blur_batch, [image_full_batch, output_true_batch]) d.trainable = True

你可以参考如下Github地址查看完全的循环:

https://www.github.com/raphaelmeudec/deblur-gan

材料

我利用了Deep Learning AMI(3.0版本)中的AWS实例(p2.xlarge)。
它在GOPRO数据集上的演习韶光约为5小时(50个epoch)。

图像去模糊结果

从左到右:原始图像,模糊图像,GAN输出。

上面的输出是我们Keras Deblur GAN的输出结果。
纵然是在模糊不清的情形下,网络也能够产生更令人信服的图像。
车灯和树枝都会更清晰。

左图:GOPRO测试图片; 右图:GAN输出。

个中的一个限定是图像顶部的噪点图案,这可能是由于利用VGG作为丢失函数引起的。

左图:GOPRO测试图片; 右图:GAN输出。

希望你在这篇「基于天生对抗网络进行图像去模糊」的文章中度过了一段愉快的阅读光阴!

左图:GOPRO测试图片; 右图:GAN输出。

论文:DeblurGAN:利用条件敌对网络的盲运动消解

论文地址:HTTPS://arxiv.org/pdf/1711.07064.pdf

择要:我们提出了一种基于有条件的GAN和内容丢失函数的运动去模糊的端到端学习方法--DeblurGAN。
在构造相似性丈量和视觉外不雅观方面,DeblurGAN达到了业内最前辈的技能水平。
去模糊模型的质量也以一种新颖的办法在现实问题中考量 - 即对(去)模糊图像的工具检测。
该方法比目前最佳的竞争对手速率提升了5倍。
其余,我们提出了一种从清晰图像合成运动模糊图像的新方法,它可以实现真实数据集的增强。

模型,演习代码和数据集都可以在以下地址得到:HTTPS://github.com/KupynOrest/DeblurGAN。

原文链接:HTTPS://blog.sicara.com/keras-generative-adversarial-networks-image-deblurring-45e3ab6977b5

标签:

相关文章