基于机器学习的敦煌壁画修复数据分析系统

基于机器学习的敦煌壁画修复数据分析系统(Python + Flask + Sklearn 全流程实战)

摘要:本文完整分享一个"AI + 文物保护"方向的数据分析系统------以敦煌莫高窟 657 幅真实破损壁画为对象,结合文物材质检测数据与环境监测数据,用机器学习预测文物劣化趋势,并自动生成科学修复方案。系统包含数据大屏、壁画档案、环境监测、劣化预测、修复方案、数字修复演示六大模块,回归模型 5 折交叉验证 R²=0.95,修复方案推荐准确率 97%。文中给出核心代码、完整实现思路,以及 4 个只有真正跑过项目才会遇到的"坑"。

演示视频 :【基于机器学习的文物修复数据分析】

源码/数据集 :我用夸克网盘给你分享了「数据集.rar」,点击链接或复制整段内容,打开「夸克APP」即可获取。

/cfbb3bcO1u😕

链接:https://pan.quark.cn/s/8071cce8fa4d

一、前言:为什么做这个选题

"AI + 文物保护"是近年计算机技术与人文领域交叉的热门方向,敦煌莫高窟正是最佳研究对象之一:

  • 病害机理明确:壁画劣化主要由可溶盐结晶(酥碱)、有机胶结物老化(起甲)、光照褪色、游客扰动等因素驱动,因子可量化、可建模;
  • 数据可得:公开数据集提供了大量真实破损壁画图像与破损掩码,环境与材质数据可依据敦煌真实气候特征参数化生成;
  • 落地价值清晰:从"监测 → 预测 → 决策"形成完整闭环,非常适合做成毕设级/课设级的综合项目。

本项目的一句话概括:结合文物材质检测数据、环境监测数据,预测文物劣化趋势,制定科学修复方案,并用 Flask 做出全部可视化。

二、技术栈与项目结构

层次 选型
语言与环境 Python 3.12(Anaconda)
Web 框架 Flask 3.x
机器学习 scikit-learn(GBM / 随机森林 / 决策树 / 线性回归)
图像处理 Pillow、scikit-image(双调和插值修复、Otsu、形态学)
数据处理 pandas、NumPy
前端可视化 ECharts 5(已本地化,离线可用)

项目结构:

复制代码
mural_repair_system/
├── app.py                 # Flask 主应用(6 页面 + 15 个 API)
├── 01_data_prepare.py     # 数据准备(图像特征提取 + 机理仿真数据)
├── 02_train_models.py     # 模型训练与评估
├── repair_knowledge.py    # 修复方案知识库(6 类劣化对应工艺)
├── damage_detector.py     # 破损自动检测模块(无监督)
├── 启动系统.bat            # 双击一键启动
├── data/                  # 生成的 CSV(档案/环境/材质/训练样本)
├── models/                # joblib 模型 + 评估指标 JSON
├── templates/             # Jinja2 页面模板
└── static/                # 样式、ECharts、修复输出图

三、数据集介绍

!这里写图1-数据集样例

数据 规模 用途
破损壁画图像 657 张(512×512,JPG) 提取褪色/裂缝/暗化等劣化特征
破损掩码 50000 个(512×512,PNG) 黑色=破损区域,统计破损率
高清壁画 trainA 871 张 数据展示
现场照片 trainB 792 张 数据展示

环境监测数据(20 窟 × 24 个月)与材质检测数据(657 条)为机理仿真数据------按敦煌真实气候参数(月均温、荒漠湿度、旺季游客量)与壁画保护文献中的地仗/颜料特性参数化生成,用于演示"环境-材质-劣化"建模范式。

四、整体技术路线

复制代码
657幅真实壁画 ──► 图像劣化特征提取(破损率/褪色/裂缝/暗化)
                          │
敦煌气候参数 ──► 环境监测仿真(温湿度/CO2/光照/游客)
                          │                          │
保护文献参数 ──► 材质检测仿真(可溶盐/pH/胶结物老化) ──► 机理合成"年劣化速率"标签
                                                     │
                              ┌──────────────────────┤
                              ▼                      ▼
                    梯度提升回归(劣化预测)    随机森林分类(风险等级)
                              │                      │
                              ▼                      ▼
                    三情景趋势外推            决策树(修复方案推荐)
                              │                      │
                              └──────► Flask + ECharts 六大可视化模块

五、核心实现详解

5.1 真实图像劣化特征提取

对每张壁画提取 4 个无量纲劣化指数(01_data_prepare.py):

