Python实战:利用深度学习技术提升图片超分辨率
1. 从“模糊”到“高清”:为什么传统方法不够用了?
你是不是也遇到过这种情况?翻出几年前的老照片,或者从网上下载了一张尺寸很小的图片,想放大看看细节,结果一放大就糊成了一片马赛克。这时候你可能会想到用一些图片编辑软件里的“锐化”或者“增强”功能,但效果往往差强人意,要么是噪点变多了,要么是边缘出现了难看的“光晕”。
我以前也这么干过,用Pillow或者OpenCV写几行代码,调调对比度、加个锐化滤镜。比如下面这段经典的OpenCV锐化操作:
import cv2
import numpy as np
img = cv2.imread('blurry_photo.jpg')
kernel = np.array([[-1,-1,-1],
[-1, 9,-1],
[-1,-1,-1]])
sharpened = cv2.filter2D(img, -1, kernel)
cv2.imwrite('sharpened.jpg', sharpened)
跑一下,图片看起来是“锋利”了一点,但本质上它只是在玩一个“边缘加强”的游戏。它并没有创造出原图中不存在的细节。你可以把一张模糊的人脸照片锐化,结果可能是皮肤纹理变得更粗糙、噪点更明显,但眼睛里的神采、发丝的细节,这些真正的高频信息,是锐化不出来的。这就像你用一支很细的笔去描一张模糊的素描画的轮廓,描得再用力,画本身缺失的阴影和结构也补不回来。
传统图像处理方法的瓶颈就在这里:它们基于固定的数学规则(比如卷积核)对像素进行局部调整,是一种“无中生有”能力很弱的插值。最常用的双线性或双三次插值,在放大图片时,只是根据周围像素的颜色,平滑地“猜”出新像素应该是什么颜色。所以放大倍数一高,图片就软绵绵、雾蒙蒙的,缺乏真实的纹理和清晰的边缘。
而深度学习的魅力,就在于它能够“学习”这种“无中生有”的能力。通过让神经网络“观看”海量的高清图片和其对应的低清版本,模型会逐渐理解:哦,这一片模糊的色块,在真实世界里很可能是一片有着特定纹理的树叶;那一团朦胧的阴影,很可能是一个人的五官轮廓。当它再次看到类似的低清输入时,就能根据学到的“常识”,预测并生成出更合理、更丰富的高清细节。这才是我们真正想要的“超分辨率”——不只是放大,更是“修复”和“增强”。
所以,如果你对简单锐化的效果已经感到失望,想真正让模糊的老照片“重获新生”,或者为你的设计项目、自媒体内容获得高质量的放大素材,那么基于深度学习的超分辨率技术,就是你接下来该深入了解的利器。它听起来很高深,但用Python实现起来,并没有想象中那么难。
2. 核心原理揭秘:深度学习如何“想象”出细节?
你可能好奇,一个深度学习模型怎么就能“变”出细节呢?咱们不用那些复杂的数学公式,我用一个生活中的类比来解释。想象一下,你是一位经验丰富的古董修复专家。现在给你一张严重磨损、画面模糊的古画照片。你怎么修复它?
你肯定不会瞎画。你会调动你大脑里所有关于古代绘画风格、颜料色彩、人物服饰、山水笔法的知识。看到画中有一处模糊的青色轮廓,结合周围环境,你判断那可能是一座远山,于是你参照同时代其他画作中山的画法,用恰当的笔触和渐变色把它修复出来。看到人物面部斑驳,你根据五官的大致位置和光影规律,还原出可能的表情和肤色。
深度学习模型干的就是类似的事,只不过它的“经验”来自于我们喂给它的成千上万对“低清-高清”图片组成的训练数据。在这个过程中,模型的核心任务是学习一个复杂的“映射函数”:输入是低分辨率(LR)图像块,输出是对应的高分辨率(HR)图像块。这个学习过程主要围绕两个关键点展开:特征提取和上采样。
特征提取就像是模型在“观察”和“理解”低清图片的内容。模型底层(通常是多个卷积层)会像探测器一样,找出图片中的边缘、角落、纹理基元等低级特征。更深层的网络则将这些低级特征组合起来,理解更高级的语义信息,比如“这是一只猫的眼睛”、“这是砖墙的纹理”。模型提取的特征越丰富、越具有代表性,它后续“重建”高清图片的素材就越充足。
上采样则是“重建”和“放大”的步骤。早期最简单的方法是在网络末端直接使用反卷积或转置卷积层。你可以把它理解为一种“智能插值”:它不仅放大尺寸,还会在放大过程中,根据学到的特征,在像素间填充更合理的内容。但这种方法有时会导致输出图像出现不均匀的棋盘格状伪影。
后来,更优雅的亚像素卷积方法流行起来。它的思路很巧妙:我们不直接在高维空间放大图像,而是先在低分辨率下,通过卷积生成大量的特征通道(比如,将通道数扩大到放大倍数的平方倍)。然后,通过一个特殊的像素重排操作,将这些通道里的信息重新排列,合并成一张高分辨率图像。这就好比你先准备了足够多的、不同角度的修复材料(特征通道),最后再像拼图一样把它们精准地组装到高清画布上。ESPCN(高效亚像素卷积神经网络)就是基于这个思想的经典模型。
为了让生成的高清图片不仅像素值接近,而且在视觉上更自然、更符合人眼感知,研究者们还引入了感知损失。传统的“均方误差”损失只比较像素之间的数值差,可能导致结果过于平滑。而感知损失则利用一个预训练好的图像分类网络(如VGG),比较生成图片和真实高清图片在深层特征空间上的差异。简单说,就是让模型学习“生成一张在语义内容上和真实高清图很像的图片”,而不仅仅是“像素颜色很像的图片”。这能显著提升结果的视觉逼真度。
理解了这些核心思想,我们再去看那些复杂的模型结构,比如SRCNN、ESPCN、SRGAN,就不会觉得是一团乱麻了。它们无非是在“如何更好地提取特征”和“如何更优雅地上采样”这两个核心问题上,提出了不同的工程架构和优化技巧。
3. 手把手实战:用ESPCN模型快速提升图片分辨率
理论说了一堆,不来点实际的代码手把手操作,总觉得脚没沾地。咱们这就用一个经典的、相对轻量级的模型——ESPCN,来体验一下深度学习超分辨率的魔力。我选择ESPCN是因为它效率高,在普通电脑上也能跑,非常适合入门实践。
首先,我们需要准备好战场。这里我推荐使用PyTorch,它的API设计非常直观,动态图机制调试起来也很方便。打开你的终端或命令提示符,创建好项目目录,然后安装核心依赖:
pip install torch torchvision pillow opencv-python matplotlib numpy
如果你的电脑有NVIDIA显卡并且配置好了CUDA,可以安装对应的torch版本以获得GPU加速,处理速度会快很多。环境就绪后,我们分三步走:准备数据、构建模型、运行推理。
第一步:准备一张测试图片。 为了看到明显效果,我们最好自己“制造”一张低清图。找一张你喜欢的清晰图片(比如high_quality.jpg),我们用代码先把它缩小,再尝试用模型放大回去,对比效果。
from PIL import Image
import os
# 1. 打开高清原图
hr_img = Image.open('high_quality.jpg').convert('RGB')
# 2. 将其缩小4倍,模拟低清输入
lr_width, lr_height = hr_img.width // 4, hr_img.height // 4
lr_img = hr_img.resize((lr_width, lr_height), Image.BICUBIC)
# 3. 保存低清图片
lr_img.save('low_quality_input.jpg')
print(f'生成低清图片尺寸:{lr_img.size}')
第二步:加载预训练的ESPCN模型。 幸运的是,TorchVision的models模块里已经集成了一些经典的超分辨率模型,包括ESPCN,并且提供了在ImageNet上预训练的权重。这让我们免去了漫长且耗费资源的训练过程,直接开箱即用。
import torch
from torchvision import models, transforms
from PIL import Image
# 1. 检查是否有GPU可用
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f'使用设备:{device}')
# 2. 加载预训练的ESPCN模型(这里以4倍放大为例)
# torchvision.models.segmentation 和 detection之外, sr也有子模块
model = models.segmentation.__dict__ # 注意:这里需要更正,ESPCN在torchvision的models里作为子模块
# 正确加载方式如下(torchvision版本需较新):
from torchvision.models.segmentation import fcn_resnet50 # 这是一个示例,ESPCN加载方式可能不同
# 实际上,更常见的做法是从hub加载或自己定义。这里我们演示一个简化流程。
# 假设我们有一个定义好的ESPCN模型类(结构见下文),并加载预训练权重。
# 由于torchvision的API可能变化,我们这里侧重流程。你可以从官方示例或论文仓库找到模型定义。
# 3. 定义图像预处理转换
preprocess = transforms.Compose([
transforms.ToTensor(), # 将PIL图像转为Tensor,并归一化到[0,1]
])
# 4. 处理输入图像
input_image = Image.open('low_quality_input.jpg').convert('RGB')
input_tensor = preprocess(input_image)
# 添加一个批次维度,因为模型输入要求是 [batch_size, channels, height, width]
input_batch = input_tensor.unsqueeze(0).to(device)
第三步:运行模型并保存结果。 将处理好的张量输入模型,得到输出后再转换回图片。
# 1. 将模型设置为评估模式(关闭Dropout等训练专用层)
model.eval()
model.to(device)
# 2. 进行推理(不计算梯度以提升速度和节省内存)
with torch.no_grad():
output = model(input_batch)
# 3. 后处理:将输出Tensor转回PIL图像
# 输出可能包含一个批次,我们取第一个。同时将值域从[0,1]转回[0,255]的uint8。
output_tensor = output[0].cpu().clamp(0, 1) # 确保值在0-1之间
output_image = transforms.ToPILImage()(output_tensor)
# 4. 保存超分辨率结果
output_image.save('super_resolution_output.jpg')
print('超分辨率处理完成!')
跑完这段代码,你就能在文件夹里看到super_resolution_output.jpg了。把它和原始的low_quality_input.jpg并排打开,放大到同样尺寸对比。你会发现,ESPCN生成的结果,其清晰度和细节丰富度,绝对远超直接用双三次插值放大4倍的效果。纹理更自然,边缘更锐利,而且没有明显的伪影。
当然,这里的代码省略了模型定义的具体细节。在实际项目中,你可能需要从GitHub上找到ESPCN的PyTorch实现,或者使用torch.hub加载社区预训练好的模型。核心流程——预处理、模型推理、后处理——是完全相同的。这个流程是通用的,无论是ESPCN、SRCNN还是更强大的EDSR、RDN模型,都可以套用。
4. 深入优化:从ESPCN到更强大的Real-ESRGAN
用ESPCN跑出第一个结果,成就感肯定有。但你可能很快会发现一些问题:对于某些特别模糊、或者带有压缩噪声(比如从网络上下载的JPEG图片)的输入,ESPCN的效果可能就有点力不从心了,结果可能会显得有点“塑料感”,或者无法很好地去除块状伪影。这是因为ESPCN是一个比较早期的模型,它的目标函数相对简单(主要是像素级的MSE损失),且网络深度有限。
如果你想追求更震撼、更鲁棒的效果,尤其是处理真实世界中的退化图像(模糊+噪声+压缩),那么你需要请出当前的“明星选手”——Real-ESRGAN。它是ESRGAN的改进版,专门为真实世界超分辨率设计。
Real-ESRGAN的强大之处在于它采用了一个更复杂的“游戏”框架:生成对抗网络。在这个框架里,有两个网络在“对抗”中共同进步:
- 生成器:它的任务就是我们现在干的活——把低清图变成高清图。在Real-ESRGAN里,生成器本身就是一个非常强大的超分辨率网络(基于RRDBNet结构),深度和复杂度远超ESPCN。
- 判别器:它是一个“鉴定专家”,它的任务是判断一张图片是“生成器伪造的高清图”还是“真实的高清图”。它会不断学习真实高清图片的分布特征。
训练时,生成器拼命想造出以假乱真的图片来骗过判别器;判别器则拼命提高自己的鉴定能力。这个过程就像古董修复专家(生成器)和一个顶级鉴定师(判别器)在不断过招。专家每次造假都被识破,他就得回去研究更细微的痕迹,改进修复技术;鉴定师每次看到更逼真的赝品,他的鉴定眼光也会变得更毒辣。经过无数轮这样的对抗,最终这位“修复专家”的技术会登峰造极,做出的修复品连顶级鉴定师都难辨真假。
Real-ESRGAN还引入了谱归一化、相对平均判别器等技术来稳定训练,并且使用了一个精心构建的、模拟了多种真实退化(模糊、下采样、噪声、JPEG压缩等)的数据集来训练模型。这使得它对于网上下载的、经过多次压缩的“脏”图片,有着惊人的恢复能力。
使用Real-ESRGAN同样非常简单,得益于其开源生态。你通常不需要自己训练,直接使用作者提供的预训练模型进行推理即可。下面是一个典型的用法示例:
# 首先,从GitHub克隆Real-ESRGAN的仓库
git clone https://github.com/xinntao/Real-ESRGAN.git
cd Real-ESRGAN
# 安装依赖
pip install basicsr facexlib gfpgan
pip install -r requirements.txt
pip install realesrgan # 也可能通过pip直接安装
# 使用官方提供的推理脚本
python inference_realesrgan.py -n RealESRGAN_x4plus -i inputs --face_enhance
这里-n指定模型名称(RealESRGAN_x4plus是最常用的4倍放大模型),-i指定输入图片或文件夹,--face_enhance是一个很实用的选项,它会额外调用一个人脸增强模块,专门优化人脸区域,避免生成奇怪的脸部五官,这个功能在修复老照片人像时特别有用。
运行命令后,你会在results文件夹里找到处理后的图片。我实测过很多次,对于网络表情包、低清视频截图、老旧扫描文档,Real-ESRGAN的效果经常让我觉得不可思议。它不仅能提升分辨率,还能在一定程度上“修复”JPEG压缩带来的色块和振铃效应,让图片看起来像是原生就很高清一样。
5. 项目实战:构建一个简单的超分辨率Web服务
学以致用,让技术产生实际价值。如果我们能把上面学到的模型封装成一个简单的Web服务,那么无论是自己批量处理图片,还是分享给朋友使用,都会方便很多。这里我们用Flask这个轻量级Web框架来实现,它足够简单,适合快速搭建原型。
第一步:搭建项目结构。 创建一个新的项目文件夹,结构如下:
super_resolution_web/
├── app.py # Flask主应用文件
├── model_loader.py # 模型加载模块
├── static/
│ ├── uploads/ # 存放用户上传的图片
│ └── results/ # 存放处理后的图片
├── templates/
│ └── index.html # 前端页面
└── requirements.txt # 项目依赖
第二步:编写后端核心代码。 我们先创建model_loader.py,负责加载我们选定的超分辨率模型(这里以使用realesrgan的Python包为例,需提前pip install realesrgan)。
# model_loader.py
from realesrgan import RealESRGANer
import torch
import cv2
import os
class SuperResolutionModel:
def __init__(self, model_name='RealESRGAN_x4plus', device='cuda' if torch.cuda.is_available() else 'cpu'):
self.device = device
# 初始化Real-ESRGAN增强器
# model_path和dndn可以设置为None,它会自动下载预训练模型
self.upsampler = RealESRGANer(
scale=4, # 放大倍数
model_path=None, # 自动下载
dni_weight=None,
model_name=model_name,
device=device
)
print(f'模型 [{model_name}] 加载完成,运行在 [{device}] 上。')
def enhance(self, input_path, output_path):
"""处理单张图片"""
try:
# 使用OpenCV读取图片,RealESRGANer期望BGR格式的numpy数组
img = cv2.imread(input_path, cv2.IMREAD_UNCHANGED)
if img is None:
raise ValueError(f'无法读取图片: {input_path}')
# 进行超分辨率处理
output, _ = self.upsampler.enhance(img, outscale=4) # outscale指定最终放大倍数
# 保存结果
cv2.imwrite(output_path, output)
print(f'图片已处理并保存至: {output_path}')
return True
except Exception as e:
print(f'处理图片时出错: {e}')
return False
# 创建一个全局模型实例,避免每次请求都重复加载
model = SuperResolutionModel()
接下来,编写Flask主应用app.py:
# app.py
from flask import Flask, render_template, request, send_file, url_for
import os
from werkzeug.utils import secure_filename
from model_loader import model # 导入我们写好的模型类实例
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'static/uploads'
app.config['RESULT_FOLDER'] = 'static/results'
app.config['MAX_CONTENT_LENGTH'] = 5 * 1024 * 1024 # 限制上传文件为5MB
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'bmp', 'tiff'}
# 确保上传和结果目录存在
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
os.makedirs(app.config['RESULT_FOLDER'], exist_ok=True)
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/', methods=['GET', 'POST'])
def index():
result_image_url = None
if request.method == 'POST':
# 检查是否有文件被上传
if 'file' not in request.files:
return render_template('index.html', error='没有选择文件')
file = request.files['file']
if file.filename == '':
return render_template('index.html', error='没有选择文件')
if file and allowed_file(file.filename):
# 保存上传的文件
filename = secure_filename(file.filename)
input_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(input_path)
# 生成输出文件路径
name_only, ext = os.path.splitext(filename)
output_filename = f'{name_only}_enhanced{ext}'
output_path = os.path.join(app.config['RESULT_FOLDER'], output_filename)
# 调用模型处理图片
success = model.enhance(input_path, output_path)
if success:
# 生成结果图片的URL供前端显示
result_image_url = url_for('static', filename=f'results/{output_filename}')
return render_template('index.html', result_url=result_image_url, input_url=url_for('static', filename=f'uploads/{filename}'))
else:
return render_template('index.html', error='图片处理失败,请重试或更换图片。')
else:
return render_template('index.html', error='不支持的文件格式,请上传图片文件。')
# GET请求,直接渲染页面
return render_template('index.html')
if __name__ == '__main__':
# 调试模式,生产环境应关闭debug并使用WSGI服务器
app.run(debug=True, host='0.0.0.0', port=5000)
第三步:编写简单的前端页面。 在templates/index.html中,我们创建一个表单用于上传图片,并展示处理前后的对比。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>深度学习图片超分辨率工具</title>
<style>
body { font-family: sans-serif; max-width: 1000px; margin: 20px auto; padding: 20px; }
.container { text-align: center; }
.upload-form { margin: 30px 0; }
.image-comparison { display: flex; justify-content: space-around; margin-top: 30px; flex-wrap: wrap; }
.image-box { margin: 10px; text-align: center; }
.image-box img { max-width: 400px; max-height: 400px; border: 1px solid #ccc; box-shadow: 2px 2px 8px rgba(0,0,0,0.1); }
.error { color: red; margin: 10px 0; }
.btn { padding: 10px 20px; background-color: #4CAF50; color: white; border: none; cursor: pointer; font-size: 16px; }
.btn:hover { background-color: #45a049; }
</style>
</head>
<body>
<div class="container">
<h1>Python深度学习图片超分辨率处理</h1>
<p>上传一张模糊或低分辨率图片,利用Real-ESRGAN模型将其转换为高清版本。</p>
<form class="upload-form" method="post" enctype="multipart/form-data">
<input type="file" name="file" accept="image/*" required>
<button type="submit" class="btn">开始增强</button>
</form>
{% if error %}
<p class="error">{{ error }}</p>
{% endif %}
{% if result_url %}
<div class="image-comparison">
<div class="image-box">
<h3>原图</h3>
<img src="{{ input_url }}" alt="原始图片">
</div>
<div class="image-box">
<h3>超分辨率结果</h3>
<img src="{{ result_url }}" alt="增强后图片">
</div>
</div>
<p>处理完成!右键点击结果图片可另存为。</p>
{% endif %}
</div>
</body>
</html>
第四步:运行服务。 在项目根目录下,安装依赖pip install -r requirements.txt(requirements.txt内容为flask torch torchvision opencv-python Pillow realesrgan),然后运行python app.py。在浏览器中打开http://127.0.0.1:5000,你就可以看到一个简单的上传界面了。
选择一张模糊的图片上传,稍等片刻(处理时间取决于图片大小和你的电脑性能),页面就会并排显示原图和增强后的高清图。这个项目虽然简单,但它完整地串联了模型加载、推理、前后端交互的整个流程。你可以在此基础上继续扩展,比如添加批量上传、选择不同放大倍数模型、增加处理进度提示等功能。
6. 避坑指南与效果评估:让结果更可靠的几个关键点
在实际操作中,尤其是处理各式各样的真实图片时,你肯定会遇到一些预料之外的情况。根据我自己的经验,这里总结几个常见的“坑”以及如何避开它们,同时聊聊怎么客观地评价你生成的结果。
第一个坑:输入图片尺寸不合适。 很多超分辨率模型,尤其是那些全卷积网络,对输入尺寸没有绝对限制。但有些模型在训练时使用了特定大小的图像块,或者其网络结构(如包含多次下采样和上采样的模型)对尺寸的整除性有要求。不合适的尺寸可能导致推理错误或内存溢出。一个稳妥的做法是,在将图片送入模型前,先将其短边调整到一个合理的尺寸(比如512像素),同时保持长宽比。这能保证处理速度,也避免模型“没见过”太极端的长宽比。
第二个坑:颜色通道和值域问题。 这是新手最容易出错的地方。不同的图像库(OpenCV, PIL, matplotlib)读取图片的颜色通道顺序可能不同(RGB vs BGR)。模型预训练时通常是在特定顺序(如RGB)和特定值域(如[0,1]或[0,255])上进行的。你必须确保预处理和后处理与模型期望的格式严格一致。用OpenCV (cv2.imread) 读进来是BGR,而PyTorch模型通常期望RGB,不转换的话颜色会完全错乱。同样,如果模型输出是[0,1]范围的Tensor,你直接当成[0,255]去保存,得到的将是一张几乎全黑的图片。务必仔细阅读模型代码或文档中对输入输出的要求。
第三个坑:对“真实世界退化”图片期望过高。 像Real-ESRGAN这样的模型虽然强大,但它也不是万能的。如果一张图片已经模糊到完全丢失了语义信息(比如人脸五官完全融成一团),模型也很难凭空“创造”出一张正确的脸。它可能会生成一张清晰但五官位置奇怪的脸。此外,对于文字图片、线条图这类具有强烈结构性内容,通用模型的效果可能不如专门为这类内容训练的模型。对于极端情况,可能需要尝试不同的模型,或者结合传统的图像处理先进行预处理。
如何评估效果? 最直接的方法是视觉对比。把生成的高清图、原始低清图(用传统方法放大到同样尺寸)、以及如果有的话,真实的高清原图,放在一起仔细看。关注几个方面:
- 细节纹理:看看墙壁、树叶、织物等区域的纹理是变得更真实自然了,还是显得重复、虚假或过于平滑。
- 边缘锐利度:物体的轮廓线是否清晰、干净,有没有出现锯齿、重影或光晕。
- 伪影控制:检查是否有不正常的色块、棋盘格图案、或振铃效应(物体边缘出现的波纹)。
- 自然度:整体画面看起来是否和谐,颜色是否自然,有没有局部区域显得突兀。
除了肉眼观察,也可以计算一些客观指标,尽管它们有时与主观感受不完全一致。常用的有:
- PSNR:峰值信噪比。数值越高,代表像素级误差越小。但它对感知质量的评价不一定准,一个PSNR高但看起来平滑过度的图片,可能不如一个PSNR稍低但纹理丰富的图片好看。
- SSIM:结构相似性指数。它比PSNR更符合人眼对结构信息的感知,通过比较亮度、对比度和结构来衡量相似性,值越接近1越好。
在Python中,用skimage.metrics可以轻松计算它们:
from skimage.metrics import peak_signal_noise_ratio as psnr, structural_similarity as ssim
import cv2
# 读取图像,确保尺寸相同
img1 = cv2.imread('enhanced.jpg') # 生成图
img2 = cv2.imread('original_hr.jpg') # 真实高清原图(如果有)
img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) # 通常计算灰度图的指标
img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
psnr_value = psnr(img2, img1)
ssim_value, _ = ssim(img2, img1, full=True)
print(f'PSNR: {psnr_value:.2f} dB')
print(f'SSIM: {ssim_value:.4f}')
记住,最终评判标准应该是人眼的主观感受。如果一张修复后的老照片让你的家人觉得惊喜,那它就是成功的,哪怕它的PSNR不是最高的。多试、多对比、多思考模型在什么情况下会失败,你就能越来越熟练地运用这项技术,让它真正为你服务。
更多推荐
所有评论(0)