news 2026/10/2 18:16:38

GAN图像修复毕设实战:源码结构与避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
GAN图像修复毕设实战:源码结构与避坑指南

简介:一套基于深度学习的图像修复算法Python源码及配套资料,主要面向计算机视觉、人工智能等专业的毕业设计、课程设计与项目实战学习者。资源针对图像破损区域重建问题,提供了完整的模型代码、训练/推理脚本、数据集与项目说明文档,适合从入门到进阶的在校学生和开发者参考。包内共84个文件,核心代码以Python(.py)及编译缓存(.pyc)为主,辅以模型结构图、效果对比图等PNG/JPG图像,并包含C++/CUDA自定义算子、说明文档(.md/.txt)及数据集压缩包,整体大小约3.57MB。目录按模块(网络结构、数据生成、测试集等)组织,便于按需查看。目前已有253人学习下载。项目为作者高分毕业设计(评审96.5分),代码经测试运行成功,并提供使用说明与预训练模型放置指引;下载后如有运行问题可联系作者远程教学,适合需要完整可运行方案作为毕设参考或练手项目的读者。

1. 这份深度学习图像修复源码,先别急着跑 demo

拿到一份基于深度学习的图像修复算法 python 源码,大多数人第一步是装环境跑 demo,但我建议你先花二十分钟把目录结构过一遍。这个项目做的事是 GAN 图像修复:它不是简单地把破损区域涂掉,而是根据周边像素的纹理、结构和语义信息,把缺失内容重新画出来。项目里自带 Places 和 CelebA-HQ 两个标准数据集,有掩码生成脚本、CPU/GPU 双推理入口和 gradio 演示界面,适合正在做毕设、课设、期末大作业的计算机相关专业学生,也适合想完整走一遍 GAN 图像修复链路的 Python 开发者。

这类资源最容易出现的情况是:能跑通,但不知道每一步在干什么。所以我这篇不打算只讲「双击运行」,而是按我实际拆项目的顺序,先把算法栈讲清楚,再给可复现的命令、参数和避坑记录。读完之后你拿到的不是一堆 py 文件,而是一条能自己控制的修复流水线。

2. 拆开项目的骨架:GAN 图像修复的模型结构、文件清单与选型理由

2.1 从文件清单反推算法栈:dnnlib、torch_utils 与 legacy 说明了什么

打开 zip 包先看目录,我的习惯是先找dnnlib、torch_utils、legacy.py这三个东西。dnnlib和torch_utils是 StyleGAN2 生态里的标准组件,里面带着upfirdn2d.cpp、bias_act.cu、conv2d_gradfix.py这类自定义算子;legacy.py负责把旧的.pkl权重文件转换并加载。这说明整个修复模型不是随便拼的 CNN,而是基于预训练 GAN 生成器做的图像修复,网络主体大概率是 StyleGAN2 的生成器结构,修复过程依赖潜向量或特征约束来完成缺失区域的生成。

这一点对写论文很重要。评审老师看你项目说明时,最关心的不是「效果图多好看」,而是「你是否理解修复为什么有效」。基于 GAN 的修复思路和基于 U-Net 的修复思路有本质区别:U-Net 这类判别式模型擅长拟合已知到未知的映射,对大面积缺失容易产生模糊;GAN 生成器天然学过图像分布,缺失区域由分布先验和周围条件共同决定,纹理和结构更接近真实。这个项目选 GAN 路线,在毕设答辩时讲「生成先验」这个概念,比单纯报 PSNR 数字更有说服力。

再看入口文件:generate_image.py和generate_image_cpu.py分别是 GPU 和 CPU 的推理脚本,mask_generator_512.py生成 512×512 的掩码,fix_image_size.py统一图像尺寸,legacy.py负责兼容。整个流程就是:拿到一张图 → 生成掩码标记破损区 → 喂给 GAN 生成器 → 输出修复结果。pretrained目录里只放了说明.txt,而不是直接放权重文件——这点后面避坑章节要重点讲,很多人就是卡在这里。

2.2 为什么用「生成器 + 掩码 + 数据集」这套组合