python 复制代码
def extract_image_features(img_path):
    im = Image.open(img_path).convert('RGB')
    arr = np.asarray(im).astype(np.float32)
    maxc = arr.max(-1); minc = arr.min(-1)
    v = maxc / 255.0
    s = np.where(maxc > 0, (maxc - minc) / (maxc + 1e-6), 0)

    # 褪色指数: 饱和度越低褪色越严重
    fading = float(np.clip(1.0 - s.mean() / 0.45, 0, 1))
    # 暗化指数: 亮度越低暗化(烟熏/尘垢)越严重
    darkening = float(np.clip(1.0 - v.mean() / 0.55, 0, 1))
    # 裂缝密度: 灰度梯度(Sobel近似)密度
    gray = 0.299*arr[...,0] + 0.587*arr[...,1] + 0.114*arr[...,2]
    gx = np.abs(np.diff(gray, axis=1)).mean()
    gy = np.abs(np.diff(gray, axis=0)).mean()
    crack = float(np.clip((gx + gy) / 12.0, 0, 1))
    return dict(fading=fading, darkening=darkening, crack=crack)

破损率来自掩码统计(注意本数据集黑色=破损,与常见"白色=前景"约定相反,这是第一个坑,见第七节):

python 复制代码
def mask_damage_ratio(mask_path):
    m = np.asarray(Image.open(mask_path).convert('L'))
    return float((m <= 127).mean())   # 黑色=破损待修复区域

5.2 劣化机理建模:把领域知识写进标签

这是整个项目最有"含金量"的一步。文物劣化不是黑箱,保护学界有明确的机理公式,我把它显式写成多因子叠加模型:

python 复制代码
# 1) 盐害: 可溶盐 × 湿度波动交互(盐反复结晶-潮解→起甲/粉化), 主导因素
salt_term   = (m.soluble_salt / 8.0) * (e.rh_std / 6.0) * 1.15
# 2) CO2+有机胶老化: 高CO2加速动物胶降解→颜料层酥粉
co2_term    = ((e.co2 - 420) / 1200) * m.binder_aging * 0.55
# 3) 光致褪色: 照度 × 颜料不稳定度(铅丹返黑/植物颜料褪色)
light_term  = (e.lux / 150) * (1 - r.pig_stability) * 0.75
# 4) 湿度均值过高→地仗软化+微生物
rh_term     = np.clip((e.rh_mean - 35) / 35, 0, 1.5) * 0.4
# 5) 游客振动/涌入扰动
visitor_term= (e.visitors / 900) * 0.22
# 6) 年代基础劣化
age_term    = r.age_years / 6500 * 0.5

rate = np.clip(salt_term + co2_term + light_term + rh_term
             + visitor_term + age_term, 0.15, 3.2)   # %/年

为什么这样合成标签? 因为监督学习需要真值,而真实"年劣化速率"需要多年跟踪监测才能获得。按机理合成标签后,模型学到的因子权重可以和保护学常识互相印证------这比纯黑箱拟合更有说服力(第六节的特征重要性验证了这一点)。

5.3 机器学习模型训练(三模型 + 四任务)

02_train_models.py 同时对比三个回归器(5 折交叉验证):

模型 CV-R² 测试 MAE 测试 RMSE
线性回归 0.913 0.149 0.195
随机森林 0.948 0.100 0.148
梯度提升(最优) 0.953 0.094 0.135

梯度提升模型的特征重要性 Top5:

复制代码
可溶盐含量  0.481   ← 盐害主导劣化, 与保护学结论一致
CO2浓度     0.172   ← 加速胶结物老化
光照度      0.149   ← 光致褪色
月均游客量  0.102   ← 扰动因素
温度波动    0.042

这组数字就是"机理标签"的价值:模型自己"发现"盐害是首要因素,与敦煌壁画保护领域"酥碱是壁画癌症"的共识完全吻合,答辩时讲这个点非常加分。

其余两个模型:

  • 风险等级分类(Ⅰ稳定~Ⅴ危急五级):随机森林,测试准确率 72.7%,混淆矩阵显示误判全部集中在相邻等级边界(Ⅱ↔Ⅲ),这在等级型任务中属于正常现象;
  • 修复方案推荐 (6 类主导劣化类型):先用保护学规则生成标签(盐害型/起甲型/裂隙型/褪色型/脱落型/综合型),再用决策树学习,测试准确率 96.97%------证明规则逻辑高度可学习。

5.4 三情景趋势预测

用最优回归模型做反事实推演,把"环境干预决策"变成可视化对比:

