RealESRGAN_x2plus超分辨率模型实战:从环境搭建到批量处理与部署

1. 从“模糊”到“清晰”:RealESRGAN_x2plus 能做什么?

如果你手头有一张分辨率不高、细节模糊的老照片,或者是从视频里截取出来的一帧画面,又或者是在弱光环境下拍摄的、噪点明显的图片,你肯定想过:要是能把它变清晰就好了。传统的图像放大,比如在Photoshop里直接拉大尺寸,往往只是让像素点变大了,图像会变得更“糊”,边缘出现锯齿和马赛克。这就是所谓的“插值放大”的局限性,它只是在已有的像素之间“猜”出新的像素,无法创造出图片中原本不存在的真实细节。

而 RealESRGAN_x2plus 的出现,就是为了解决这个问题。它不是一个简单的滤镜,而是一个基于深度学习的超分辨率模型。简单来说,你可以把它理解为一个经过海量高清-模糊图片对训练出来的“图像修复专家”。当你把一张低分辨率图片交给它时,它并不是在“猜测”新像素,而是在根据它从训练中学到的“知识”,去“推理”和“重建”出图片在更高分辨率下应该有的纹理、边缘和细节。这个过程,我们称之为“超分辨率重建”。

RealESRGAN_x2plus 这个名字本身就包含了它的核心信息。“Real”意味着它针对的是真实世界中的复杂退化(模糊、噪声、压缩失真等),而不仅仅是实验室里人为制造的简单模糊。“ESRGAN”是其前身模型 Enhanced Super-Resolution Generative Adversarial Network 的缩写,这是一种非常强大的生成对抗网络架构。“x2plus”则指明了它的放大倍数至少是2倍,并且通过一些技术手段,理论上可以支持任意倍数的放大(比如4倍、8倍),但通常以2倍为基础倍数进行调用,效果和速度最为均衡。

所以,当你用代码调用 RealESRGAN_x2plus 时,你实际上是在启动一个“AI修图师”,让它自动化、批量化地为你处理图像清晰化的工作。这对于很多场景都非常有用:修复家庭老照片、提升游戏截图或动漫图片的画质、为低分辨率素材制作高清海报、甚至辅助医学影像或卫星图像的分析。接下来,我们就深入看看,如何把这个强大的工具集成到你的工作流中。

2. 环境搭建与模型获取:万事开头,细节决定成败

在开始写调用代码之前,我们必须先把“舞台”搭好。这个舞台包括运行环境、必要的软件库,以及最核心的——预训练好的模型文件。很多新手在这里踩坑,不是因为步骤复杂,而是忽略了一些关键的细节。

2.1 Python 环境与核心依赖库

RealESRGAN 是基于 PyTorch 框架实现的,因此一个配置正确的 Python 环境是首要条件。我强烈建议使用 Anaconda 或 Miniconda 来创建独立的虚拟环境,避免与系统或其他项目的 Python 包发生冲突。

首先,创建一个新的 conda 环境(这里以 Python 3.8 为例,这是一个兼容性较好的版本):

conda create -n realesrgan_env python=3.8 conda activate realesrgan_env

接下来,安装 PyTorch。这一步需要根据你是否有 NVIDIA GPU 以及 CUDA 版本来决定。访问 PyTorch 官网获取最新的安装命令是最稳妥的。例如,对于 CUDA 11.3 的用户:

pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu113

如果没有 GPU,或者想先快速测试,可以安装 CPU 版本:

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu

然后,安装 RealESRGAN 官方仓库中要求的其他依赖。最核心的是basicsr库,它是 RealESRGAN 所依赖的一个底层图像复原工具箱。我们通常通过克隆官方仓库来安装:

git clone https://github.com/xinntao/Real-ESRGAN.git cd Real-ESRGAN pip install -r requirements.txt python setup.py develop

执行python setup.py develop而不是pip install .的好处是,它以“开发模式”安装,你对本地仓库代码的修改会立即生效,方便后续调试或自定义。