图像修复本质是一个条件生成问题。给定一张带 mask 的图像,生成器需要同时做两件事:保持非 mask 区域像素不变,在 mask 区域内生成与全局语义一致的内容。如果只用 L2 损失约束,模型会选择「平均化」策略来降低误差,结果就是一片模糊;如果引入对抗损失,生成器会学会输出锐利、真实的纹理。这个项目把 GAN 生成器作为主干,掩码作为条件输入,正好对应了「先分布后细节」的修复逻辑。

数据集方面,项目带了test_sets/Places和test_sets/CelebA-HQ两个测试集,masks和images分开放。Places 是室外场景数据集,纹理复杂、结构多样,适合验证模型对大面积缺失的泛化能力;CelebA-HQ 是高清人脸数据集,人脸结构对称且先验强,修复结果更容易看出语义是否正确。两个数据集叠加,可以覆盖「场景」和「人脸」两种最常见的毕设展示场景。mask_generator_512.py生成掩码的方式是模拟笔画涂抹,这种掩码比规则矩形块更接近真实应用。

选型理由落到项目本身也很直接:这是个人毕设项目,不是工业级产品,所以方案要「效果可展示、原理可讲述、资源可复现」。StyleGAN2 生态有成熟的预训练权重加载机制,legacy.py可以直接兼容旧版 pkl,省去从头训练生成器的时间;generate_image_cpu.py的存在意味着没有 N 卡也能跑通全流程,只是慢一些。下面这个表格是我拆完目录后整理的文件角色对照,建议你保存下来,写项目说明时直接照这个逻辑组织章节。

文件/目录角色关键作用
networks/basic_module.py网络定义生成器与判别器的骨架模块
dnnlib/ torch_utils/基础设施自定义算子、权重管理、训练统计
legacy.py权重兼容加载旧版本.pkl权重文件
mask_generator_512.py掩码生成生成 512×512 的笔画式掩码
generate_image.pyGPU 推理调用生成器做图像修复
generate_image_cpu.pyCPU 推理无 GPU 环境下的推理入口
fix_image_size.py预处理统一输入图像尺寸
test_sets/测试数据Places、CelebA-HQ 的 images/masks
show_img/效果展示修复前后对比图,写文档时可用

2.3 网络结构图与 demo 图:答辩材料怎么用

项目里带了模型结构图.png、gradio演示1.png、cmd_demo.png这些展示文件。不要小看这几张图,毕设答辩时老师最常问的三句话是:网络结构是什么、数据怎么准备的、效果怎么验证。结构图直接回答第一问,demo 图回答第三问。我一般会建议把模型结构图.png重新标注一遍,把生成器、判别器、mask 输入的位置用箭头标清楚,贴在项目说明第二章。

cmd_demo.png是命令行运行截图,写使用说明时可以作为「运行结果验证」的证据。gradio演示1.png展示的是浏览器界面,说明项目带了可交互演示环境。这三类素材配合起来,就是一份完整的成果展示链:模型结构 → 命令行结果 → 交互界面。评审看到的是你不仅跑通了代码,还做了可视化封装。

3. 复现一条完整链路:环境配置、掩码生成与修复推理的参数对照

3.1 环境与依赖:requirements.txt 里的关键项

先看requirements.txt,这个文件直接决定了你能不能把环境装起来。从项目使用的库来看,核心依赖包括 PyTorch、NumPy、OpenCV 和 Gradio。目录里__pycache__同时出现了cpython-38和cpython-39,说明作者在 Python 3.8 和 3.9 上都跑过,你在这两个版本里选一个都行,我建议直接用 3.8,兼容性最稳。

装环境时我通常用虚拟环境隔离,避免把系统 Python 搅乱。常见做法是:

conda create -n inpaint python=3.8 conda activate inpaint pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install -r requirements.txt

这里--index-url指定 CUDA 11.8 版本的 PyTorch,如果你的显卡驱动只支持 CUDA 12,把cu118改成cu121再装一次。CPU 环境不需要这个参数,直接pip install torch torchvision就行。装完后跑一句python -c "import torch; print(torch.cuda.is_available())",输出True说明 GPU 可用,False也不用慌,项目提供了 CPU 推理入口,只是速度会慢一个量级。

3.2 mask_generator_512:掩码怎么生成、参数怎么调

掩码生成是整个修复流程的起点。mask_generator_512.py做的事情是模拟涂抹痕迹,在 512×512 的图上随机画白色笔触,白色区域就是要修复的地方。这类掩码叫不规则掩码,比规则矩形块更贴近真实场景——现实中照片破损、物体遮挡很少是正矩形。