python 复制代码
SCENARIOS = {
    '自然延续': dict(rh_std=1.00, co2=1.00, lux=1.00, visitors=1.05),
    '环境调控': dict(rh_std=0.65, co2=0.70, lux=0.55, visitors=0.75),  # 恒湿+限流
    '全面保护': dict(rh_std=0.45, co2=0.50, lux=0.35, visitors=0.40),  # 恒温恒湿+预约制
}

全库预测结果:自然延续 0.93%/年 → 环境调控 0.70%/年 → 全面保护 0.61%/年,即环境调控可让壁画劣化速率降低约 25%------这就是"用数据支撑保护决策"的直观呈现。

5.5 破损自动检测:把"标注准确性"做成系统功能

这是项目里最值得写进文章的严谨性环节 。我最初直接拿数据集掩码当破损标注用,后来做了三重验证,发现掩码与图像不配对:

验证方法 结果
统计检验(30 对样本) "破损区"与完好区的亮度/方差/饱和度差异全部不显著(p=0.30 / 0.07 / 0.44)
同图稳定性 同一张壁画配 10 个不同掩码,破损率从 3.5% 飘到 23.2%
视觉抽检 3/3 不吻合:掩码盖住了完好的佛像面部,真实脱落区反而没标

结论:这 5 万个掩码是通用合成掩码池(图像修复训练用),不能当逐图真值用。

于是补了一套基于图像自身证据的无监督破损检测算法 (damage_detector.py):

复制代码
线索1: LAB空间 KMeans 主色离群度 → 脱落/地仗裸露(颜色偏离颜料主色域)
线索2: 亮度异常(偏离图像中位亮度) → 烟熏霉斑(过暗) / 裸露地仗(过亮)
线索3: 低饱和度 → 灰白剥落斑块
线索4: 局部均质度 → 破损斑块内部平滑, 完好区有笔触纹理
融合: outlier×0.55 + lum_anom×0.25 + (1-s)×0.20, 再乘平滑度增强
阈值: Otsu 自适应 + 85分位下限 → 形态学开闭清理 → 去小连通域

视觉抽检结果:6 张中 4 张完全吻合真实破损位置,2 张主体吻合含少量边缘误检(主要是把图像黑边/胶片齿孔误判为破损),显著优于示例掩码:

对应地,详情页叠加图做成双模式切换:「🔍 算法检测」= 本图实际破损定位(约 1 秒);「示例掩码」= 仅作数字修复算法演示,页面上明确写了两者的语义差别。

5.6 数字修复演示(双调和插值)

调用 scikit-image 的 inpaint_biharmonic 做虚拟复原,前端做滑动条对比:

python 复制代码
from skimage.restoration import inpaint_biharmonic

im = Image.open(img_path).convert('RGB').resize((256, 256))
mk = Image.open(mask_path).convert('L').resize((256, 256))
arr = np.asarray(im).astype(float) / 255.0
mask = np.asarray(mk) <= 127          # 黑色=待修复
res = inpaint_biharmonic(arr, mask, channel_axis=-1)

实测单次修复 0.4 秒,色彩过渡自然:

注意在页面上写明:数字修复仅用于虚拟复原展示与修复效果预评估,实际物理修复须遵循"最小干预、可逆性、可识别"原则------这句话在答辩时也是加分项。

5.7 Flask 可视化系统(六大页面)

全部页面基于统一深色敦煌色系(金/朱砂/石青),ECharts 本地化零外部依赖:

页面 功能
数据大屏 / 8 统计卡 + 等级分布环形图 + 洞窟风险排行 + 环境趋势 + 修复优先级 Top10
壁画档案 /murals 657 幅全库筛选(洞窟/等级/朝代/劣化类型/关键词)+ 分页卡片流
壁画详情 /murals/<id> 破损双模式标注 + 病害雷达 + 材质检测 + 单壁画三情景预测 + 完整修复方案
环境监测 /environment 温湿度/CO₂/游客量曲线 + 洞窟横向对比 + 环境因子相关性条形图
劣化预测 /prediction 模型性能对比 + 特征重要性 + 混淆矩阵 + 交互式 10 年趋势预测
修复方案 /repair 材料清单 + 工艺时间轴 + 施工风险 + 同类型壁画统筹排期
数字修复 /inpaint 选壁画/选掩码 → 双调和插值 → 滑动条对比

