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

资讯详情

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

深度学习老照片修复Python源码:从环境配置到Web页面实战

深度学习老照片修复Python源码:从环境配置到Web页面实战 简介基于深度学习的老照片修复项目源码面向计算机、数学、电子信息等专业学生适合作为课程设计、期末大作业或毕业设计的参考资料。压缩包共20个文件包含7个Python源码文件、3个HTML页面模板、2个pyc编译文件、2个JPG和5个PNG示例图像及1个说明文档整体仅2.1MB目录划分清晰主要涉及服务接口、图像色彩转换、模型定义与页面展示等模块无需复杂配置即可启动自带Web界面。项目调用深度学习模型自动完成老照片上色、去除污渍和划痕等修复操作用户通过浏览器上传图片即可预览修复效果前端交互简单非常适合快速搭建图像修复Demo。说明文档和工具脚本进一步帮助读者理解模型结构、数据预处理及推理流程若想二次开发需具备一定Python与深度学习基础并愿意自行调试。目前已有306人学习下载对于想钻研图像修复应用或完成课程项目的开发者是一份轻量实用的参考资源。1. 这个老照片修复项目为什么值得你花一下午跑通拿到一包祖辈留下的老照片扫描件时最先想做的事不是研究论文而是让那些划痕、霉点、模糊的五官快点“活”过来。这是“基于深度学习的老照片修复python源码自带web页面超级简单”这类项目最常见的诉求用一个训练好的模型把老照片变成清晰、干净、五官可辨认的样子再套一个Web页面让不懂命令行的人也能上传图片直接看结果。整个项目说穿了是一套图像复原流程的封装深度学习模型负责干活Python脚本负责调度Web页面负责把上传、等待、下载这几个动作做成傻瓜式操作。这类“深度学习实战项目案例”式的源码包适合三类人手里有大量老照片要修复的个人、做历史影像数字化的从业者、想跑通一个完整图像生成落地流程的开发者。一个反直觉的事实是这类项目里模型几乎都是现成的不需要你训练整个流程里最花时间的反而是把Python环境、模型权重、Web依赖这三样东西理顺。这篇文章就按这个顺序把跑通它需要的每一步和最容易翻车的坑位讲清楚。2. 修复在修什么老照片的三类损伤与模型分工2.1 先给老照片的“脏”分个类混合损伤为什么让传统算法失效老照片扫描出来的问题从来不是单一的。拿一张上世纪七十年代的全家福来说画面上同时存在几十道白色划痕是物理损伤导致像素信息完全丢失密密麻麻的颗粒噪点来自胶片乳剂老化整体模糊因为原片分辨率本来就低还有一层黄褐色的偏色。这就是老照片修复和普通图像美化的本质区别——它处理的是混合损伤不是单一噪声。传统图像复原方法对每一种损伤都有一招专门对策中值滤波去椒盐噪声维纳滤波去模糊CLAHE提升对比度。但问题在于老照片的损伤是叠加的而且处理顺序会影响最终效果。你先把划痕当你处理掉再去噪时又抻淡了边缘你先全局锐化划痕反而变得更刺眼。传统方法每一招都只对一种损伤有效对“又划痕又噪声又低分辨率”的混合状态根本找不到一个统一的数学模型。深度学习的思路完全不同。CNN在大量干净照片上学到了“一张正常的照片应该长什么样”修复的过程本质上是用学到的先验去推断缺失的信息。它的多尺度感受野能同时看见纹理和结构不会把噪声和细节搞混所以对这种混合损伤反而比单一损伤好处理——因为图像里没被破坏的部分提供了更多约束信息。这也是为什么“基于深度学习的老照片修复”能替代传统滤镜成为主流做法的根本原因。2.2 三个子任务结构修复、超分辨率、人脸增强老照片修复听起来是一件事落到模型上其实是三个子任务每个子任务对应一种网络结构的选择。第一个子任务是结构修复解决划痕、霉斑、折痕这类“像素直接缺失”的损伤。这种问题在计算机视觉里叫 inpainting模型要做的不是模糊掉伤痕而是根据周围的纹理、边缘走向把缺失的结构“长”回来。第二个子任务是超分辨率重建老照片原片分辨率普遍低扫描后放大就会模糊需要用生成式模型补充高频细节。第三个子任务是人脸增强这是老照片修复里最特殊的一环——观众看老照片时第一眼一定看人脸而人脸对细节的要求远高于背景通用修复模型修出来的脸常常是“虽然干净但认不出是谁”必须单独处理。子任务对应技术方向典型模型关注点划痕/噪点去除图像修复InpaintingBringing Old Photos Back to Life、VAE类生成网络结构连续性低分辨率放大超分辨率Super-ResolutionReal-ESRGAN 等GAN类SR模型高频细节真实感人脸增强人脸复原Face RestorationGFPGAN 等身份一致性这里要澄清一个常见误解老照片修复不是美颜。美颜是磨皮把皮肤细节抹掉让脸看起来“光滑”修复则是要把模糊的五官重建出符合这个人的结构。美颜是掩盖修复是重建两者对细节的处理方向完全相反。2.3 模型怎么拼成一个完整方案级联链路与预训练权重没有一个模型能同时把三个子任务都做到最好所以这类源码包的典型做法是级联先用一个主修复网络处理划痕和噪声再交给超分模型放大并补细节最后单独检测人脸区域做增强再把处理后的脸贴回原图。其中人脸增强这步最特殊它不会在整张图上直接跑而是先做一次人脸检测把脸部的裁剪出来单独送进增强网络处理完再按原坐标贴回。这么做是因为人脸增强网络的输入尺寸有限整图送入时小脸区域只有几十个像素效果远不如裁剪放大后单独处理。需要明确的是这类源码包里模型通常只有预训练权重没有完整的训练数据和训练脚本。你拿到手的是一个训练好的“黑匣子”权重文件可能几十MB到几百MB最常见的三种是主修复模型、超分模型、人脸增强模型。下载源码后第一件事不是看代码而是确认权重文件是否齐全这直接决定了你能不能跑起来。2.4 “Python源码Web页面”这层包装解决了什么问题命令行工具对普通人来说是灾难。你让一个档案馆的老师输一长串python infer.py --input xx --output xx --bigsize即使他能复制粘贴遇到一次报错就卡住了。所以这类项目几乎都把交互封装成Web页面最常见的两种实现一种是Flask自己写HTML模板、表单上传、图片回显灵活但代码量大另一种是Gradio几行代码生成一个带上传框、滑杆、对比展示的网页开发成本低得多也更符合标题里“超级简单”的定位。从项目结构上看这类源码包的典型布局是入口脚本webui.py 或 app.py负责启动Web服务核心推理代码在另一个模块里weights或models目录放权重requirements.txt列出Python依赖。Web层只干一件事把上传的图片存到临时目录调用核心推理函数把结果回传浏览器。理解了这个分层排错时就能快速定位问题是出在前端、后端还是模型推理上。3. 跑通源码的完整路径环境、权重、Web页面与参数调整3.1 环境准备Python版本与PyTorch安装是两个最大的坑先说明一件事不要用最新的Python除非你想给依赖的编译报错陪跑一下午。这类老照片修复项目依赖的深度学习库很多二进制包只发布到Python 3.8到3.10用3.11以上版本很容易遇到“找不到预编译wheel进入源码编译”的尴尬编译失败就卡死了。我一般固定用3.9这是兼容性最稳的版本。# 用conda建一个独立环境避免和已有环境互相污染 conda create -n photo python3.9 -y conda activate photo python --version这里-n photo是环境名你可以改成任意名字python3.9指定解释器版本不要省略。建独立环境的目的是让项目的依赖互相隔离某个包版本冲突时直接删环境重建就行不用动系统Python。接下来装PyTorch这是整个流程里最容易出问题的依赖。先确认你的机器有无NVIDIA显卡再选择对应版本# 有N卡Linux下常见装法CUDA 11.8 版本 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 没有N卡或不想用GPU装CPU版慢但能跑 pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu--index-url参数指定了PyTorch官方的whl仓库cu118后缀代表这个版本配套CUDA 11.8。如果你的机器已经装了CUDA先执行nvidia-smi看右上角的CUDA版本再决定选 cu117 还是 cu118。国内网络下载官方源慢的话可以把--index-url换掉或者直接走IPython镜像站。装完务必验证一次python -c import torch; print(torch.__version__, torch.cuda.is_available())torch.cuda.is_available()输出True才说明GPU可用输出False也不影响功能但修复速度会慢一个数量级。这里花五分钟确认能省下后面排查OOM问题时的半天时间。3.2 模型权重下载最容易被卡住的一步源码包解压后先别急着装依赖跑启动命令先检查weights/或models/目录下有没有 .pth 或 .pkl 文件。这类项目有个非常普遍的做法源码和权重分开存放压缩包里只有代码权重需要单独下载或者权重文件太大打包时被压缩软件截断了。你可以用ls -lh查看文件大小再和README里写的预期大小对比差太多说明下载不完整。# 从发布页或README指出的地址下载权重-C - 支持断点续传 curl -L -C - -o weights/photo_restore.pth https://example.com/weights/photo_restore.pth # 解压前先看目录结构和文件大小确认没有缺失 ls -lh weights/-o指定保存路径和文件名一定要和代码里加载时写的名字一致错一个字符都会报“找不到权重”-C -让中断的下载能从断点继续这个参数是血泪经验权重文件动辄几百MB下载中断是常态。权重文件放置位置以每个项目的README为准常见位置有三个项目根目录下的weights/、models/、或者checkpoints/。有的项目还会在启动时自动下载权重第一次运行会在终端打印下载进度这种情况你要盯紧了下载失败程序不会重试只会直接退出。3.3 启动Web页面最小命令与第一次修复依赖和权重都就位后安装剩余依赖并启动Web服务# 安装项目声明的所有Python依赖国内推荐用镜像源加速 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple # 启动入口以项目实际文件名为准常见是webui.py、app.py、run.py python webui.py-i参数指定PyPI镜像requirements.txt里是项目运行需要的所有依赖包括torch、torchvision、opencv、gradio、flask等。入口文件名决定权在项目本身解压后看一眼根目录有哪些.py文件就能判断别死记我这里的例子。启动成功后终端会打印一行本地访问地址Gradio封装的默认是http://127.0.0.1:7860。用浏览器打开页面上通常有一个图片上传区域和若干参数选项上传一张老照片扫描件点击修复等模型推理完成页面会并排显示修复前和修复后的效果提供下载按钮。整个过程不需要写一行代码这就是标题里“超级简单”的具体含义。如果你的项目刚好就是Gradio封装的整个Web层最核心的代码长这样import gradio as gr def restore(image, scale, face_enhance): # 内部调用项目的修复核心函数传入界面参数 return pipeline(image, scalescale, face_enhanceface_enhance) demo gr.Interface( fnrestore, inputs[ gr.Image(typepil, label上传老照片), gr.Slider(1, 4, value2, step1, label放大倍数), gr.Checkbox(valueTrue, label人脸增强), ], outputsgr.Image(typepil, label修复结果), title老照片修复, ) demo.launch(server_name0.0.0.0, server_port7860)inputs列表里的每个组件按顺序映射到fn函数的参数gr.Slider的value2是默认放大倍数step1让滑杆每次只走整数demo.launch里server_name0.0.0.0允许局域网内其他设备访问server_port指定端口这个参数在默认端口被占用时很重要改一下就能解决打不开页面的问题。3.4 影响修复效果的4个关键参数修复效果不是靠模型是靠参数调出来的。这类项目的Web页面上一般有这几个能改的东西参数常见默认作用翻车表现放大倍数 scale2对修复结果做超分辨率放大的倍数调4倍后显存溢出或生成塑料纹理人脸增强 face_enhance开启是否对人脸区域单独做五官增强小脸、多人合影时修成“陌生人”长边限制 max_size1500输入图像超长边后是否等比压缩不开的话大图直接OOM修复强度 denoise/sigma模型默认控制去噪力度调太强会抹掉皱纹等真实细节放大倍数建议固定用2。老照片本身信息量有限4倍放大并不能凭空生成更多真实细节只会让模型幻觉出纹理同时GPU显存消耗成倍上涨。人脸增强建议分情况单人正面照、五官清晰的开启效果很好多人合影、侧脸、脸部占比很小的宁可不开避免模型把人脸“脑补”成另一个人。长边限制是个避免崩溃的保险源码包里一般有默认值没有的话手动在代码里加一行缩放逻辑。3.5 单张图片在代码里经历了什么明白了参数再看一眼核心推理代码就知道Web页面背后在干什么import torch from PIL import Image import torchvision.transforms as T img Image.open(old_photo.jpg).convert(RGB) img img.resize((min(img.width, 1500), min(img.height, 1500))) # 限制长边防止OOM tensor T.ToTensor()(img).unsqueeze(0).to(cuda) model.load_state_dict(torch.load(weights/photo_restore.pth)) with torch.no_grad(): out_tensor model(tensor) result T.ToPILImage()(out_tensor.squeeze(0).cpu()) result.save(restored.jpg).convert(RGB)是为了丢弃老照片扫描件可能带有的Alpha通道统一成三通道T.ToTensor()会把0到255的像素值归一化到0到1并且自动把形状变成(C, H, W)unsqueeze(0)增加batch维度因为模型期望输入是四维张量to(cuda)把数据搬到显卡如果没有GPU改成cpu。torch.no_grad()必须加推理模式下不需要计算梯度不加会白白多占一份显存大图很容易直接爆掉。这段代码是这类项目里的通用模板不同的只是模型类和权重路径。跑通Web页面后留着这段逻辑下一章的批量处理脚本就从这里改。4. 避坑跑老照片修复最容易翻车的5个位置4.1 模型权重下载不完整运行时直接报错现象启动命令执行后终端报FileNotFoundError或KeyError提示找不到.pth文件或加载权重时键名对不上。原因这类项目的源码和权重是分开发布的你下载的源码包只有代码权重文件需要单独获取。很多人的操作是直接从网盘拖了一个没下完的文件放进去或者文件名少了一个下划线导致PyTorch加载时找不到对应条目的键名。解决先解压源码找到weights/或models/目录对照README里写明的文件名逐一比对下载时用curl -L -C -或带断点续传的下载工具下载完成后立即ls -lh看大小和README里的预期值对比差别超过几十MB基本就是下断了重新下别心存侥幸。4.2 上传稍大的扫描件就报 torch.cuda.OutOfMemoryError现象上传一张普通尺寸照片没问题换成那种扫描仪的5000×4000大图点击修复后界面卡住终端刷出显存不足的报错。原因模型本身在GPU显存里占了一块输入图长边超过2000像素时中间特征图的显存占用量随分辨率非线性上涨把剩余显存挤爆了。不是你的卡不行是输入尺寸超出了模型门槛。解决在代码里对输入做长边限制比如max_size1500超过就等比缩放关闭人脸增强分支这个分支会额外加载一个人脸检测和一个增强网络各占几百MB显存进阶方案是把模型切到半精度推理在加载权重后加model.half()输入张量也.half()显存立刻减半效果肉眼看不太出差别。4.3 import阶段报 No module named torchvision / facexlib现象启动脚本时直接报ModuleNotFoundError连Web界面都没起来。原因requirements.txt没装全或者当时用的Python版本太新某些依赖包没有对应版本pip跳过了一部分。这里面最典型的是torchvision和torch版本不配套直接装torchvision时pip自动给你升级了torch然后另一段代码用的API在新版本里改了名。解决确认Python版本在3.8到3.10之间先装torch再装requirements并且检查版本匹配python -c import torch, torchvision; print(torch.__version__, torchvision.__version__) pip list | grep -i -E facexlib|gfpgan|realesrgan如果发现某个包缺失单独补装pip install facexlib或pip install gfpgan别重复跑整份requirements把其他依赖搞乱。4.4 人脸增强开得太猛修出来像“另一个人”现象背景和服装修复得很自然唯独脸上的五官变成了另外一个人或者出现那种说不出的“塑料感”——皮肤光滑得像橡胶眼睛没有高光。原因人脸增强网络本质上是一个生成模型它看到低分辨率的人脸时不是在做“修复”而是在做“生成”——用训练集里学到的平均脸来填补缺失的信息。脸部越小、越模糊生成成分占比越高结果就是“脑补”出来的脸和照片本人越差越远。解决多人合影、脸部占比小的照片直接关闭人脸增强开关如果项目支持强度参数把增强强度降到0.5以下。我自己的习惯是先关人脸增强跑一遍看整体修复效果再开起来单独对比脸部区域如果两版脸都已经认不出来了果断保持关闭状态。4.5 Web页面打不开或上传后一直转圈现象启动命令执行后页面访问不了或者上传图片后界面一直显示加载中十几分钟不出结果。原因浏览器访问不了多半是端口被改了或者被其他进程占用上传后转圈不走通常是模型还在加载或者推理线程被前面的请求阻塞Gradio默认是多线程处理但某些Flask封装只开了单进程。还有可能是上一次运行残留的进程占着GPU显存新进程加载模型时直接OOM表现在界面上就是转圈。解决启动日志里查看打印的本地地址server_port被占用就换一个比如demo.launch(server_port7861)上传前先确认终端日志里已经打印“模型加载完成”nvidia-smi查看显存占用有残留进程就kill掉再重启。记住一点Web页面的任何卡死都要回头看终端输出的日志错误信息一定在那里。5. 进阶玩法从单张上传到批量修复流水线修一张照片照看效果满意后你面对的通常是几十张一盒子的老照片。这时一张张点网页上传、下载、保存效率太低了我一般写个小脚本把核心推理函数直接串成批量处理from pathlib import Path src_dir Path(photos) # 放原始扫描件的文件夹 out_dir Path(restored) # 修复结果输出文件夹 out_dir.mkdir(exist_okTrue) for img_path in sorted(src_dir.glob(*.jpg)): result pipeline(img_path) # 复用项目的核心函数 out_path out_dir / f{img_path.stem}_restored.jpg result.save(out_path) print(f{img_path.name} - {out_path.name})glob(*.jpg)按后缀匹配文件stem是去掉扩展名的文件名pipeline函数直接从项目的推理脚本里import过来这样批量脚本和Web页面共用同一套参数和权重不会出现两边效果不一致的情况。注意逐张串行处理不要手动开多进程并行GAN类模型对显存敏感两个进程同时推理极易OOM。批量跑完后怎么验证效果是否达标如果你手里真的有一张同场景的清晰照片可以算PSNR峰值信噪比和SSIM结构相似性做定量对比但绝大多数老照片没有对照原图我一般用三个主观指标判放大到200%看边缘有没有锯齿或振铃纹看皮肤区域有没有被抹成一片的“水粉感”看人脸五官比例是否稳定——拿同一个人不同角度的照片对比修出来的脸应该能看出是同一个人。更细一步的做法是放弃一键修复改成“先修复划痕、再单独超分、最后人脸增强”的三级流水线每一级用一个独立脚本跑中间产物保存下来检查。这样做的代价是操作次数变多但每一步的输入输出都清晰可控遇到问题能快速定位在哪一级而不是面对一个不透明的黑匣子什么都查不了。我自己第一次跑通这类项目时就吃了人脸增强的亏——一家四口的合影开完增强全家都变成“网红脸”。后来养成的习惯是先关增强跑一遍再单独开增强做对比宁可多花几分钟也不让模型替我“决定”谁长什么样。希望这个习惯也能帮到你。本文还有配套的精品资源点击获取
返回列表