注意:安装过程中可能会遇到各种依赖冲突,特别是opencv-pythonnumpy的版本问题。如果报错,可以尝试先单独安装一个稍旧但稳定的版本,例如pip install opencv-python==4.5.5.64。原则是优先保证basicsrtorch能正常安装。

2.2 模型文件的获取与放置

模型文件(.pth文件)是 RealESRGAN 的“大脑”,没有它,代码什么都做不了。官方提供了多个预训练模型,最常用的就是RealESRGAN_x2plus.pth

方法一:通过代码自动下载(推荐)官方仓库的inference_realesrgan.py脚本内置了模型下载逻辑。当你第一次运行脚本并指定模型名称(如RealESRGAN_x2plus)时,如果检测到本地没有对应的.pth文件,它会自动从 GitHub Release 页面下载并保存到默认目录(通常是~/.cache/torch/hub/checkpoints/)。这是最省事的方法。

方法二:手动下载如果网络环境导致自动下载失败,你就需要手动操作了。

  1. 访问 Real-ESRGAN 的 GitHub Release 页面:https://github.com/xinntao/Real-ESRGAN/releases
  2. 找到最新的发布版本,在 Assets 里找到RealESRGAN_x2plus.pth文件并下载。
  3. 手动放置模型文件。你需要知道代码去哪里找模型。通常,你需要将下载的.pth文件放入Real-ESRGAN/experiments/pretrained_models/目录下。如果该目录不存在,就创建它。
    mkdir -p experiments/pretrained_models mv /你的下载路径/RealESRGAN_x2plus.pth ./experiments/pretrained_models/

一个关键的踩坑点:模型路径解析很多人在手动放置模型后依然报错“找不到模型”,问题出在代码的路径解析逻辑上。在inference_realesrgan.py中,有一段代码会尝试从多个路径加载模型:先尝试从torch.hub缓存目录加载,如果失败,则尝试从experiments/pretrained_models/加载,再失败则尝试从basicsr库的模型目录加载。 如果你手动放置了模型,但脚本依然去torch.hub目录找,当然找不到。这时,你可以在调用时直接使用本地模型的绝对路径,这是最可靠的方式。我们会在下一章的代码示例中具体说明。

3. 核心调用代码详解:从单张图片到批量处理

环境准备好后,我们就可以进入正题了。Real-ESRGAN 仓库提供了一个非常方便的脚本inference_realesrgan.py,我们既可以直接使用命令行调用,也可以将其核心功能嵌入到我们自己的 Python 程序中。我们来把这两种方式都吃透。

3.1 命令行直接调用:快速验证与简单任务

对于简单的单张或单文件夹图片处理,命令行是最快的方式。进入Real-ESRGAN目录后,基本命令格式如下:

python inference_realesrgan.py -n RealESRGAN_x2plus -i input.jpg -o results

让我们拆解每个参数:

  • -n RealESRGAN_x2plus: 指定使用的模型名称。脚本会根据这个名字去查找或下载对应的.pth文件。
  • -i input.jpg: 指定输入图像路径。可以是一张图片(如test.jpg),也可以是一个文件夹路径(如./input_images/),脚本会自动处理文件夹内所有支持的图片格式。
  • -o results: 指定输出目录。处理后的图片会保存在这个目录下,文件名会增加_out后缀(如input_out.jpg)。

更多实用参数:

  • --face_enhance: 这是一个非常重要的选项。如果处理的图片中包含人脸,启用此选项会调用 GFPGAN 模型对人脸区域进行针对性增强,能显著提升人脸清晰度和自然度。命令变为:
    python inference_realesrgan.py -n RealESRGAN_x2plus -i input.jpg -o results --face_enhance
  • -s 4: 指定放大倍数(scale)。虽然模型是x2plus,但通过插值算法,可以执行 4 倍放大。例如,将一张 500x500 的图放大到 2000x2000。命令为:
    python inference_realesrgan.py -n RealESRGAN_x2plus -i input.jpg -o results -s 4
  • --tile 0: 处理超大图像时,可能会因为显存不足而崩溃。--tile参数可以将图像分割成多个小块(瓦片)分别处理,最后再拼接起来。0表示自动计算合适的瓦片大小。如果你的图很大或显存很小,可以加上这个参数。
    python inference_realesrgan.py -n RealESRGAN_x2plus -i large_input.jpg -o results --tile 0