修复方案知识库(repair_knowledge.py)按 6 类主导劣化类型分别编写了修复原理、材料规格(PS 高模数硅酸钾、聚醋酸乙烯乳液配比、Paraloid B72 封护等)、工序时间轴、风险禁忌与监测要求,参照《古代壁画保护修复技术规范》整理------这让"修复方案"不是随机模板,而是带领域知识的输出。

六、运行方式

bash 复制代码
# 1) 环境: Anaconda Python 3.12, 依赖均为常用库
#    flask / scikit-learn / scikit-image / pandas / numpy / pillow / joblib

# 2) 双击 启动系统.bat (或):
python app.py          # 自动打开 http://127.0.0.1:5000

# 3) 如需重新生成数据/模型(约2分钟):
python 01_data_prepare.py
python 02_train_models.py

七、踩坑记录(4 个真实 Bug)

这些是只有真正把项目跑起来才会遇到的问题,写出来比成功经验更值钱:

坑 1:掩码黑白方向反了。 常规语义分割数据集白色=前景,本数据集白色=保留区域、黑色=破损。一开始我按"白色=破损"统计,破损率高达 67%~96%,全库 657 幅壁画全部判为"危急"。修正方法:先做统计合理性检查 + 图像区域亮度交叉验证,再定方向。

坑 2:把通用掩码当配对真值。 详见 5.5 节。教训:拿到带标注的数据集,先做配对性验证(统计检验 + 同图稳定性 + 视觉抽检三重交叉),不要默认"掩码=真值"。

坑 3:<select size="14"> 填充 option 后默认不选中。 下拉列表框转多行列表框后 .value 返回空字符串,导致修复方案页"请选择壁画生成方案"卡死。修复:填充后手动 sel.selectedIndex = 0。

坑 4:JS 函数参数与内部 const 变量重名。 renderCompare(before, after) 内部又写了 const after = document.getElementById(...),语法错误导致整个 <script> 块不执行,页面完全无请求发出。定位方法:把渲染后的 JS 抠出来 node --check 一遍语法立刻暴露。排查"页面 JS 完全不执行"类问题,先做语法检查,再看网络请求。

八、总结

这个项目的完整链路是:真实图像特征提取 → 机理仿真数据构建 → 机器学习建模(回归/分类/推荐)→ 三情景决策推演 → Flask 全可视化 → 破损检测与数字修复算法。

几个可以直接写进论文/答辩的核心数据:

  • 劣化速率回归:梯度提升,5 折 CV R²=0.95,MAE 0.094
  • 特征重要性:可溶盐 48% > CO₂ 17% > 光照 15%,与保护学机理吻合
  • 修复方案推荐:97% 准确率;风险等级分类 72.7%(误判集中于相邻等级)
  • 情景推演:环境调控使平均劣化速率 0.93 → 0.70 %/年(降低约 25%)
  • 数字修复:双调和插值 0.4 秒/幅;破损检测视觉抽检 4/6 完全吻合

如果要在它的基础上继续加深,三个方向:① 检测前裁掉图像边缘黑框消除误检源;② 用人工标注的真值训练深度学习破损分割网络(U-Net/DeepLabV3);③ 接入 pix2pix 配对数据(trainA/trainB)做风格化的数字复原,替代双调和插值。

相关推荐
夕阳_醉了1 小时前
让 AI 回答“打字般”浮现:用 Vue 3 + DeepSeek 实现流式聊天
前端·vue.js·人工智能
xiaoyunxuexibiji1 小时前
供应商绩效评价体系如何建立?从评价指标到自动化考核
运维·人工智能·自动化
lucas_AI1 小时前
488 GiB 变 3.81 GiB:腾讯把视觉文档检索的索引砍掉 128 倍,精度只让了 7 分
人工智能
星川皆无恙1 小时前
基于知识图谱的百科问答系统:Django + Neo4j 与实现
人工智能·python·机器学习·自然语言处理·django·知识图谱·neo4j
Raas1001 小时前
MemT-1.0 接入设计指南:硬件核算、三方案选型与写入触发点
大数据·网络·人工智能·机器学习·数据挖掘·ai agent
金仓社区的KK1 小时前
Agent Skill 没按预期执行?用请求、调用记录和产物排查
人工智能·软件构建·ai-native
小熊美家熊猫系统1 小时前
从“科技兴商“意见看家政行业:可追溯体系的技术实现路径
大数据·科技
java1234_小锋1 小时前
MySQL 宣布正式拥抱 AI
数据库·人工智能·mysql
打工仔折腾 AI1 小时前
介入式脑机接口的跨尺度解码与闭环调控:从算法落地到后端工程实践
人工智能·后端·python·深度学习·算法·ai agent 实战