核心逻辑通常长这样:

import numpy as np import cv2 def generate_mask(size=512, num_vertices=8, brush_size=12): mask = np.zeros((size, size, 3), dtype=np.uint8) points = [] for _ in range(num_vertices): points.append((np.random.randint(0, size), np.random.randint(0, size))) points = np.array(points) cv2.fillPoly(mask, [points], color=(255, 255, 255)) kernel = np.ones((brush_size, brush_size), np.uint8) mask = cv2.dilate(mask, kernel, iterations=2) return mask[:, :, 0]

这段代码先生成一个全黑掩码,再用fillPoly画一个不规则多边形,最后用膨胀操作加粗笔触,让它看起来更像真实涂抹。num_vertices控制涂抹形状的复杂度,值越大形状越不规则;brush_size控制笔触粗细,12对应 512 分辨率下大约能覆盖 2% 的区域。如果你想让破损面积更大,把num_vertices调大到 12、brush_size调到 20,生成的掩码区域会明显变大。

在这个项目里,掩码生成后要放进test_sets/Places/masks或test_sets/CelebA-HQ/masks,和images目录下的原图一一对应。文件名必须一致,否则后续加载时配对不上。我第一次跑的时候在这个环节翻过车:图叫001.png,掩码叫001_mask.png,结果掩码找不到对应原图,输出一片黑。

3.3 修复推理:generate_image_cpu / generate_image 的入口与输出

推理入口有两个文件,generate_image.py走 GPU,generate_image_cpu.py走 CPU。两者的区别本质上只在设备指定上,其余参数逻辑基本一致。GPU 版本的调用方式大概是这样:

python generate_image.py \ --network pretrained/your_model.pkl \ --image test_sets/CelebA-HQ/images/00001.png \ --mask test_sets/CelebA-HQ/masks/00001.png \ --outdir results/ \ --seed 42

拆开看每个参数:--network指向预训练权重文件,.pkl是 GAN 生态的标准权重格式,由legacy.py负责加载;--image是待修复原图路径;--mask是对应的掩码路径,白色区域会被修复;--outdir是输出目录;--seed控制随机数种子,固定后结果可复现,写论文时需要固定这个值。

CPU 版本调用方式几乎一样,只是把脚本名换成generate_image_cpu.py:

python generate_image_cpu.py \ --network pretrained/your_model.pkl \ --image test_sets/Places/images/00001.png \ --mask test_sets/Places/masks/00001.png \ --outdir results/

注意pretrained目录里目前只是说明文件。运行之前要把训练好的权重文件下载后放进去,权重文件名保持和代码里引用的一致。加载权重时legacy.py会做一次版本检查,如果报AssertionError: The network is not compatible with the current code,说明权重文件的格式和当前代码不匹配,通常需要在命令行加--legacy 1强制走兼容加载,这在老项目里是常见操作。

输出结果会写到--outdir目录,文件名一般保留原图文件名。项目里的samples目录就是用来放修复效果图的,修复好的图片会出现在这里.txt这个文件名本身就是个提示:输出路径不要乱改。

3.4 gradio 演示脚本:把修复结果拉到浏览器里看

项目里有多张gradio演示1.png、gradio演示2.png,说明作者用 Gradio 封装了可视化界面。这个封装对毕设答辩很加分——老师可以看到你上传一张破损图,界面自动返回修复结果,而不是冷冰冰的命令行输出。Gradio 脚本的核心结构通常是这样:

import gradio as gr import torch from generate_image_cpu import inpaint_single def inpaint_wrapper(image_path, mask_path): result = inpaint_single( image_path=image_path, mask_path=mask_path, network='pretrained/your_model.pkl' ) return result gr.Interface( fn=inpaint_wrapper, inputs=[gr.Image(type='filepath', label='破损图'), gr.Image(type='filepath', label='掩码图')], outputs=gr.Image(label='修复结果'), title='GAN 图像修复演示' ).launch()

gr.Image(type='filepath')会把上传的图片转成文件路径,再传给修复函数;inpaint_single是推理脚本里封装的单图修复函数,你可以把它理解成命令行参数缺省版本的封装。启动后浏览器打开http://127.0.0.1:7860,就能看到交互界面。我一般建议把演示录一段短视频,答辩 PPT 里放视频比放截图更能说明问题。