命令行方式的优缺点:

  • 优点:简单直接,无需写代码,适合一次性任务或集成到 Shell 脚本中。
  • 缺点:灵活性差,难以进行复杂的前后处理(如自定义图像预处理、结果分析、集成到Web服务等)。

3.2 编写 Python 脚本调用:获得完全控制权

为了将 RealESRGAN 集成到你的应用程序、自动化流水线或 Web 后端,你需要编写 Python 代码来调用它。核心是使用RealESRGAN类。下面是一个最基础的、健壮的示例:

import os import cv2 import torch from basicsr.archs.rrdbnet_arch import RRDBNet from realesrgan import RealESRGANer def upscale_image(input_path, output_path, model_path=None, scale=2, face_enhance=False): """ 使用 RealESRGAN_x2plus 放大单张图片 Args: input_path: 输入图片路径 output_path: 输出图片路径 model_path: 预训练模型文件(.pth)的**绝对路径**。为None则尝试自动下载。 scale: 放大倍数 face_enhance: 是否启用人脸增强 """ # 1. 确定设备 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') print(f'使用设备: {device}') # 2. 定义模型架构 (必须与.pth文件匹配) # RealESRGAN_x2plus 使用的是 RRDBNet,通道数为3,缩放因子为scale model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=scale) # 3. 初始化 RealESRGANer # 关键参数解释: # scale: 放大倍数 # model_path: 模型文件路径。这里提供了两种方式: # a) 指定本地绝对路径(最可靠) # b) 传None,让 `RealESRGANer` 尝试按名称下载(需要网络) # model: 上面定义的模型架构对象 # tile: 瓦片大小,0为自动,用于处理大图防止OOM # tile_pad: 瓦片重叠像素,减少接缝 # pre_pad: 图像边缘填充像素,改善边界效果 # half: 是否使用半精度浮点数(fp16)推理,能减少显存占用并可能加速,但某些显卡可能不支持 upsampler = RealESRGANer( scale=scale, model_path=model_path, model=model, tile=0, # 自动瓦片 tile_pad=10, pre_pad=0, half=device.type != 'cpu' # 在GPU上使用半精度 ) # 4. 可选:加载人脸增强模型 if face_enhance: from gfpgan import GFPGANer face_enhancer = GFPGANer( model_path='https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth', upscale=scale, arch='clean', channel_multiplier=2, bg_upsampler=upsampler # 将RealESRGAN作为背景放大器 ) # 注意:当使用face_enhance时,后续处理逻辑会不同,这里为简化先不展开。 # 实际使用时,需要判断图像中是否有人脸,并调用face_enhancer.enhance。 # 5. 读取图像 # 使用OpenCV读取,颜色通道顺序为BGR img = cv2.imread(input_path, cv2.IMREAD_COLOR) if img is None: raise FileNotFoundError(f"无法读取图像: {input_path}") # 6. 执行超分辨率 try: # output 是放大后的图像 (numpy array, BGR格式) output, _ = upsampler.enhance(img, outscale=scale) except RuntimeError as error: print(f'推理过程出错: {error}') print('如果是因为显存不足(CUDA out of memory),尝试设置 `tile` 为一个较小的值,如400。') # 可以在这里重试,或者调整参数 upsampler.tile = 400 output, _ = upsampler.enhance(img, outscale=scale) # 7. 保存结果 # 确保输出目录存在 os.makedirs(os.path.dirname(output_path), exist_ok=True) cv2.imwrite(output_path, output) print(f'图片已保存至: {output_path}') if __name__ == '__main__': # 使用示例1:指定本地模型路径(最稳定) model_pth_path = '/绝对路径/到/你的/Real-ESRGAN/experiments/pretrained_models/RealESRGAN_x2plus.pth' upscale_image('low_res_photo.jpg', 'results/high_res_photo.jpg', model_path=model_pth_path, scale=2, face_enhance=False) # 使用示例2:让程序自动按模型名查找/下载(需要网络) # upscale_image('low_res_photo.jpg', 'results/high_res_photo_auto.jpg', # model_path=None, scale=2, face_enhance=False) # 当 model_path=None 时,RealESRGANer 内部会尝试加载名为 'RealESRGAN_x2plus' 的模型。

