当前位置: 首页 > 科技观察

DeepLearningProjectExampleBlurredImageRestorationUsingAutoencoders

时间:2023-03-18 10:07:39 科技观察

为了获得更清晰的照片,我们可以用相机镜头的首选焦点重新拍摄同一张照片,或者使用深度学习知识来重现模糊图像。由于我的专业不是摄影,所以我只能选择使用深度学习技术来对图像进行去模糊!在开始这个项目之前,本文假设读者应该了解深度学习的基本概念,比如神经网络、CNN。还要稍微熟悉Keras、Tensorflow和OpenCV。模糊有多种类型——运动模糊、高斯模糊、平均模糊等。但我们将重点关注高斯模糊图像。在这种模糊类型中,像素权重不相等。模糊在中心较高,在边缘沿钟形曲线降低。数据集在我们开始使用代码之前,我们首先需要的是一个由两组图像组成的数据集——模糊图像和干净图像。目前可能没有现成的数据集可以使用,但是我们上面说了,如果你有opencv的基础,这个对我们来说很简单。我们只要有原图,就可以使用opencv自己生成训练需要的。数据集。此处我的数据集大小约为50张图像(50张干净图像和50张模糊图像),仅选择了少数图像用于演示目的。编写代码现在数据集已准备就绪,是时候开始编写代码了。依赖项importnumpyasnpiimportpandasaspdimportmatplotlib.pyplotasplt%matplotlibinlineimportrandomimportcv2importosimporttensorflowastffromtqdmimporttqdm这里导入了tqdm库来帮助我创建一个进度条,这样我就可以知道运行代码需要多长时间.importdatagood_frames='/content/drive/MyDrive/mini_clean'bad_frames='/content/drive/MyDrive/mini_blur'现在创建了2个列表。我们将使用keras预处理库读取“.jpg”、“jpeg”或“.png”类型的图像并将它们转换为数组。这里的图像大小是128x128。clean_frames=[]用于tqdm中的文件(已排序(os.listdir(good_frames))):如果有(文件中的扩展名用于['.jpg','jpeg','.png']中的扩展名):image=tf.keras.preprocessing.image.load_img(good_frames+'/'+文件,target_size=(128,128))image=tf.keras.preprocessing.image.img_to_array(image).astype('float32')/255clean_frames.append(image)clean_frames=np.array(clean_frames)blurry_frames=[]forfileintqdm(sorted(os.listdir(bad_frames))):ifany(extensioninfileforextensionin['.jpg','jpeg','.png']):image=tf.keras.preprocessing.image.load_img(bad_frames+'/'+文件,target_size=(128,128))image=tf.keras.preprocessing.image.img_to_array(image).astype('float32')/255blurry_frames.append(image)blurry_frames=np.array(blurry_frames)导入模型库fromkeras.layersimportDense,Inputfromkeras.layersimportConv2D,Flattenfromkeras.layersimportReshape,Conv2DTransposefromkeras.modelsimportModelfromkeras.callbacksimportReduceLROnPlateau,ModelCcheckpointfromkeras.utils.vis_utilsimportplot_modelfromkerasimportbackendasKrandom.seed=21np.random.seed=seed将数据集拆分为训练集和测试集现在我们将数据集以80:20的比例拆分为训练集和测试集x=clean_frames;y=模糊帧;fromsklearn.model_selectionimporttrain_test_splitx_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=42)检查训练和测试数据集的形状print(x_train[0].shape)print(y_train[0].shape)r=random.randint(0,len(clean_frames)-1)print(r)fig=plt.figure()fig.subplots_adjust(hspace=0.1,wspace=0.2)ax=fig.add_subplot(1,2,1)ax.imshow(clean_frames[r])ax=fig.add_subplot(1,2,2)ax.imshow(blurry_frames[r])上面的代码可以看出训练和测试数据集的图像,例如:下面初始化一些写模型时需要用到的参数#NetworkParametersinput_shape=(128,128,3)batch_size=32kernel_size=3latent_dim=256#Encoder/DecodernumberofCNNlayersandfiltersperlayer_filters=[64,128,256]Encodermodel自编码器的结构在我们之前的文章中已经详细介绍过很多次,这里不再详细解释inputs=Input(shape=input_shape,name='encoder_input')x=inputs第一个是输入(图片数组)。得到输入后,构建了Conv2D(64)-Conv2D(128)-Conv2D(256)的简单编码器。编码器将图片压缩成(16,16,256),数组将作为解码器的输入。对于layer_filters中的过滤器:x=Conv2D(filters=filters,kernel_size=kernel_size,strides=2,activation='relu',padding='same')(x)shape=K.int_shape(x)x=Flatten()(x)latent=Dense(latent_dim,name='latent_vector')(x)其中K.int_shape()将张量转换为整数元组。实例化编码器模型如下encoder=Model(inputs,latent,name='encoder')encoder.summary()解码器模型解码器模型类似于编码器模型,但它进行相反的计算。解码器将输入解码回(128,128,3)。所以这里会使用Conv2DTranspose(256)-Conv2DTranspose(128)-Conv2DTranspose(64)。latent_inputs=Input(shape=(latent_dim,),name='decoder_input')x=Dense(shape[1]*shape[2]*shape[3])(latent_inputs)x=Reshape((shape[1],形状[2],shape[3]))(x)forfiltersinlayer_filters[::-1]:x=Conv2DTranspose(filters=filters,kernel_size=kernel_size,strides=2,activation='relu',padding='same')(x)outputs=Conv2DTranspose(filters=3,kernel_size=kernel_size,activation='sigmoid',padding='same',name='decoder_output')(x)解码器如下:decoder=Model(latent_inputs,outputs,name='decoder')decoder.summary()集成到autoencoderautoencoder=encoder+decoderautoencoder=Model(inputs,decoder(encoder(inputs)),name='autoencoder')autoencoder.summary()最后但并非最不重要,我们需要在训练模型之前设置超参数。autoencoder.compile(loss='mse',optimizer='adam',metrics=["acc"])我选择均方误差作为损失函数,adam作为优化器,accuracy作为评价指标。然后需要定义一个学习率调整的计划,这样在指标没有提高的情况下可以降低学习率,lr_reducer=ReduceLROnPlateau(factor=np.sqrt(0.1),cooldown=0,patient=5,verbose=1,min_lr=0.5e-6)学习率的调整需要每轮训练都调用,callbacks=[lr_reducer]trainingmodelhistory=autoencoder.fit(blurry_frames,clean_frames,validation_data=(blurry_frames,clean_frames),epochs=100,batch_size=batch_size,callbacks=callbacks)运行这段代码后,可能需要大约5-6分钟甚至更长的时间才能看到最终的输出,因为我们设置了训练轮数为100,最终的结果现在已经成功训练了模型,让我们看看我们模型的预测,print("\nInputGroundTruthPredictedValue")foriinrange(3):r=random.randint(0,len(clean_frames)-1)x,y=blurry_frames[r]、clean_frames[r]x_inp=x.reshape(1,128,128,3)result=autoencoder.predict(x_inp)result=result.reshape(128,128,3)fig=plt.figure(figsize=(12,10))图。subplots_adjust(hspace=0.1,wspace=0.2)ax=fig.add_subplot(1,3,1)ax.imshow(x)ax=fig.add_subplot(1,3,2)ax.imshow(y)ax=图。add_subplot(1,3,3)plt.imshow(result)可以看到模型对图像去模糊做的很好,几乎可以得到原图。由于我们只使用了3层卷积架构,如果我们使用更深的模型,一些超参数调整应该会产生更好的结果。为了查看训练进行得如何,您可以绘制损失函数和准确率,您可以使用这些数据做出更好的决策。损失变化plt.figure(figsize=(12,8))plt.plot(history.history['loss'])plt.plot(history.history['val_loss'])plt.legend(['Train','Test'])plt.xlabel('Epoch')plt.ylabel('Loss')plt.xticks(np.arange(0,101,25))plt.show()可以看到loss明显减少,然后从第80个纪元开始停滞不前。精度plt.figure(figsize=(12,8))plt.plot(history.history['acc'])plt.plot(history.history['val_acc'])plt.legend(['Train','Test'])plt.xlabel('Epoch')plt.ylabel('Accuracy')plt.xticks(np.arange(0,101,25))plt.show()这里可以看到准确率明显提升,如果训练更多的epoch,它可能会进一步提高。因此,尝试增加epoch大小并检查精度是否确实提高,或者添加提前停止以便训练自动停止总结我们实现了78.07%的不错精度。本文只是实际应用的开始,例如更好的网络架构、更多数据和超参数调优等。