4. 在毕设项目里最容易踩的五个坑:现象、原因与解决

4.1 预训练权重放错位置:一运行就报找不到文件

现象是运行generate_image.py立刻报FileNotFoundError,提示找不到pretrained/xxx.pkl。原因很直接:zip 包里pretrained目录只有说明文本,没有实际权重文件,需要你自己下载后放进去。很多第一次拿到这个项目的人没注意下载训练好的文件放在这里.txt,直接运行,自然报错。

解决方法是先读pretrained目录下的说明文件,按里面指定的文件名和放置路径把权重放好。如果说明文件没给下载源,去项目对应社区或论文主页找同名.pkl。放进去后验证一次加载是否成功:python里执行import legacy; legacy.load_network_pkl(open('pretrained/xxx.pkl','rb')),看到网络结构输出说明加载成功。

4.2 Python 版本与 pyc 缓存冲突:同代码两种结果

项目__pycache__里同时存在cpython-38.pyc和cpython-39.pyc,这是作者先后用两个 Python 版本运行留下的。现象是你用自己的 Python 版本跑时,偶尔会报缓存文件损坏或者行为诡异的结果。原因是有时候.pyc缓存和当前解释器版本不匹配,Python 虽然会自动重新编译,但旧缓存干扰了导入路径。

解决方法是清掉整个__pycache__目录再跑,命令是find . -type d -name "__pycache__" -exec rm -rf {} +,Windows 上直接手动删。注意删缓存不影响源码,只影响编译后的字节码。从那以后我每拿到一个新项目,第一件事就是清一遍__pycache__,避免历史残留干扰。

4.3 mask 与图像尺寸对不上:修复区域整块错位

现象是生成结果里修复区域明显偏移,mask 画在左脸,修复痕迹出现在右脸。原因在于mask_generator_512.py固定生成 512×512 掩码,但测试集图像可能不是这个分辨率,而加载图像时如果做了 resize,mask 没有同步 resize,坐标就全错位了。

解决方法是先跑一遍fix_image_size.py统一所有输入图像尺寸。这个脚本的作用就是把test_sets里的图像和掩码都处理成同一尺寸。执行时注意脚本默认读目录、写目录,需要确认输入输出路径参数。如果脚本没给参数,自己写两行代码同步 resize:

import cv2 def resize_pair(image_path, mask_path, out_size=512): img = cv2.imread(image_path) mask = cv2.imread(mask_path, 0) img = cv2.resize(img, (out_size, out_size)) mask = cv2.resize(mask, (out_size, out_size), interpolation=cv2.INTER_NEAREST) return img, mask

mask 的 resize 要用INTER_NEAREST,保持掩码边缘硬边,不能出现灰度插值,否则掩码就不是纯 0/255 二值图,后续处理会出问题。

4.4 CUDA 算子编译失败:upfirdn2d 编不过去

现象是 GPU 环境下运行,报错指向upfirdn2d.cpp或bias_act.cu编译失败。原因是项目依赖的 CUDA 自定义算子需要和当前 PyTorch 版本匹配,新版本 PyTorch 改了接口,旧算子代码编不过。这种问题在新旧环境切换时非常典型。

解决办法有两个:一是把 PyTorch 版本降到项目开发时的版本,常见做法是装 1.8 或 1.9;二是切换到generate_image_cpu.py做纯 CPU 推理,绕开 CUDA 算子编译。CPU 推理慢,但至少能把流程跑通。如果毕设演示只需要几张图的效果,CPU 完全够用。

4.5 修复结果发糊或纹理重复:掩码密度与生成参数没配合

现象是修复区域像被涂抹过,没有细节纹理,或者出现重复的几何图案。原因通常不是模型坏了,而是掩码面积过大、生成器需要重建的区域太宽,已经超出了它能合理推断的范围;另一个常见原因是随机种子固定后,生成器对特定 mask 的采样结果不理想。

解决方法是先缩小掩码面积,把mask_generator_512.py里的brush_size调低,或者减少num_vertices;然后是换--seed,多跑几个随机种子选效果最好的。我的习惯是每个测试图跑三个 seed,对比后再定稿,写进论文里的结果永远是可复现的最佳值,而不是第一次运行的值。