这段代码包含了几个关键点:

  1. 设备检测:自动判断使用 GPU 还是 CPU。
  2. 模型架构定义RRDBNet的参数必须与你要加载的.pth文件严格匹配。对于RealESRGAN_x2plus,使用代码中所示的参数。
  3. 初始化RealESRGANer:这是核心类,封装了加载模型、预处理、推理、后处理的完整流程。注意half参数在 GPU 上启用可以节省显存。
  4. 异常处理:用try-except包裹推理过程,捕获显存不足 (RuntimeError) 等错误,并给出降级方案(如减小tile值)。
  5. 模型路径:强烈建议在正式项目中使用本地模型的绝对路径(model_pth_path),这样可以避免网络问题和不必要的下载,也便于代码部署。

3.3 批量处理与性能优化

在实际项目中,我们很少只处理一张图。批量处理需要关注效率和资源管理。

简单的文件夹批量处理:

import glob from concurrent.futures import ThreadPoolExecutor, as_completed def batch_upscale_folder(input_dir, output_dir, model_path, scale=2, max_workers=2): """批量处理一个文件夹下的所有图片""" # 支持的图片格式 extensions = ('*.jpg', '*.jpeg', '*.png', '*.bmp', '*.tif', '*.tiff') input_paths = [] for ext in extensions: input_paths.extend(glob.glob(os.path.join(input_dir, ext))) if not input_paths: print(f'在目录 {input_dir} 中未找到图片文件。') return os.makedirs(output_dir, exist_ok=True) # 使用线程池并行处理(注意:如果模型很大,多线程可能争抢GPU内存,需谨慎) # 对于CPU密集型或IO密集型任务,多线程有帮助。对于大型GPU模型,顺序处理可能更稳定。 with ThreadPoolExecutor(max_workers=max_workers) as executor: future_to_path = {} for inp_path in input_paths: filename = os.path.basename(inp_path) name, ext = os.path.splitext(filename) out_path = os.path.join(output_dir, f'{name}_out{ext}') # 提交任务 future = executor.submit(upscale_image, inp_path, out_path, model_path, scale) future_to_path[future] = (inp_path, out_path) # 等待所有任务完成,并处理结果 for future in as_completed(future_to_path): inp_path, out_path = future_to_path[future] try: future.result() # 这里会重新抛出任务执行时的异常 print(f'完成: {inp_path} -> {out_path}') except Exception as exc: print(f'处理 {inp_path} 时产生异常: {exc}')

性能优化要点:

  • tile参数调优:处理超大图像(如超过 2000x2000)时,务必设置tile参数。值越小,内存占用越低,但可能会因为瓦片间重叠计算而略微变慢。通常设置为 0(自动)或 400、600 等。
  • 半精度推理 (half=True):在支持 FP16 的 GPU(如 NVIDIA Volta 架构及以后)上,设置half=True可以大幅减少显存占用,有时还能加速推理。这是性价比极高的优化。
  • 批处理 (Batch Inference):原版RealESRGANerenhance方法一次只处理一张图。如果你需要处理大量尺寸相同的小图,可以修改代码,将多张图片堆叠成一个批次(batch)送入模型,能充分利用 GPU 的并行计算能力,显著提升吞吐量。但这需要对模型前向传播部分有更深的理解和修改。
  • ONNX/TensorRT 部署:对于追求极致性能的生产环境,可以考虑将 PyTorch 模型转换为 ONNX 格式,进而使用 TensorRT 进行优化和部署。这能获得数倍甚至数十倍的推理速度提升,但转换和调试过程较为复杂。

