尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

GFPGAN工程实战:人脸修复与超分推理全流程解析

GFPGAN工程实战:人脸修复与超分推理全流程解析 简介GFPGAN 旧照片修复算法的完整工程包面向对人工智能图像修复感兴趣的开发者、研究者及有老照片还原需求的用户。工程基于 VS2019 构建已集成必要的依赖与模型权重下载解压后即可打开运行省去繁琐的环境配置。压缩包共 445 个文件约 255.35MB主要包含 hpp/h 头文件、cpp 源文件、lib/obj 等编译产物、dll 运行库以及 param/bin 等模型参数文件结构清晰便于二次开发与学习。已有 1470 人浏览学习。通过该工程用户可直接体验人脸修复、超分辨率重建等典型流程也可基于源码深入理解 GAN 在图像增强中的实现细节是实践深度学习落地应用的优质参考。1. GFPGAN.rar 整个工程一次拆包开始的实战课拿到一个GFPGAN.rar 整个工程说是“整个工程”其实打开之后往往是一堆.py文件、几个.yaml配置、一个weights文件夹里面躺着 200MB 以上的 pth 权重还有个 README。这套东西在 AI 绘画圈子里几乎是人脸修复的默认答案GAN 生成器负责把人脸从模糊、马赛克、低分辨率拉回清晰状态同时保留身份特征不漂移。常见用途是给老照片去糊、给 AI 生成的人脸二次精修、给视频抽帧后的人脸批量提清晰度。但真正动手跑过的人都知道这个“整个工程”比想象中更容易卡住不是缺库就是版本冲突明明照着 README 写了三行代码却报RuntimeError: CUDA out of memory或者输出图片一片漆黑。这篇博文不做背诵式介绍按一线工程师拆解开源工程的习惯从压缩包落地、依赖还原、推理链路验证、参数边界、批量应用和排错这几个层次把GFPGAN.rar 整个工程背后那套东西讲透。目标是你拿到任意一份 GFPGAN 源码包能在半小时内让它跑出第一张图并且知道它为什么能跑。2. 先拆包再谈跑通rar 工程压缩包的结构与校验2.1 rar 解压不只是右键解压检查压缩包完整性与目录结构常见做法是拿到GFPGAN.rar直接右键解压到当前文件夹但这在工程场景下不够严谨。rar 在传输过程中可能截断GFPGAN 的weights目录里放着GFPGANv1.4.pth约 348MB这类大文件如果 rar 分卷或者从网盘下载时有丢包解压时可能报 CRC 错误也可能静默解出损坏的权重文件。后者更危险——文件在但模型加载后推理结果全是噪声。我一般习惯在解压前先验证完整性Windows 下可以用 WinRAR 的“测试压缩文件”功能命令行则走unrar t。Linux 下如果安装了unar也可以快速校验# 测试压缩包完整性不解压 unrar t GFPGAN.rar # 如果包内目录层级混乱先列出内容再决定解压方式 unrar lb GFPGAN.rar | head -50unrar t会逐个文件进行 CRC 校验输出All OK才说明压缩包本体没问题。unrar lb是只列出文件路径不实际解压适合先看一眼包内是不是套了一层GFPGAN-master/之类的父目录。如果套了一层直接解压后所有路径前面都会多一个父目录影响后续工作目录设置。解压本身用unrar x会保留压缩包内的目录结构unrar e则会把所有文件平铺到当前目录工程场景下不要用e模式因为 GFPGAN 有inference_gfpgan.py与gfpgan/包目录同名的风险平铺会导致 import 失败。2.2 压缩包内整个工程的标准骨架解压后先别急着跑代码先对着目录结构确认这是完整工程还是被裁剪过的“伪完整”。一份标准的 GFPGAN 工程应该包含以下部分GFPGAN/ ├── gfpgan/ # 核心 Python 包 │ ├── archs/ │ │ └── gfpganv1_arch.py # 生成器模型结构 │ ├── models/ │ ├── utils.py │ └── __init__.py ├── inference_gfpgan.py # 推理入口脚本 ├── options/ │ └── inference_gfpgan.yml # 推理参数配置 ├── weights/ # 预训练权重目录 │ ├── GFPGANv1.4.pth │ ├── GFPGANv1.3.pth │ └── detection_Resnet50_Final.pth ├── experiments/ │ └── pretrained_models/ ├── inputs/ # 默认输入图片目录 ├── results/ # 默认输出目录 ├── requirements.txt ├── setup.py └── README.md最关键的三个文件是inference_gfpgan.py、gfpgan/archs/gfpganv1_arch.py和weights/下的权重。inference_gfpgan.py是推理入口它定义了命令行参数如何映射到模型加载和推理流程。gfpganv1_arch.py定义了GFPGANv1这个 PyTorch 网络的层结构包括退化清除分支U-Net 风格与先验分支基于人脸解析图怎么融合。如果包内没有gfpgan/目录而是直接散落.py文件那说明这个 rar 是从别处拷贝的源码而非官方打包需要额外确认依赖版本。权重文件的大小也是判断完整度的直观指标GFPGANv1.4.pth一般在 300~400MB 之间如果解压出来只有几 MB多半是源文件被损坏或者是经过哈希截断的残次品不用继续尝试。3. 跑通 GFPGAN 推理链路环境、模型与第一张修复图3.1 环境搭建依赖版本踩过的三个深坑GFPGAN 的依赖不多requirements.txt里核心是torch、torchvision、opencv-python、basicsr、facexlib、gfpgan自身。但版本组合不对跑起来就各种诡异报错。我自己实践下来最容易出问题的三个点是PyTorch 与 CUDA 版本匹配。如果你机器上有 CUDA 11.8安装 torch 时如果直接pip install torch默认拿到的是 CPU 版本在部分镜像源下推理会慢得让人失去耐心。正确做法是走 PyTorch 官方索引pip install torch2.0.1 torchvision0.15.2 --index-url https://download.pytorch.org/whl/cu1182.0.1搭配cu118是与basicsr兼容性较好的组合新版本 torch 2.1 也可以跑但部分环境里会遇到basicsr内部torchvision.transforms.functional_tensor被移除导致的 import 错误不建议在新手上路阶段给自己加难度。basicsr和facexlib必须使用源码安装。GFPGAN 官方 README 里明确建议pip install basicsr -i https://pypi.org/simple和pip install facexlib -i https://pypi.org/simple但实际执行时由于依赖链中torchvision的版本约束松散可能装到与 torch 2.0 不兼容的版本。我一般会指定 GitHub 源码pip install githttps://github.com/xinntao/BasicSR.git pip install githttps://github.com/xinntao/facexlib.git这两者的源码安装会实时拉取最新代码规避 PyPI 上老版本对torchvision.models里AlexNet权重加载方式变更的适配问题。FaceXLib 的权重下载被墙或超时。第一次跑人脸检测时facexlib会尝试从 GitHub Release 下载detection_Resnet50_Final.pth约 108MB。这个下载不是通过weights/目录走而是默认缓存在~/.cache/facexlib/。如果下载失败后续会报FileNotFoundError但报错信息里不会告诉你它在下载。所以工程里如果把facexlib的权重也一并打包放进 rar就非常省事只是需要手动指定权重路径。我通常先把权重解压后放到项目根下的weights/然后设置环境变量让 FaceXLib 优先读这里export FACE_XLIB_CACHE_DIR/path/to/GFPGAN/weights/facexlib这个变量名是 facexlib 源码里实际读取的缓存根目录指向了包含detection_Resnet50_Final.pth的目录后推理时就不会再去外网下载。3.2 最小推理命令一张图从输入到输出的全流程环境就绪后跑通整个工程的最小命令如下python inference_gfpgan.py \ --upscale 2 \ --version 1.4 \ --source inputs/old_photo.jpg \ --bg_upsampler realesrgan \ --bg_tile 400 \ --suffix old_photo_restored \ --output results逐项拆解这些参数的实际作用--upscale 2超分辨率放大倍数。GFPGAN 内部默认会先做人脸检测与对齐人脸区域裁剪后送入生成器输出的高清人脸贴回原图时需要按这个倍率缩放。设为 1 时人脸区域基本只做修复不做放大背景保持原始分辨率。--version 1.4指定使用GFPGANv1.4.pth权重。v1.2、v1.3、v1.4 三版权重在训练数据与网络结构上有细微差别v1.4 是官方推荐版本对真实老照片的泛化更好v1.3 更偏合成降质数据。--bg_upsampler realesrgan背景增强器。传入realesrgan时代码会用 Real-ESRGAN 对背景非人脸区域做放大增强这对整张照片效果提升非常明显但显存消耗也会上升。如果显存紧张可以设为None表示只修脸不改背景。--bg_tile 400背景增强时 Real-ESRGAN 的分块大小。背景分辨率高时直接整图推理会爆显存分块tile把图片切成 400x400 的小块逐步推理再拼回防止 OOM。调小这个值如 200能进一步降低显存峰值但拼接痕迹会略微明显。--suffix输出文件名的后缀便于区分不同参数下的结果。--output输出目录。默认是results如果目录不存在脚本会自动创建。执行过程中STDOUT 会打印face detect的日志说明人脸检测模型已经成功加载随后打印当前检测到的人脸数量与置信度。如果输入图里没有人脸脚本会直接跳过人脸修复只对背景做超分在--bg_upsampler启用时或者直接原样输出。看到输出图里人脸没变化第一反应不应该是代码坏了而是确认原图里是否真的有人脸、人脸分辨率是否低于 GFPGAN 的可检测下限一般小于 16x16 像素的人脸检测不到。3.3 weights 何时缺失哪些情况下可以自己下载工程压缩包里如果没有weights/GFPGANv1.4.pth运行时会有非常醒目的报错FileNotFoundError: No such file or directory: weights/GFPGANv1.4.pth。这种缺失不用慌因为权重文件本身是通过开源协议发布的可以从官方 GitHub Release 自行下载然后把 pth 文件放进weights/目录即可。注意版本要与--version参数一致v1.4与v1.2的模型结构不完全一致混用会在load_state_dict时报Missing key(s) in state_dict。4. GFPGAN 的代码边界哪些参数值得动哪些是误区4.1--only_center_face、--aligned和--extensions人脸修复的控制开关inference_gfpgan.py提供了多个针对人脸处理方式的开关参数文档往往只有一句话但实际使用差别很大。参数可选值行为差异适用场景--only_center_faceFalse/TrueFalse时修复图中所有检测到的人脸True时只修复最靠近画面中心的那张脸多人合照但只想修主体人物--alignedFalse/TrueTrue时跳过人脸检测假设输入图已经是裁剪对齐后的人脸图配合人脸裁剪脚本做批处理时使用--extensions字符串列表如[jpg, png]指定输入目录下要处理的图片扩展名目录中混有.jpeg、.bmp时按需扩展以--only_center_face为例源码内部是对检测出的人脸框计算几何中心到图像中心的欧氏距离取最小值那张脸进行修复。多人合照中画面边缘的人脸即使再模糊也不会被处理。这个开关在旧照片修复场景下容易踩坑如果主体人脸不在画面中心输出结果会让人觉得“该修的脸没修”。--aligned的语义更微妙。正常推理链路中GFPGAN 会对检测到的人脸做仿射变换校准——将人脸关键点对齐到模板位置再送入网络最后把修复结果做逆变换贴回原图。--alignedTrue跳过了检测与对齐两个环节直接把输入当作对齐好的标准人脸图。所以如果你拿一张完整的老照片含背景且设置--aligned输出会是变形的、不受控的结果。4.2--bg_upsampler与--face_enhance的功能边界很多人分不清--bg_upsampler和--face_enhance的作用范围这两者的命名确实容易混淆。--bg_upsampler作用于背景非人脸区域。可传realesrgan、realersrnet或None。传None时背景不做任何处理只把人脸修复结果贴回原分辨率背景上。--face_enhance没有参数值写了就启用。它表示人脸区域先由 GFPGAN 修复再额外由一个 face enhancement 模型GPEN 或 RestoreFormer进行二次增强。从执行流程看--face_enhance生效时推理会变成两个阶段GFPGAN 修复 - 贴回原图 - 再次裁剪该人脸 - 送入增强模型 - 再次贴回。这会让单张图的处理时间翻倍甚至更久但对人脸细节毛孔、眉毛纹理有肉眼可见的提升。对于 5 年以上经验的人来说值得注意的细节是--face_enhance与--bg_upsampler realesrgan同时启用时两个模型都会占用显存一张 1920x1080 的图在 8GB 显存下容易 OOM解决办法是先把--bg_tile调低到 200 左右或者干脆先关掉--face_enhance分两步执行。4.3 常见误用把 GFPGAN 当通用超分模型用这是 GFPGAN 最有辨识度的边界。GFPGAN 不是通用超分模型它只负责把人脸区域从“有降质的人脸”变为“清晰的人脸”背景的超分来自--bg_upsampler背后的 Real-ESRGAN。如果只传--bg_upsampler None一张风景图的输出基本是原图直接复制回来。不少新手把老照片整张丢进去发现背景糊得跟输入一样就判定模型无效实际上是把两个模块的职责范围搞混了。同样GFPGAN 对输入人脸的分辨率也有限制。内部实现中检测到的人脸会先被缩放到 512x512 再送入网络。所以一张 1920x1080 的照片中人脸区域只有 40x40 像素放大到 512 后本身的底层信息已经不足以支撑高质量修复输出只能算是“脑补”细节会偏平滑。真正适合 GFPGAN 的输入人脸在原始图像中至少要有 100x100 以上像素。低于这个阈值正常做法是先走一遍 Real-ESRGAN 整体超分把脸放大到可修复范围再交给 GFPGAN。5. 批量推理与高清化配合从单张图片到真实工作流5.1 用脚本改写inference_gfpgan.py目录级批处理官方inference_gfpgan.py的--source参数虽然支持传入目录但处理逻辑较为基础遍历目录下匹配--extensions的文件逐张推理。这里有一个隐藏的限制——它不支持递归子目录。如果素材按train/class_a/xxx.jpg到train/class_z/xxx.jpg这种分类目录存放直接传--source train只能处理train/第一层的图片。常见做法是写一个小的 shell 脚本配合find展开文件列表find /path/to/inputs -type f \( -name *.jpg -o -name *.png \) | while read img; do python inference_gfpgan.py \ --upscale 2 \ --version 1.4 \ --source $img \ --bg_upsampler realesrgan \ --bg_tile 400 \ --suffix restored \ --output /path/to/results echo done: $img done逐张调用 Python 进程虽然慢但好在每张图有独立的日志输出哪张图失败能精确定位。如果要追求吞吐可以改为在 Python 内部用torch.no_grad()包住整个循环一次加载模型处理多张图这需要直接改inference_gfpgan.py的逻辑把--source目录下所有图片路径预处理后传给循环。批处理场景下最容易忽视的一点是--suffix重名覆盖。不同子目录下可能都存在photo.jpg输出到同一个results目录时会互相覆盖。解决方式是在脚本里为每个子目录单独建输出子目录或利用--suffix拼接输入文件名中的唯一特征。5.2 先超分再修复把 GFPGAN 放进两级流水线真实老照片的修复工作流中GFPGAN 很少单枪匹马出场。我一般是这样设计流水线的第一步用 Real-ESRGAN 做 2x 或 4x 整体超分把背景和前脸上采样到足够分辨率。第二步用 GFPGAN 只做人脸修复--bg_upsampler None --upscale 1避免二次超分带来的重复处理成本。第三步如果需要导入图像编辑软件里做色彩校正与瑕疵手工清理。这里的思路是GFPGAN 的修复能力在人脸区域而背景细节的恢复交给专门的超分模型两者分工。如果反过来先 GFPGAN 再超分人脸区域会被超分模型进一步涂抹GFPGAN 刚修好的脸部纹理反而被破坏。先后顺序不是随意的是一个 pipeline 顺序决定最终画质的典型例子。GPU 资源允许时--bg_upsampler realesrgan可以在一步内完成超分与修复但这要求人脸区域的原始信息占比较大。人脸在画面中占比较小时整图超分出来的背景不会特别自然。5.3 视频抽帧人脸修复的注意点视频场景下GFPGAN 的用法是ffmpeg抽帧 - 批处理 GFPGAN -ffmpeg重组视频。但这里有个实际项目里会反复出现的问题——相邻帧人脸修复结果不一致导致闪烁。GFPGAN 是单帧模型不引入时间维度的约束因此同一张脸在不同帧里可能得到略微不同的修复纹理。常见解法是把视频先做场景切分每个场景内取关键帧修复再用ffmpeg的minterpolate做光流插帧减少闪烁感。或者直接接受轻微闪烁因为对大部分档案视频人脸区域的微小闪烁远没有分辨率提升带来的观感收益明显。6. 遇到黑图、灰度图和爆显存时的定位路径6.1 RGB 顺序问题导致输出发绿发紫有人用cv2.imread自行写脚本读入图片后送进 GFPGAN输出图颜色整体偏绿或偏紫。这几乎一定是 BGR 与 RGB 通道顺序错乱导致的。inference_gfpgan.py内部使用cv2.imread读图并用cv2.cvtColor(img, cv2.COLOR_BGR2RGB)做转换生成器内部处理的是 RGB保存时再转回 BGR。如果你自己写脚本直接读图尤其用imageio或matplotlib读入拿到的就是 RGB 顺序但直接用 GFPGAN 的enhance接口最终输出会以 BGR 顺序保存颜色自然错乱。6.2 全黑输出的根源归一化方式不匹配GFPGAN 内部对人脸区域的归一化遵循 Real-ESGAN 系列的标准像素值除以 255 后映射到[-1, 1]即x x * 2 - 1。如果外部调用时只做x / 255.0而不做2x - 1的线性映射网络输入的分布与训练时不一致输出大概率是噪声或全黑图。这不是模型损坏是预处理管道问题。检查顺序是先确认输入张量归一化范围和值域分布其次才去怀疑权重文件损坏。6.3 黑屏与 OOM 的显存排查CUDA out of memory出现时先看--bg_tile。背景超分是显存消耗大户一张 4K 图直接送 Real-ESRGAN 会瞬间吃掉 6~8GB 显存。调低--bg_tile到 200 或 100峰值显存会显著下降。另外一个较少人注意的配置是torch.backends.cudnn.benchmarkGFPGAN 推理脚本里没有显式设置它但 PyTorch 默认在输入尺寸变化时会重新选择卷积算法batch 处理时多张不同分辨率的图交替输入会造成显存碎片化。可以用环境变量PYTORCH_CUDA_ALLOC_CONFexpandable_segments:True缓解实测对 GFPGAN 这种交替加载多个模型检测模型、生成器、背景超分的场景有效。6.4 验证推理结果的简单手段把中间特征图导出来当输出结果看起来没有达到预期时不要只盯最终输出图可以把archs/gfpganv1_arch.py中生成器的中间层输出导出为 numpy 数组快速判断人脸特征是否被有效提取。具体做法是在forward方法里把self.face_generator某一层的输出x用x.detach().cpu().numpy()存下来再去看它的数值分布。如果中间特征图全为常数或方差极小说明输入的人脸质量过低或归一化有问题如果特征图有明显的边缘激活说明网络前向计算正常问题出在后处理或贴回原图阶段。这比反复调整超参数更能快速定位方向。本文还有配套的精品资源点击获取
返回列表