5. 更进一步:批量修复脚本、gradio 界面与换数据集验证

5.1 一个 40 行的批量修复脚本

单图推理跑通之后,下一步通常是要批量处理测试集,用于统计修复效果。手动一条条敲命令太慢,我一般会写一个批量脚本,把测试集里所有配对好的图像和掩码扫一遍,逐个推理并保存结果:

import os import sys import glob image_dir = 'test_sets/Places/images' mask_dir = 'test_sets/Places/masks' out_dir = 'results/places' os.makedirs(out_dir, exist_ok=True) image_paths = sorted(glob.glob(os.path.join(image_dir, '*.png'))) for img_path in image_paths: name = os.path.basename(img_path) mask_path = os.path.join(mask_dir, name) if not os.path.exists(mask_path): print(f'skip {name}: mask not found') continue cmd = ( f'python generate_image_cpu.py ' f'--network pretrained/your_model.pkl ' f'--image {img_path} ' f'--mask {mask_path} ' f'--outdir {out_dir} ' f'--seed 7' ) print(f'processing {name}') os.system(cmd)

脚本逻辑不复杂:glob扫出所有原图,匹配同名掩码,缺失的直接跳过,然后用os.system调推理脚本。这里三个变量值得留意:out_dir每次跑完检查一下是否有输出,避免掩码没配对但脚本静默跳过;--seed在批量场景下固定,保证一批结果的随机性一致;mask_path用os.path.exists做存在性检查,路径写错立刻暴露。

5.2 换数据集验证模型的泛化能力

如果你有自定义数据,不要直接丢进测试集,先跑两遍流程:第一遍用fix_image_size.py把图像统一到 512×512;第二遍用mask_generator_512.py生成掩码。原图放images,掩码放masks,保持文件名一致。验证时先跑 3 张,看整体效果再决定要不要全量跑——全量跑人脸数据集比跑场景数据集耗时多,因为人脸细节对生成器的计算压力更大。

我在自己的项目里养成了一个习惯:任何模型换数据集,先过一张图看两件事——掩码区域边界清不清晰、非掩码区域有没有被改动。前者看修复能力,后者看约束能力。一个合格的修复模型应该做到掩码区完全重绘、非掩码区像素不变,如果非掩码区也变了,说明条件注入没锁住原图内容,要回头检查输入拼接逻辑。从那以后,我每次跑批处理前都强制走一遍「单图三连」:一张原图、一张掩码、一张结果,确认三者对应关系无误才敢继续。这个习惯让我省了至少十次「跑完整个测试集才发现掩码错了」的翻车事故,希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 18:16:29

大模型工程实战:从推理到RAG的系统性入门指南

1. 这份资料不是“速成课”,而是大模型时代的第一张工程地图你点开这个标题,大概率不是想听“什么是Transformer”这种教科书定义——你可能刚被老板甩来一句“下周用大模型做个智能客服原型”,也可能在技术选型会上听到同事脱口而出“RAG”“…

作者头像 李华
网站建设 2026/10/2 18:12:26

从 ALV 到智能业务界面,SAP UI Services 如何打通分析、编辑与 RAP 业务逻辑

打开 SAP 官方 abap-platform-rap200 示例项目的第六个练习,会看到一个很熟悉的开发任务,为 Travel 业务应用增加一张能够分组和汇总的表格。练习要求创建分析用的 CDS 投影视图、元数据扩展、服务定义和服务绑定,最终在 SAP Fiori 界面中展示旅行数据。对于长期使用 ABAP L…

作者头像 李华
网站建设 2026/10/2 18:10:57

大模型本地部署实战指南:从模型选型到推理框架优化

1. 为什么要折腾本地部署:先搞清楚自己到底在为什么买单这几年大模型的浪潮几乎把所有人的注意力都吸了过去,但真正上手之后你会发现,API调用和网页版聊天只是冰山一角。很多场景下,数据不能出内网、延迟要控制在毫秒级、调用次数…

作者头像 李华
网站建设 2026/10/2 18:10:40

开源油藏模拟器OPM/Flow实战:安装部署与Eclipse差异化对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/2 18:10:24

Xshell连接Ubuntu失败排查手册:SSH服务五节点验证指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华