4. 实战中的问题排查与效果调优

即使代码能跑起来,也不代表万事大吉。在实际使用中,你会遇到各种预期之外的情况。这一章,我们集中解决那些最常见的“坑”。

4.1 常见错误与解决方案

错误1:RuntimeError: CUDA out of memory.这是最经典的错误,意味着显卡显存不够了。

  • 根本原因:输入图像太大,或者模型本身加载后占用的显存超出了显卡容量。
  • 解决方案
    1. 启用瓦片处理 (tile):这是首选方案。在初始化RealESRGANer时,将tile设置为一个正整数,如 400。这会将图像切分成 400x400 的小块进行处理。
    2. 减小输入尺寸:在调用enhance之前,先用 OpenCV 将图像等比例缩小到一个合理的尺寸(如长边不超过 1500 像素),处理完后再放大回去?不,这违背了超分辨率的初衷。更好的方法是分步处理:先缩放到一个中间尺寸用 RealESRGAN 处理,如果还不够,可以多次应用。
    3. 使用 CPU 模式:如果显卡实在太弱,在初始化时强制使用device=torch.device('cpu'),但速度会慢几十倍。
    4. 启用半精度:确保half=True(在 GPU 上),这能直接减少近一半的显存占用。

错误2:KeyError: 'params_ema'Unexpected key(s) in state_dict

  • 根本原因:模型文件.pth中保存的权重字典的键名,与代码中定义的模型对象 (RRDBNet) 期望加载的键名不匹配。这通常发生在模型文件版本与代码版本不一致,或者你错误地下载了其他模型的权重时。
  • 解决方案
    1. 检查模型文件:确认你下载的确实是RealESRGAN_x2plus.pth,并且来自官方仓库的最新 Release。
    2. 查看权重键名:你可以用torch.load('model.pth', map_location='cpu')加载并打印键名,看看开头的键是什么。有时官方模型会包含params_emaparams两组权重,而代码默认加载params_ema。如果只有params,你需要修改加载逻辑,或者更简单的方法:在初始化RealESRGANer时,添加参数model_path指向文件,并设置dni_weight=None(如果不需要动态网络插值)。复杂的权重键名问题可能需要你手动调整加载字典。
    3. 使用官方脚本验证:先用官方的inference_realesrgan.py命令行脚本测试同一个模型文件是否能正常工作。如果能,对比你的代码和官方脚本在初始化RealESRGANer时的参数差异。

错误3:处理后的图像颜色异常或出现奇怪伪影

  • 根本原因:OpenCV (cv2) 默认使用 BGR 颜色通道顺序,而很多图像处理库或显示器期望 RGB 顺序。此外,图像数值范围(0-255 还是 0-1)或类型(uint8 还是 float32)不对也可能导致问题。
  • 解决方案
    1. 统一颜色空间RealESRGANer.enhance返回的output是 BGR 格式的numpy数组。如果你需要保存为 RGB 格式的图片供其他用途,需要在保存前转换:
      output_rgb = cv2.cvtColor(output, cv2.COLOR_BGR2RGB) # 然后用PIL或其他库保存 output_rgb
    2. 检查数值范围:确保输入给模型的图像是uint8类型,值在 0-255 之间。enhance方法内部会处理归一化。输出output也是 0-255 范围的uint8
    3. 伪影问题:如果图像出现网格状、块状伪影,这通常是tile参数设置不当,瓦片之间的重叠 (tile_pad) 太小导致的。尝试增大tile_pad(例如从 10 增加到 20)。另一种可能是模型在训练时未见过此类图像特征,产生了“幻觉”,这属于模型能力的边界。

4.2 效果调优:什么图效果好,什么图效果差?

RealESRGAN_x2plus 不是万能的,理解其能力边界能帮你更好地使用它。

