十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

壁画损伤修复实战:画线引导与GAN在muralnet中的应用

壁画损伤修复实战:画线引导与GAN在muralnet中的应用 简介本资源是一套面向计算机视觉研究者与图像修复方向初学者的壁画损伤修复实践方案聚焦于文化遗产数字化保护中的关键任务——基于画线引导的壁画图像修复。项目采用深度学习方法实现破损区域的结构重建与纹理补全适用于文物修复、古建数字化存档等实际场景。压缩包共34个文件含14个Python源码涵盖模型定义、训练/测试主流程、损失函数与评估模块、10张原始及修复效果示例图jpg/png格式、4份配置与说明文本txt/md/yml以及cfg、pyproject等工程化支持文件整体6.86MB结构清晰、开箱即用。已有296人学习下载提供完整可运行代码、预训练模型调用接口、数据集加载逻辑及典型修复结果可视化便于快速复现实验、理解画线引导机制在inpainting任务中的作用路径并支持进一步算法改进与迁移应用。 最近处理一批壁画数字化扫描图的时候又想起之前那个mural-image-inpainting项目。很多同行拿到这种项目包第一步都是跑通模型、看效果但真正落地时才发现问题一个接一个模型把裂纹补成一根生硬的亮线把人物轮廓改得面目全非或者做画线引导时根本不知道该让用户画到什么程度。这篇文章想把整套方案从数据制作、网络设计、训练推理到后处理完整拆开讲清楚。重点回答三个问题壁画损伤为什么不能直接用通用修复模型硬套画线引导图像修复到底是怎么把人的经验“灌”进模型的muralnet在实际运行中有哪些坑。如果你正在做图像修复、GAN生成或者文化遗产数字化方向这篇内容应该能帮你省下不少调试时间。1. 壁画的损伤语义与修复难点为什么通用模型会翻车1.1 从图像角度重新认识壁画损伤我们日常说“损伤”会想到裂纹、剥落、霉斑但从图像修复的角度真正影响模型的是这些损伤在像素层面呈现的类型。我习惯归纳为三类。第一类是结构性缺失比如大块颜料剥落导致人物轮廓线断裂衣纹、发丝这些关键结构直接断掉第二类是纹理性退化比如酥碱造成的表面粉化原本清晰的笔触和颗粒感消失第三类是叠加性污染比如烟熏、水渍、泥渍遮挡了底层颜色信息。这三类损伤对算法的要求完全不一样。结构性缺失需要模型有全局语义理解能力能推测出失去的那段线条应该怎么走纹理性退化要求模型能模仿壁画特有的做旧质感叠加性污染则需要先把前景污渍和底层内容分离再决定补什么颜色。一个单纯的卷积网络很难同时处理好三种情况。说实话很多通用图像修复模型在自然照片上表现确实不错人脸修复、老照片修复效果都很惊艳。但一到壁画上效果崩坏非常快。第一个原因是训练分布错位自然照片充满了车、人、房子、草地而壁画主要是线条、平涂色块和矿物颜料特有的质感模型在迁移时容易把“看过的语义”强加进壁画里偶尔甚至生成出现代社会的物件幻觉。第二个原因是损伤模式不同自然照片里的损坏区域通常较小、形状随机壁画往往是大面积剥落、长条状裂纹、颜色渐变缺失掩码形态差异巨大通用模型的感受野和注意力机制未必能覆盖。这个反差是做壁画修复时首先要认清的。1.2 传统修复算法为什么也扛不住说到传统方法很多人会想到经典的补洞算法。Criminisi样例匹配、快速行进法等在小面积、有规律纹理的区域表现还行但在壁画这种复杂结构上基本是拼凑纹理到处是“缝合感”。比如沿着一条发丝细的裂纹算法会从附近找相似块去复制一旦相似块里有笔触、衣纹等结构复制出来就完全不对。加上壁画表面有颜料不均匀的颗粒感样例块匹配很容易产生振铃和模糊。另一种传统思路是偏微分方程扩散比如基于拉普拉斯算子的方法适合小噪点、小划痕但遇到大片剥落时只会把周围颜色“糊”进去细节全丢。所以我的结论是传统算法适合做前期预处理和数据准备真正承担大面积生成任务的还得靠深度生成模型。但即便用GAN也绝不是把某一篇论文的网络结构搬过来就能用的必须有针对壁画和画线引导的设计。1.3 muralnet 想解决的到底是什么说回项目本身。muralnet的目标不是“把所有损伤全自动修好”而是搭建一套“人机协作”的修复流程算法先自动检测并标记损伤区域然后修复师通过画线的方式告诉模型破损区域的结构走向、颜色趋势和细节特征模型在这些结构线索约束下生成内容。这和现实中壁画修复师的工作方式很像——修复师不会凭空猜测而是先根据残留线条和对称性推断缺失部分的结构再动手补色。画线引导图像修复本质上就是把修复师的经验数字化成结构约束再把这个约束注入到生成模型中。为了实现这个目标项目整体拆成三个模块损伤掩码生成、画线引导接口、核心修复网络。下面我会逐一展开。2. 项目包解剖mural-image-inpainting 的数据链路与目录结构2.1 拿到 zip 后先别急着跑目录里每一块是干嘛的项目包解压后看起来不大但目录结构如果理解错后面会很痛苦。我建议先按功能划分成四块数据侧data/、模型侧models/、训练推理脚本train.py、infer.py以及配置与工具configs/、utils/。数据侧包含壁画图像、损伤掩码、画线图模型侧包含生成网络和判别网络。很多入门同学调试时会忽略configs/直接拿一个裸配置跑结果 batch size 和输入尺寸对不上报一堆维度错误。实际上模型输入尺寸、掩码类型、画线是否作为独立通道都直接受配置文件控制建议拿到项目后先花十分钟通读配置文件把它当成整个项目的“说明书”。关于输入通道这里多说一句。主干网络的输入并不是一张 RGB 图就够了而是三部分拼接原始壁画图、损伤掩码1通道、画线引导图1通道。也就是说在通道维度上输入是 5 通道后续网络先通过一个卷积层把通道数压缩。有一个容易踩的坑掩码和引导图的宽高必须与输入图严格一致否则在 DataLoader 里就会出现拼接矩阵维度不匹配而且这种错误往往只在第一个训练步才暴露光看报错提示很难定位。# 输入构造示例原图、掩码、引导线拼接 import torch img torch.randn(1, 3, 512, 512) mask torch.randint(0, 2, (1, 1, 512, 512)).float() guide torch.zeros_like(mask) x torch.cat([img, mask, guide], dim1) # 5通道2.2 数据准备壁画损伤掩码是怎么制造的数据是壁画修复项目里最费人工的部分。掩码标注的质量直接决定模型上限。项目里我采用了两条路径来制造掩码。第一条路径是人工辅助标注用鼠标或数位板在壁画图像上圈出损伤区域然后程序自动把圈选区域膨胀若干像素生成边缘过渡带。这里关键的是膨胀半径的选取太大会让掩码盖住健康区域太小则训练时模型学不到损伤边缘的过渡。我实测下来对 2000x2000 左右的壁画图掩码膨胀 6~10 像素比较合适。第二条路径是程序化掩码生成。壁画里最常见的是线状裂纹可以用随机贝塞尔曲线加高斯噪声模拟块状剥落则用随机多边形加模糊核模拟。程序化生成的好处是省人力坏处是生成的掩码边缘太“干净”跟真实损伤的毛糙程度有差距。我的做法是生成后加一层 Perlin 噪声扰动边缘让掩码更接近真实损伤。训练时还要对掩码做随机旋转、缩放、翻转让模型见过更多形态避免对固定图案产生依赖。2.3 画线引导的用户交互流程画线引导是这个项目最出彩的地方。用户打开工具后先加载原图系统把检测到的损伤区域叠加显示为半透明红色蒙版接着用户根据自己在壁画上观察到的残留结构用画笔沿轮廓或纹理走向画线比如一条断裂的衣纹、一片莲花瓣的弧线。系统把绘画轨迹离散化做一次高斯模糊形成一张宽度约 5~7 像素的结构引导图然后和掩码一起送入网络。这里有一个细节引导图对网络应该是“软约束”还是“硬约束”我的处理是只在输入时作为一层特征通道不做过硬限制。因为壁画修复需要生成的内容往往不是完全确定的如果用户画线稍微偏一点模型不应完全照着这条偏掉的线去生成而应把它当作一个结构先验。但为了防止引导线被模型忽视训练时我通过随机丢弃一部分引导线dropout策略来增强模型对引导线索的敏感度。这也意味着推理时如果用户不画线模型也能运行只是效果会更依赖自动修复分支。3. muralnet 的网络结构粗修复与精细修复的两阶段设计3.1 粗修复阶段的“内容骨架”重建muralnet 的整体结构采用两阶段生成。第一阶段是粗修复主要目标是把大块缺失区域的内容骨架补出来。输入那张 5 通道图被送入一个带膨胀卷积堆叠的编码器编码器逐步降采样到 1/8 分辨率再把特征图送入几个快速卷积块最后解码回原分辨率输出一张粗略修复图。这里有个设计取舍需要说明为什么不直接端到端一次性输出精细修复因为壁画修复问题里大范围色块和结构语义的推理与小尺度纹理细节的生成是两种能力混在一个阶段里往往相互干扰。粗修复阶段用大感受野把“这里应该是什么内容”定下来第二阶段才有条件去细化“这里应该是怎样的笔触和颜色过渡”。粗修复阶段损失函数以 L1 和感知损失为主。L1 保证像素层面的基础重建感知损失我用 VGG16 的 relu1_2 到 relu4_2 特征图保证生成结果的语义结构跟原图相似。我见过有人只加 L1结果生成出一片“平均色”边界处糊成灰色。感知损失这一项不能省。3.2 部分卷积与门控卷积让网络学会“只修补该补的地方”第二阶段是精修复这阶段最核心的设计是掩码感知机制。早期我用过普通卷积结果模型容易把掩码周围的好像素也一并破坏。后来改成部分卷积Partial Convolution结构。部分卷积的核心思路很简单在卷积计算时只对有效像素区域做加权同时对掩码进行更新让网络明白哪些地方仍是未知区域哪些地方已经被生成过。它解决了传统卷积把空洞和有效区域混为一谈的问题。比部分卷积更灵活的是门控卷积。部分卷积的掩码更新规则是手工设定的只能二值化地判断“有没有效”而门控卷积通过学习一个门控图让网络自己去决定每个位置的特征贡献权重可以在复杂边缘和半覆盖区域表现得更好。muralnet 里我在中间层用了门控卷积特别是在残差块之后添加一个可学习的门控分支相当于给特征图装了一个动态开关。用生活化类比解释部分卷积像施工围挡告诉你这块地不能踩门控卷积像智能交通信号灯会根据车流量动态放行。壁画破损边缘往往不是干净矩形而是参差不齐的自然断裂面门控卷积的动态权重对这种边缘天然更友好。3.3 注意力机制与画线特征注入全局关联从哪来有了门控卷积网络只能从局部感受野获取信息但壁画经常出现左右对称、重复纹样的特征。比如一块缺失的莲花纹可能在画面另一侧有近乎完整的同类纹样这时局部卷积很难跨越大距离拷贝特征。muralnet 在第二阶段加入了自注意力self-attention模块在 1/4 分辨率特征图上计算全局相似度让缺失区域可以参考远处完好区域的特征。具体实现上自注意力模块把特征图做三个分支卷积得到 query、key、value然后计算相似度矩阵。这个相似度矩阵的大小是 H/4 × W/4 的平方一旦输入图像分辨率过大显存会爆炸。我这里把自注意力放在 1/4 分辨率实测在单张 11G 显存显卡上输入 1024x1024 时勉强能跑再高就会 OOM。如果显存紧张可以把注意力改为局部窗口注意力或者用线性注意力近似。画线引导正是在这个注意力模块之后注入的。引导图经过两层卷积提取特征后与注意力输出特征相加再进入恢复分支。之所以放在这里是因为画线本质上也是“结构线索”它需要在全局特征已经关联起来之后再对生成结果加以修正。如果一开始就把原始画线丢给编码器容易被深浅不一的笔迹干扰颜色重建。4. 训练细节与损失函数让模型“像修复师一样思考”4.1 训练数据组织与增广别让模型背下样本壁画样本数量通常不大所以数据组织很重要。我的训练集按 7:2:1 划分成训练、验证和测试关键点是不允许把同一幅壁画的不同裁剪块放进两个集合。如果同一幅画的高清大图被切成若干块切块之间内容高度重合模型会隐式记住这些细节验证集和测试集指标会虚高等真正遇到新壁画时立刻露出马脚。增广手段里除了常规的随机翻转、旋转、色彩抖动我强烈建议加上“掩码增广”也就是同一张图、同一个真实掩码在训练时对掩码做小幅抖动比如膨胀腐蚀、平移几个像素。这能让模型对掩码边界的小误差更鲁棒。因为实际推理时自动检测的损伤掩码不可能跟标注完全一致边界一定会有偏差如果训练时掩码精确到像素推理时一遇到抖动边界效果就衰减。4.2 损失函数的“四菜一汤”我在 muralnet 里用的损失函数组合叫“四菜一汤”。四菜分别是 L1 重建损失、感知损失、对抗损失、风格损失一汤是验证损失不用在训练时而是用来做早停。具体权重我调了很久目前比较满意的一套如下损失项权重作用L1 重建损失1.0保证基础像素对齐感知损失10.0约束语义特征相似对抗损失PatchGAN1.0提升局部细节真实感风格损失120.0统一笔触和纹理质感感知损失权重为什么比 L1 高这么多简单说L1 看的是“每个像素颜色对没对上”感知损失看的是“特征层面像不像”。对壁画修复来说特征层面的“像”比逐像素的“对”重要得多。而风格损失权重更高是为了让生成区域的笔触和纹理质感尽量靠近健康区域否则颜色也许对但质感发糊、发“塑料感”一眼假。风格损失我取 VGG16 的 relu2_2、relu3_3、relu4_3 层计算生成区域和真实区域之间 Gram 矩阵的差异。对抗损失用的是 PatchGAN 判别器。判别器输入是对生成图区域和真实图区域做拼接输出一个 N×N 概率矩阵对每个小块判断真伪。PatchGAN 的好处是对显存友好同时能保留局部纹理细节。我试过用普通判别器结果生成图整体色调偏暗因为全局判别器太容易看出轮廓差异对细节监督不足。# 损失组合示意 l1 F.l1_loss(pred, target) * 1.0 percep percep_loss(pred, target) * 10.0 adv gan_loss(disc, pred, target) * 1.0 style style_loss(pred, target) * 120.0 total l1 percep adv style另外如果发现生成区域颜色与原图有整体性偏移可以在损失函数里加一个简单的直方图匹配约束但这种操作要慎用。因为如果原图本身就存在色差直方图匹配会强行拉平这种差异反而破坏壁画的历史感。4.3 评估指标与主观判断的平衡项目评估我同时看三组指标PSNR、SSIM、LPIPS。PSNR 从均方误差来对噪声敏感数值越高越好SSIM 衡量结构相似度适合判断边缘和纹理是否保留LPIPS 是感知距离数值越低越好反映人眼感知层面的相似度。但老实说对壁画修复这种任务这三个指标很多时候和肉眼观感不一致。比如模型把深色裂纹修成浅灰色PSNR 可能还不错但修复师一眼就看出不对。所以我最终评估标准是“修复师盲测”让修复师在不看原图的情况下按“可接受/不可接受”打标这个主观指标往往最能反映真实需求。5. 推理与后处理从生成结果到可交付的修复图5.1 推理时掩码的细化与过渡带处理训练结束模型跑到推理阶段很多人以为把测试图喂进去就完事了。实际上推理时的预处理和训练时不一样最容易踩坑的是掩码。自动检测得到的掩码经常有锯齿和孤立噪点如果不做细化修复结果会在边缘产生一圈明显的接痕。我的做法是先用形态学开运算去掉孤立小区域再用高斯模糊把掩码边缘软化然后将掩码的过渡带区域在最终结果中做一次 alpha 混合。也就是掩码完全为 1 的中心区域完全用生成结果掩码为 0 的区域完全用原图过渡区域按掩码权重融合。这样能避免“硬边缘”的塑料感。alpha 混合有个注意点过渡带不宜过宽否则会让结果像蒙了一层雾。我实测过渡带宽度控制在原图尺寸的 0.5%~1% 比较自然比如 2048 宽的图过渡带约 10~20 像素。5.2 色彩校正与纹理融合生成区如何“做旧”模型刚生成出来的区域颜色往往过于新鲜跟多年风化后的壁画原图摆在一起很明显。为了让生成区融入背景我通常再做两类后处理。第一是颜色域匹配把生成区像素的颜色统计量校正到与周围健康区域一致常见做法是在 Lab 空间里做均值和标准差的线性映射。这个操作很便宜效果却很明显。第二是纹理叠加在生成区域叠加上从健康区域随机采样得到的噪声纹理让表面的颗粒感一致。说白了这相当于给补好的地方做了一层“仿旧色浆”技术含量不高但能极大提升最终交付观感。颜色匹配有个细节如果壁画图像因为年代原因本身存在大范围褪色渐变就不能用整幅图的统计量而应该以生成区域附近的局部窗口为准否则会把不应存在的色调变化也拉平。我通常取生成区域外扩 30~50 像素范围的健康区域作为颜色参照。5.3 多尺度修复策略大图怎么跑壁画原图动辄几千万像素不能直接一股脑塞进网络。我采用“先缩放到模型支持的最大分辨率比如 1024x1024做一轮粗修复再在原分辨率上做一轮精修复”的策略。粗修复阶段确定结构和色调精修复阶段以固定窗口512x512滑动窗口之间加 20% 重叠区重叠区最后用线性加权融合。这里要特别提醒精修复阶段输入图最好保留原分辨率的小块不要靠拉伸放大去“硬造”细节。如果原图本身分辨率不够拉伸只能得到过度平滑的结果算法不可能凭空生成超高细节。多尺度策略的另一个好处是可以在粗修复时把用户画的引导线缩放到统一尺度精修复阶段再把引导线恢复成原分辨率这样画线引导的稳定性更高不会因为缩放导致线条粗细变化。如果用户画得很细缩放后可能完全消失这时要采取“先膨胀后缩放再腐蚀”的操作把线宽保持在至少 2 像素。6. 实测中的坑这些经验是常规文档里不会写的6.1 裂纹区域颜色发灰、发闷第一次跑完生成结果最常见的问题是修复区发灰。排查后我发现主要原因是 L1 损失权重过高。模型为了最小化平均误差倾向于生成“最稳的平均色”而壁画裂纹周围的颜色通常是亮色或暗色渐变平均下来就成了灰色。解决办法是把对抗损失的权重稍微调高同时把感知损失里的高层特征权重提高让模型更关注语义细节。如果调完还是灰可以检查一下 mask 是否把原图的健康区域也盖住了导致模型拿到了错误的重建参照。6.2 画线引导线的“过拟合”问题刚开始做画线引导时模型对用户画的线条过于敏感稍微画偏一个像素生成结果就完全偏离。研究发现是训练时引导线都太干净了模型学会了“引导线一定是精准的”。后来我在训练数据里对引导线做随机偏移、随机加宽、随机擦除让模型学会不完全依赖线条的精确位置而是把它当作一簇结构线索。换句话说要故意给引导线“找麻烦”让模型在噪声中学会提取真正的结构信息。还有一个使用层面的细节交互界面上最好把缩放比例放大到 100% 以上再让用户画线否则用户以为画的是精准结构线但在缩小的视图里偏差可能已经达到十几个像素。实测下来引导线偏离 3~5 像素以内问题不大超过 10 像素就容易出错。6.3 显存不足与批次大小壁画高分辨率输入带来的最大实际困难是显存。我一度在单卡 11G 显存上训练 1024 输入batch size 只能设为 1训练很不稳定。后来我降低生成器第一阶段的输入分辨率比如改为 640精修复阶段再提升到 1024相当于用两阶段的训练策略去换显存。batch size 为 1 时要特别注意 BatchNorm 层的表现我建议在 batch size 小于等于 2 时使用 GroupNorm 或 InstanceNorm 替代 BatchNorm否则归一化统计量波动太大模型难以收敛。6.4 自动掩码生成质量差时不如退回半人工很多同学把精力都放在模型上结果发现瓶颈其实在掩码。自动检测模型生成的掩码经常漏掉细裂纹、多框出健康区域这种数据喂给修复网络怎么调都白搭。我的建议是如果自动掩码的 IoU 低于 0.8干脆用半人工标注哪怕花一点时间也要保证掩码质量。模型再强掩码上全是洞的组合也是事倍功半。具体可以用常见的标注工具快速标注并结合形态学后处理把边缘磨平。7. 后续扩展从壁画单图修复到数字化保护工作流7.1 与摄影采集和三维纹理映射的衔接壁画修复不应该是一个孤立的单图任务。在实际工程里壁画图像往往来自多视角摄影或三维扫描的纹理贴图。我目前在做的是把多视角的一致性约束加入修复流程同一位置在不同视角下都应该修复出相似的颜色和结构而不是各修各的。实现思路是在推理时对多个视角的修复结果做一致性约束或者在训练时加入视图一致性损失。这个方向还在迭代中个人感觉比单纯堆修复网络更贴近真实文物保护需求。7.2 面向不同材质的调优不同材质的壁画修复参数差异很大。干燥岩画表面纹理粗糙风格损失权重要适当提高彩绘泥塑表面较为平滑对抗损失的权重可以高一些如果壁画存在大面积起甲掩码往往呈片状分布粗修复阶段的感受野就需要加大。建议在实际应用中把材质类型作为一个条件输入或者训练一个多专家模型不同材质用不同分支处理。这样在接手一个新项目时不用每次都从头调参。操作中我的经验是壁画修复这个项目真正难的不是把某个 GAN 网络跑通而是把“损伤语义”和“人的判断”融进管线。画线引导图像修复把修复师从“完全相信模型”里解放出来效果可以接受之后我越来越多地时间花在掩码质量和交互体验上而不是网络结构微调。如果你也在做类似项目建议先把数据、掩码、引导线这三样做扎实再回头调损失权重通常比盲目换网络结构更有效。最终修复出来的结果还是要交给懂壁画的人去判断算法在这里只是一个工具。本文还有配套的精品资源点击获取
返回列表