GFPGAN人脸修复与清晰度调节:从环境配置到视频批处理

发布时间:2026/9/16 3:52:32
GFPGAN人脸修复与清晰度调节:从环境配置到视频批处理
简介基于Python实现的GFPGAN美颜与清晰度调节源码包面向计算机视觉开发者、图像美化爱好者和视频编辑人员解决人脸图片及视频帧的细节增强与人像美颜需求。资源共60个文件大小约6.23MB以Python脚本为主另有Markdown说明文档、YAML配置文件、PNG与JPG示例图片、TXT文本及MDB数据库文件等Python脚本覆盖模型架构、推理、训练、测试和多进程视频处理等模块Markdown文档则提供安装使用指南和FAQYAML配置用于调整美颜强度、清晰度等参数。已有281人学习。同时包内既有可直接运行的视频和图片美颜推理脚本也有完整的模型定义、训练与数据集退化脚本以及单元测试和预训练权重适合从源码层面学习GFPGAN在GAN图像修复和人像美化中的实际应用通过阅读文件中的README、PaperModel等文档可快速上手复现实验或基于现有代码做二次开发与优化。1. 用GFPGAN做美颜先把“清晰度”这件事想明白老照片、监控截图或者短视频里被压缩过一次的人脸往往不是单纯“模糊”而是五官轮廓被编码器揉成了一片接近皮肤颜色的色块。传统超分模型最擅长处理风景和文字一旦碰到人脸就会脑补出一张“大眼睛、尖下巴”的标准脸皮肤反而被抹成了塑料质感。GFPGAN 走的是另一条路它用 StyleGAN2 的人脸先验在生成空间里重新“画出”一张与输入最接近的高清人脸再把细节融回原图。换句话说它做的美颜不是磨皮和提亮而是把真实皮肤纹理恢复出来。对 IT 从业者来说这套方案同时覆盖了图片批处理、视频抽帧修复和超分参数调优很适合作为入门到进阶的人脸修复项目来研究。2. GFPGAN 的模型选型与“美颜/清晰度”的边界2.1 GFPGAN 真正在做的事人脸先验生成而不是超分整张图先把 GFPGAN 的处理流程拆开看它由三个独立模块组成。第一用预训练的人脸检测器 RetinaFace 从画面里把人脸区域裁出来第二把这张低质量人脸送进以 StyleGAN2 为骨干的生成网络通过隐空间编码匹配“与原图最像”的高清人脸第三把修复结果通过 alpha 融合贴回原位置背景区域则交给单独的背景增强器处理。了解这个分工有什么用它划定了能力边界GFPGAN 只负责“人脸区域的重建”整张照片的清晰度其实由背景超分模型决定。如果你拿一张全身照去做美颜人脸区域可能只占几十个像素这时候直接跑 GFPGAN 效果很差因为检测器连关键点都找不准。正确顺序是先整图放大再做人脸修复最后融合回去。另一个值得说的点是训练数据的构成。训练时模型会把高清人脸做降采样、加模糊、加噪点构成“低清到高清”的样本对。推理时模型本质上是在“清晰人脸流形”上寻找离输入最近的点所以它对被压缩算法破坏的真实人脸特别有效但如果你输入一张本来就拍糊了的普通照片它恢复出来的细节同样有限。理解这一点就能解释为什么同一套参数下老照片修复效果惊艳而随手拍的手机照片却容易产生“换脸感”。2.2 版本与配套模型怎么选v1.4 是默认v1.3 是备用GFPGAN 这个项目在社区里流传的版本很多二改发行包更是五花八门。常见做法是先固定权重文件再在推理环境里对比效果。以下是我对不同权重的使用经验。权重文件生成器配置适用场景注意点GFPGANv1.2.pthstylegan2-ffhq-512老项目兼容细节保留少肤色略“油”GFPGANv1.3.pth同上普通照片人脸修复纹理均衡色彩偏暖GFPGANv1.4.pth同上视频帧、真实退化图像边缘更干净但重建强度更高RealESRGAN_x4plus.pth背景超分整图清晰度调节与 GFPGAN 配合时 scale 建议设 2如果拿到的源码包只带了一个权重文件先用 v1.4 跑基准发现“换脸感”太重再降回 v1.3。上面表格里 RealESRGAN 虽然不出现在标题里但它是实现“清晰度调节”的关键棋子后面第 4 章会展开讲怎么和 GFPGAN 一起用。2.3 二改源码包通常会改哪三个文件市面上的源码包命名五花八门但只要是 GFPGAN 的衍生项目主流程逃不出“构造 GFPGANer - 读图 - 调用 enhance - 写图”四步。拿到任何源码包先按顺序找三个位置命令行入口脚本、核心封装模块、配置文件。命令行入口通常叫inference_gfpgan.py或predict.py这里决定了它支持批量目录、视频流还是单图。核心封装模块在官方仓库里是gfpganer.py二改包基本不碰它。配置文件一般是options/下的 yml里面藏着预训练路径、是否使用背景超分、输出尺寸这些全局参数。网上流传的“免费 python 源码大全”里这类项目特别多很多只是把这三个文件的路由改了一下真正花心思的是参数编排和批处理逻辑。判断一个源码包是否值得继续读就看命令行入口是否做了合理的异常处理和进度输出否则跑到一半崩溃都不知道从哪儿断的。3. 从零跑通Python 环境、预训练权重与最小推理脚本3.1 python安装与vscode python环境配置先从环境说起。GFPGAN 对 Python 版本不挑剔但考虑到 PyTorch 和 basicsr 的兼容性建议用 3.8 到 3.10 之间的版本。创建独立环境而不是直接装进 base因为realesrgan和basicsr对部分依赖的版本很敏感装坏了还要连带排查其他项目。conda create -n face python3.10 -y conda activate face pip install basicsr facexlib gfpgan realesrgan装完后在 vscode python 环境配置里按CtrlShiftP选择 Python: Select Interpreter指向face这个 conda 环境。这里有个容易踩的细节不要同时安装opencv-python和opencv-python-headless服务器上没显示环境时优先用 headless 版本否则 import cv2 时可能出现段错误。上述命令默认安装 CPU 版或匹配当前 CUDA 的 PyTorch如果你需要手动控制 CUDA 版本先跑nvidia-smi看驱动支持的 CUDA 版本再按官方安装命令装对应版本避免推理时出现libcudart.so找不到的报错。3.2 权重文件放哪里推理前需要先准备预训练权重。常见做法是在项目根目录下建experiments/pretrained_models/把权重文件放进去。需要两种GFPGAN 人脸的权重和背景超分的 RealESRGAN 权重。不要依赖运行时自动下载一是体积不小二是网络状态不稳定时下载失败排查起来浪费时间。我会在第一次推理前手动确认两个文件都能读文件大小和 README 里标注的一致再继续。3.3 最小推理脚本一张照片从模糊到清晰不引入任何批处理框架先写一个能跑通的最小脚本把问题范围尽量缩小。import cv2 from gfpgan import GFPGANer model_path experiments/pretrained_models/GFPGANv1.4.pth # 第一步先不挂背景超分单独验证人脸修复效果 enhancer GFPGANer( model_pathmodel_path, upscale1, # GFPGAN 内部把人脸恢复到 512x512这里不做整图放大 archclean, # v1.3/v1.4 权重对应的生成器配置 channel_multiplier2, # 生成器通道倍数固定为 2 bg_upsamplerNone, # 暂时不加载背景超分排除干扰 ) img cv2.imread(input.jpg, cv2.IMREAD_COLOR) result enhancer.enhance( img, has_alignedFalse, # 输入是普通照片需要检测器先找脸 only_center_faceFalse, # 如果有多个脸全部处理 paste_backTrue, # 修复后的人脸贴回原图 ) out_img result[-1] # 不同版本的 enhance 返回值个数不同取最后一个一定是最终图 cv2.imwrite(output.jpg, out_img)代码里有两个关键点。第一upscale1不是不放大而是 GFPGAN 只把人脸区域修复到 512×512整张图片的尺寸不变如果想输出更大尺寸需要配合背景超分或事后 resize。第二result[-1]是为了兼容不同版本对返回值的定义新版返回(cropped_faces, restored_faces, restored_img)旧版只返回两个值统一取最后一个最稳妥。archclean是官方推荐的生成器结构v1.3 和 v1.4 的权重都对应这个配置改成其他值会直接报 shape 不匹配。3.4 跑通后先看这三处脚本能输出图片只算成功了一半。第一次跑通后我会重点检查三个位置眼睛和眉毛的边界是否锐利这是 GFPGAN 最擅长的部位背景区域是否出现奇怪的涂抹感如果出现说明bg_upsampler没有被正确隔离肤色是否偏红或偏黄v1.4 偶尔会把亚洲肤色往冷白调上带出现这种情况降回 v1.3 再测。如果这三处都没问题再开始考虑并发和多帧处理。4. 把“美颜”与“清晰度”做成可调的批处理源码4.1 用 weight 控制美颜强度而不是换模型很多人第一次跑通会嫌效果“太假”皮肤光滑到失真。实际上 GFPGAN 提供了现成的强度旋钮就是enhance()方法里的weight参数。它的含义是最终输出中保留原图信息的比例权重越低修复图占比越高权重越高原图质感保留越多。参数默认值用途调参经验weight0.5原图与修复图的线性融合比例日常人像用 0.3~0.5老照片想彻底翻新用 0.7~0.9only_center_faceFalse是否只处理画面中间的人脸多人合照设 False单人格子图设 True 可提速paste_backTrue修复人脸是否贴回原图做证件照质检时设 False直接输出人脸特写upscale1构造器参数控制最终输出尺寸有背景超分时保持 1避免二次放大这里有个反直觉的经验想要“自然美颜”效果反而要把 weight 调高让更多原图细节保留下来而不是调到 0 追求完全重建。因为 GFPGAN 的重建像素是从生成空间采样出来的权重太低会把脸上原有的痣和皱纹也一并抹掉结果就是“连亲妈都不认识”。4.2 清晰度调节的真正旋钮scale、bg_upsampler 与 tile清晰度调节的核心在 RealESRGAN 背景超分上。构造RealESRGANer时有两个参数直接决定输出清晰度scale决定放大倍数tile决定处理时切块的大小。放大倍数不是越高越好视频帧一般用 2老照片翻修才用 44K 大图强行上 4 倍会让显存爆掉且背景出现伪纹理。实践中我总结出一条经验清晰度调节的顺序比参数本身更重要。先判断输入图里人脸区域占多大如果人脸宽度小于 100 像素先用背景超分把整张图放大 2 倍再送给 GFPGAN 做人脸修复。否则人脸检测器在过小的区域上定位关键点会失败最后输出一张“背景清晰、人脸依旧糊”的图。先放大再修复还是先修复再放大结果差异很大。4.3 一个可复用的批处理接口把第 3 章的最小脚本包装成一个可复用的类并加入目录批处理、异常跳过和断点记录。这类源码设计你要在 GitHub 上翻很多项目才能看到完整版这里直接给一个能抄的骨架。import argparse from pathlib import Path import cv2 import torch from gfpgan import GFPGANer from realesrgan import RealESRGANer class FaceEnhancePipeline: def __init__(self, gfpgan_path, bg_pathNone, scale2, weight0.5, tile32, halfTrue): self.bg_upsampler None if bg_path: self.bg_upsampler RealESRGANer( scalescale, # 背景放大倍数视频帧推荐 2 model_pathbg_path, tiletile, # 切块大小显存小就调成 16 tile_pad10, pre_pad0, halfhalf if torch.cuda.is_available() else False, ) self.enhancer GFPGANer( model_pathgfpgan_path, upscale1, archclean, channel_multiplier2, bg_upsamplerself.bg_upsampler, ) self.weight weight def enhance_image(self, img_path, out_path): img cv2.imread(str(img_path), cv2.IMREAD_COLOR) if img is None: return False result self.enhancer.enhance( img, has_alignedFalse, only_center_faceFalse, paste_backTrue, weightself.weight, ) cv2.imwrite(str(out_path), result[-1]) return True def run_dir(self, src_dir, out_dir, done_file): src_dir, out_dir Path(src_dir), Path(out_dir) out_dir.mkdir(parentsTrue, exist_okTrue) # 断点续传已经成功的图片记录在 done.txt跳过 done set() if Path(done_file).exists(): done set(Path(done_file).read_text().splitlines()) for img_path in sorted(src_dir.glob(*.jpg)): if img_path.name in done: continue try: if self.enhance_image(img_path, out_dir / img_path.name): with open(done_file, a) as fh: fh.write(img_path.name \n) except RuntimeError as exc: if out of memory in str(exc).lower(): torch.cuda.empty_cache() print(fskip {img_path.name}: {exc})done_file这个设计看起来不起眼但在处理几千张图片时非常实用。视频抽帧动辄几万张跑到一半断电或者显存溢出崩溃重启后能从断点继续而不是从头再来。类初始化时把bg_upsampler单独抽出来也方便单独对比“只修人脸”和“人脸背景一起超分”的效果差异。4.4 批处理时最容易忽略的编码问题批处理设置好之后还有个容易掉进去的坑是输出编码。cv2.imwrite 在写入中文路径时经常静默失败返回 False 但没有任何报错。处理前统一把路径转成纯英文或者在写文件前判断返回值。另一个坑是 jpg 的压缩质量cv2.imwrite 默认质量是 95肉眼几乎无损但如果你要拿修复结果再做二次压缩建议显式指定高质量参数避免细节还没用上就被压缩算法破坏。5. 视频处理流水线FFmpeg 抽帧、修复、合成与去闪烁5.1 三段式 FFmpeg 流水线图片批处理跑通之后视频只是换了个输入输出格式。标准做法是用 FFmpeg 抽帧Python 脚本逐帧修复FFmpeg 再把帧合成视频。不要试图用 OpenCV 的 VideoWriter 直接写视频编码参数不好控制音画同步也是麻烦。# 第一步按原始帧率抽帧保留完整帧序列 ffmpeg -i input.mp4 -vsync 0 frames/frame_%06d.png # 第二步调用第 4 章的批处理接口逐帧修复 python enhance_frames.py --src frames --out out_frames --done done.txt # 第三步把修复后帧序列合回视频并复用原始音轨 ffmpeg -r 30 -i out_frames/frame_%06d.png -i input.mp4 \ -map 0:v:0 -map 1:a:0 -c:v libx264 -crf 18 -preset medium -pix_fmt yuv420p \ -c:a copy -shortest output_hd.mp4抽帧时-vsync 0让 FFmpeg 输出全部帧而不是按固定帧率重新采样否则修复后的视频长度和原视频对不上。第三步的-r 30要根据原视频实际帧率调整可以先用ffprobe查一下。-crf 18是视觉无损的编码档位比默认的 23 更保细节-pix_fmt yuv420p保证生成文件能在一个终端上播放不转的话可能只有专业播放器能认。5.2 视频场景特有的三个坑第一个是闪烁。逐帧独立修复时检测器在每一帧检测到的人脸框位置会有一两个像素的抖动导致修复后的人脸像“果冻”一样起伏。常见做法是每 5 帧检测一次人脸框中间帧直接继承上一帧的框位置再把weight固定在一个值上不要逐帧变化。第二个是显存溢出。视频帧分辨率通常不小显存 6GB 的卡建议把tile调到 16并打开halfTrue混合精度实测能省一半显存。第三个是音画不同步通常在第三步踩到解决办法是先合视频再合音频别用-c:v copy去直接改原文件。5.3 效果验收放大细节而不是盯着整体看图片处理可以肉眼判断好与不好视频必须逐帧回放才能看出问题。我的验收方法很简单从修复后的视频里截取人脸特写帧用播放器放大到 200%看眼睛和嘴唇的边界是否干净清晰皮肤区域是否有反常的塑料光泽。然后从原视频和修复视频各截一段相同动作的片段放在同一时间轴对比重点看肤色是否稳定、人脸轮廓是否有跳动。差分检查也有用把相邻两帧做像素差如果差值集中在人脸边缘说明闪烁依旧存在如果差值均匀分布在整帧说明画面运动正常。修复效果合格的标准很简单放大看有细节连续播不闪烁。本文还有配套的精品资源点击获取