效果通常很好的场景:

  • 自然风景、建筑照片:对于线条、纹理比较清晰的真实世界图像,增强效果显著,能恢复出丰富的细节。
  • 动漫/游戏截图:这类图片通常颜色分明、边缘清晰,模型能很好地去除压缩带来的锯齿和色块。
  • 轻度模糊的老照片:对于因对焦不准或轻微运动造成的模糊,有不错的去模糊和细节重建效果。

效果可能不佳或需要特别注意的场景:

  • 重度噪声图像:如果原图充满了椒盐噪声或高斯噪声,RealESRGAN 可能会将噪声也当作细节进行“增强”,导致结果更糟。建议先使用专业的降噪工具(如 Topaz Denoise AI)或 OpenCV 降噪滤波器进行处理,再进行超分。
  • 极端低分辨率图像:比如将一个 50x50 的图标放大到 500x500,信息缺失太严重,模型很难凭空生成合理的细节,结果可能看起来“塑料感”很强或不自然。
  • 文字图像:对于包含大量小号文字的场景(如文档截图),超分辨率可能会让文字笔画粘连或产生畸变。有专门针对文档超分的模型(如 Real-ESRGAN 的文本增强版本),效果会更好。
  • 人脸特写(未开启face_enhance:普通模式对人脸的处理可能产生不自然的表情或皮肤纹理。务必在有人脸的图片上尝试--face_enhance选项或集成 GFPGAN

一个重要的经验:先预处理,后超分。对于质量很差的源图,一套组合拳往往比直接超分更有效。例如:降噪 -> 轻度锐化/对比度调整 -> RealESRGAN 超分 -> 最终微调。你可以使用 OpenCV 或 Pillow 库轻松实现这些预处理步骤。

4.3 与 GFPGAN 结合进行人脸增强

RealESRGAN 负责整体画质提升,而 GFPGAN 专门负责修复人脸。它们可以协同工作。在命令行中,一个--face_enhance参数就搞定了。在代码中,我们需要稍微多做一些工作。

原理是:GFPGANer 将 RealESRGANer 作为它的bg_upsampler(背景上采样器)。GFPGAN 会先检测图像中的人脸区域,只对这些人脸区域进行高保真修复,其余背景区域则交给 RealESRGAN 去处理,最后将两部分结果融合。

集成代码片段如下:

# 假设 upsampler 是已经初始化好的 RealESRGANer 对象 from gfpgan import GFPGANer # 初始化 GFPGAN 人脸增强器 face_enhancer = GFPGANer( model_path='https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth', upscale=scale, # 放大倍数,需与背景放大倍数一致 arch='clean', channel_multiplier=2, bg_upsampler=upsampler # 关键:传入背景超分模型 ) # 读取图像 img = cv2.imread(input_path) # 使用人脸增强器进行处理 # 注意:enhance 方法返回一个列表,第一个元素是处理后的BGR图像 try: _, _, output = face_enhancer.enhance( img, has_aligned=False, # 输入图像是否是人脸对齐后的?我们输入的是整图,所以是False only_center_face=False, # 是否只处理中心人脸?通常False paste_back=True, # 是否将增强后的人脸贴回原图?必须为True weight=0.5 # 融合权重,通常0.5即可 ) except Exception as e: print(f'人脸增强失败,回退到纯超分: {e}') output, _ = upsampler.enhance(img, outscale=scale) # 保存 output cv2.imwrite(output_path, output)

这段代码实现了带人脸增强的完整流程。try-except块很重要,因为如果图片中没有人脸,GFPGAN 的enhance方法可能会出错,我们需要一个回退方案,即使用普通的 RealESRGAN 超分。

5. 进阶应用:封装与部署

当你的代码稳定运行后,可以考虑将其工程化,以便于团队协作、持续集成或对外提供服务。

5.1 将功能封装成类

将之前的代码封装成一个类,管理模型加载、配置和推理状态,更加清晰和可复用。

class RealESRGANUpscaler: def __init__(self, model_path, scale=2, tile=0, device='cuda'): self.scale = scale self.device = torch.device(device if torch.cuda.is_available() and device=='cuda' else 'cpu') self.model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=scale) self.upsampler = RealESRGANer( scale=scale, model_path=model_path, model=self.model, tile=tile, tile_pad=10, pre_pad=0, half=self.device.type != 'cpu' ) print(f'RealESRGAN 加载完毕,运行在: {self.device}') def enhance(self, img_cv2): """输入为OpenCV读取的BGR图像,返回增强后的BGR图像""" if img_cv2 is None: raise ValueError("输入图像为空") output, _ = self.upsampler.enhance(img_cv2, outscale=self.scale) return output def enhance_from_path(self, input_path, output_path): """从文件路径读取并增强,保存结果""" img = cv2.imread(input_path) if img is None: raise FileNotFoundError(f"无法读取图像: {input_path}") output = self.enhance(img) os.makedirs(os.path.dirname(output_path), exist_ok=True) cv2.imwrite(output_path, output) return output # 使用示例 upscaler = RealESRGANUpscaler(model_path='path/to/model.pth', tile=400) result = upscaler.enhance_from_path('input.jpg', 'output.jpg')

5.2 构建简单的 REST API 服务

使用 FastAPI 或 Flask,你可以快速创建一个提供超分辨率服务的 HTTP API。

# 示例:使用 FastAPI from fastapi import FastAPI, File, UploadFile, HTTPException from fastapi.responses import FileResponse import tempfile import uuid app = FastAPI() # 全局加载一次模型,避免每次请求都重复加载 upscaler = RealESRGANUpscaler(model_path='path/to/model.pth') @app.post("/upscale/") async def upscale_image(file: UploadFile = File(...)): if not file.content_type.startswith("image/"): raise HTTPException(status_code=400, detail="请上传图片文件") # 保存上传的临时文件 suffix = os.path.splitext(file.filename)[1] with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp_input: content = await file.read() tmp_input.write(content) input_path = tmp_input.name # 生成输出路径 output_filename = f"{uuid.uuid4().hex}{suffix}" output_path = os.path.join("results", output_filename) os.makedirs("results", exist_ok=True) try: # 调用超分功能 upscaler.enhance_from_path(input_path, output_path) except Exception as e: raise HTTPException(status_code=500, detail=f"图像处理失败: {str(e)}") finally: # 清理临时输入文件 os.unlink(input_path) # 返回处理后的文件 return FileResponse(output_path, media_type="image/jpeg", filename=f"enhanced_{file.filename}") # 运行: uvicorn api:app --reload

这样,前端或其他服务就可以通过发送一个 POST 请求到/upscale/端点来上传图片并获得高清结果。

5.3 内存管理与长期运行

如果你的服务需要 7x24 小时运行,处理大量图片,就必须关注内存管理。

  • 显存泄漏:在长时间批量处理后,如果发现 GPU 显存占用持续增长,可能是由于 PyTorch 的缓存没有及时释放。在批量处理的循环中,可以使用torch.cuda.empty_cache()来清理缓存。但要注意,频繁调用这个函数会影响性能。
  • 模型单例:确保RealESRGANerRealESRGANUpscaler类只被初始化一次,并在整个应用生命周期内复用。每次初始化都会加载一次模型,消耗大量时间和内存。
  • 异步处理:对于 Web API,使用异步框架(如 FastAPI)并配合ThreadPoolExecutor来处理并发请求,避免一个耗时请求阻塞整个服务。但要注意,多个线程同时调用 GPU 模型可能会造成显存竞争,需要合理控制并发数。

通过以上五个章节的拆解,我们从原理、环境、编码、排错到部署,完整地覆盖了用代码调用 RealESRGAN_x2plus 的方方面面。记住,工具是死的,人是活的。最关键的还是根据你的具体图片和需求,灵活调整参数,必要时结合其他图像处理技术,才能让这个强大的 AI 模型发挥出最大的价值。在实际操作中多尝试、多对比,你很快就能掌握让它“听话”的窍门。