让 AI 理解敦煌壁画:多模态方法在文化遗产保护中的应用

让 AI 理解敦煌壁画:多模态方法在文化遗产保护中的应用
让 AI 理解敦煌壁画多模态方法在文化遗产保护中的应用一、个性化深度引言敦煌莫高窟现存壁画约 4.5 万平方米跨越十六国至元代十多个朝代。这些壁画不是静态的艺术品——它们每一年都在老化、褪色、剥落。数字化是保护的第一步高清扫描存档但仅仅是数字扫描还不够——需要让 AI 真正理解壁画的内容、风格和损坏程度才能指导保护修复的优先级。这比传统的图像分类任务复杂得多。传统分类需要的是这是什么物体壁画理解需要的是这是什么故事、属于哪个年代、用的是什么技法、褪色了多少。一个画面可能同时出现佛、菩萨、飞天、供养人、建筑、装饰纹样——每个元素都是数据库索引的关键维度。多模态方法是解决方案的关键——不仅要看画面本身还要结合考古文献题记图像中的文字、历史资料壁画对应的经文内容、以及颜料化学分析数据判断褪色原因。这篇文章记录了一次多模态方法在壁画数字化保护中的探索实践。二、个性化原理剖析敦煌壁画 AI 理解的多模态架构系统的核心设计思路是将壁画从一张图片拆解为多个维度的可检索信息。人工分类一幅壁画需要专家 2-3 小时AI 辅助后在 5 分钟内给出初步分析结果专家只需复核修正。三、个性化代码实践壁画分析多模态系统的核心实现import numpy as np import torch from dataclasses import dataclass, field from typing import List, Dict, Tuple, Optional from enum import Enum from collections import defaultdict from PIL import Image import json class Dynasty(Enum): 朝代——设计原因敦煌壁画跨越的年代 BEILIANG 北凉 BEIWEI 北魏 XIWEI 西魏 BEIZHOU 北周 SUI 隋 CHU_TANG 初唐 SHENG_TANG 盛唐 ZHONG_TANG 中唐 WAN_TANG 晚唐 WUDAI 五代 SONG 宋 XI_XIA 西夏 YUAN 元 class FigureType(Enum): 人物类型——设计原因壁画中最核心的识别目标 BUDDHA 佛 BODHISATTVA 菩萨 APSARA 飞天 DISCIPLE 弟子 DONOR 供养人 GUARDIAN 天王 KINNARA 伎乐天 ATTENDANT 侍从 class DamageType(Enum): 损毁类型——设计原因标准化损毁分类 FADING 褪色 # 颜料氧化褪色 FLAKING 剥落 # 颜料层剥落 CRACKING 龟裂 # 墙体龟裂 EFFLORESCENCE 酥碱 # 盐分析出 SMOKE 烟熏 # 香火烟熏 SCRATCH 划痕 # 人为刮划 MOLD 霉变 # 微生物侵蚀 WATER 水渍 # 渗水痕迹 dataclass class MuralTile: 壁画图块——设计原因超大图分析的基本单位 tile_id: str image: np.ndarray position: Tuple[int, int, int, int] # 在原图中的位置 x1,y1,x2,y2 objects_detected: List[Dict] field(default_factorylist) style_features: np.ndarray None damage_regions: List[Dict] field(default_factorylist) dominant_colors: List[Dict] field(default_factorylist) dataclass class MuralAnalysis: 壁画分析结果——设计原因结构化存储全部分析维度 mural_id: str cave_number: str # 洞窟编号 wall_position: str # 壁画位置主室西壁/南壁等 # 年代分析——设计原因多证据联合推断 estimated_dynasty: Optional[Dynasty] dynasty_confidence: float dynasty_evidence: List[str] field(default_factorylist) # 人物分析——设计原因统计人物类型和数量 figures: Dict[FigureType, int] field(default_factorydict) total_figures: int 0 # 场景分析——设计原因佛教经变画的主题分类 scene_type: Optional[str] None # 西方净土变/法华经变/维摩诘经变等 scene_confidence: float 0.0 # 损毁分析——设计原因修复优先级排序的基础 damage_assessment: Dict[DamageType, float] field(default_factorydict) overall_damage_score: float 0.0 # 0完好, 1严重损毁 critical_regions: List[Dict] field(default_factorylist) # 色彩分析 pigment_analysis: Dict[str, float] field(default_factorydict) fading_score: float 0.0 # 文本分析 inscriptions: List[str] field(default_factorylist) matched_scriptures: List[str] field(default_factorylist) class MuralObjectDetector: 壁画物体检测——设计原因适配古代绘画风格的检测器 FIGURE_DESCRIPTORS { FigureType.BUDDHA: [ 肉髻, 白毫, 头光, 身光, 莲花座, 袈裟, 禅定印 ], FigureType.BODHISATTVA: [ 宝冠, 璎珞, 天衣, 披帛, 手印, 净瓶, 莲华 ], FigureType.APSARA: [ 飘带, 飞舞, 天衣飘扬, 散花, 凌空, 云气, 手持乐器 ], FigureType.DONOR: [ 世俗服饰, 题记榜题, 跪姿, 持花, 持炉, 侍从, 比丘引导 ], } def detect_figures(self, tile: MuralTile) - List[Dict]: 检测人物——设计原因基于视觉特征领域知识联合判断 detections [] for figure_type, descriptors in self.FIGURE_DESCRIPTORS.items(): # 多模态检测 visual_match self._visual_match(tile.image, descriptors) text_match self._text_match(tile.image, figure_type) # 综合置信度——设计原因视觉特征和题记文本相互验证 if visual_match 0.5: confidence ( 0.7 * visual_match 0.3 * text_match ) detections.append({ type: figure_type.value, confidence: confidence, evidence: { visual: visual_match, textual: text_match } }) tile.objects_detected detections return detections def _visual_match(self, image: np.ndarray, descriptors: List[str]) - float: 视觉特征匹配——设计原因用CLIP/ViT检测领域特有特征 # 实际使用CLIP/ViT模型检测 return 0.75 # 占位 def _text_match(self, image: np.ndarray, figure_type: FigureType) - float: 题记文本匹配——设计原因壁画中常有榜题标注人物身份 # OCR提取题记与人物类型匹配 return 0.0 # 没有题记默认返回0 class DynastyClassifier: 年代分类——设计原因多维度特征联合判断 # 朝代风格特征——设计原因不同朝代的绘画风格有明显差异 DYNASTY_STYLES { Dynasty.BEILIANG: { color_palette: [土红, 青绿, 白], line_style: 铁线描, face_style: 西域风格, halo_style: 单层圆形头光, }, Dynasty.TANG: { color_palette: [石青, 石绿, 朱砂, 金粉], line_style: 兰叶描, face_style: 丰满圆润, halo_style: 多层同心圆头光, }, # ... 更多朝代特征 } def classify(self, mural: MuralAnalysis, tiles: List[MuralTile]) - Tuple[Optional[Dynasty], float]: 年代分类——设计原因综合视觉风格文字题记颜料特征 votes defaultdict(float) # 1. 风格特征匹配——设计原因最直接的年代判断依据 style_scores self._match_style(tiles) for dynasty, score in style_scores.items(): votes[dynasty] score * 0.4 # 2. 题记文字断代——设计原因纪年题记是最可靠的断代证据 for inscription in mural.inscriptions: dynasty_from_text self._parse_dynasty_from_text(inscription) if dynasty_from_text: votes[dynasty_from_text] 0.5 # 题记权重最高 # 3. 颜料成分分析——设计原因不同朝代使用的颜料不同 pigment_dynasty self._match_pigment(mural.pigment_analysis) for dynasty, score in pigment_dynasty.items(): votes[dynasty] score * 0.1 if not votes: return None, 0.0 best_dynasty max(votes, keyvotes.get) best_score votes[best_dynasty] / max(sum(votes.values()), 1.0) return best_dynasty, best_score def _match_style(self, tiles: List[MuralTile]) - Dict[Dynasty, float]: 风格特征匹配 # 实际使用风格分类模型 return {Dynasty.TANG: 0.8, Dynasty.SUI: 0.3} def _parse_dynasty_from_text(self, text: str) - Optional[Dynasty]: 从题记文字中提取年代——设计原因纪年格式如大历十一年 reign_titles { 大历: Dynasty.WAN_TANG, 贞观: Dynasty.CHU_TANG, 开元: Dynasty.SHENG_TANG, 天宝: Dynasty.SHENG_TANG, 开皇: Dynasty.SUI, 大业: Dynasty.SUI, # ... 更多年号 } import re for reign, dynasty in reign_titles.items(): if reign in text or re.search(rf{reign}\d*年, text): return dynasty return None def _match_pigment(self, pigments: Dict[str, float]) - Dict[Dynasty, float]: 颜料匹配断代——设计原因青金石(ultramarine)主要出现在唐代以后 pigment_eras { 青金石: [Dynasty.CHU_TANG, Dynasty.SHENG_TANG, Dynasty.ZHONG_TANG], 石绿: list(Dynasty), # 各朝代都有 } scores defaultdict(float) for pigment, eras in pigment_eras.items(): if pigment in pigments: for era in eras: scores[era] pigments[pigment] * 0.5 return dict(scores) class DamageAnalyzer: 损毁分析器——设计原因自动化评估壁画保存状态 def __init__(self): # 损毁严重程度权重——设计原因剥落比褪色严重 self.damage_severity { DamageType.FLAKING: 1.0, # 剥落最严重 DamageType.CRACKING: 0.8, DamageType.EFFLORESCENCE: 0.7, DamageType.MOLD: 0.6, DamageType.FADING: 0.3, # 褪色相对不紧急 DamageType.SMOKE: 0.3, DamageType.SCRATCH: 0.2, DamageType.WATER: 0.5, } def analyze(self, tiles: List[MuralTile]) - Dict[DamageType, float]: 损毁分析——设计原因逐块分析后汇总 damage_counts defaultdict(float) for tile in tiles: tile_damages self._analyze_tile(tile) for damage_type, area_ratio in tile_damages.items(): damage_counts[damage_type] area_ratio # 按瓦片数归一化——设计原因百分比便于跨壁画对比 total_tiles max(len(tiles), 1) normalized { d: count / total_tiles for d, count in damage_counts.items() } return normalized def _analyze_tile(self, tile: MuralTile) - Dict[DamageType, float]: 分析单个图块——设计原因使用语义分割模型检测损毁区域 # 使用语义分割模型检测 damages {} # 褪色检测原色区域饱和度的均值和方差 if tile.dominant_colors: avg_saturation np.mean([c.get(saturation, 1.0) for c in tile.dominant_colors]) if avg_saturation 0.3: damages[DamageType.FADING] 0.3 return damages def compute_priority(self, damage_scores: Dict[DamageType, float]) - float: 计算修复优先级——设计原因加权综合评分 weighted_sum 0.0 total_weight 0.0 for damage_type, area in damage_scores.items(): weight self.damage_severity.get(damage_type, 0.5) weighted_sum area * weight total_weight weight if total_weight 0: return 0.0 return weighted_sum / total_weight def identify_critical_regions(self, tiles: List[MuralTile]) - List[Dict]: 标记紧急修复区域——设计原因自动标注最需关注的区域 critical [] for tile in tiles: tile_damages self._analyze_tile(tile) # 剥落和龟裂需要紧急修复 urgent_types [DamageType.FLAKING, DamageType.CRACKING] urgent_area sum( tile_damages.get(d, 0) for d in urgent_types ) if urgent_area 0.2: # 超过20%面积 critical.append({ tile_id: tile.tile_id, position: tile.position, damage_types: [ d.value for d in urgent_types if d in tile_damages ], severity: urgent_area }) # 按严重程度排序 critical.sort(keylambda x: x[severity], reverseTrue) return critical[:10] # Top-10最紧急区域 class VirtualRestorer: 虚拟修复——设计原因推测壁画褪色前原貌 def __init__(self): # 颜色参考数据——设计原因基于未褪色区域的颜料样本 self.color_reference {} def restore_fading(self, tile: MuralTile) - np.ndarray: 褪色修复——设计原因基于颜料成分和周围未褪色区域推断原色 image tile.image.copy() if tile.dominant_colors: for color_info in tile.dominant_colors: # 如果该颜色的饱和度偏低——设计原因饱和度降低是褪色的主要表现 if color_info.get(saturation, 1.0) 0.4: # 提升饱和度至推测的原色 restored self._enhance_color( image, color_info[hue], target_saturationcolor_info.get(original_saturation, 0.8) ) image restored return image def _enhance_color(self, image: np.ndarray, hue: float, target_saturation: float) - np.ndarray: 颜色增强——设计原因HSV空间操作饱和度 hsv cv2.cvtColor(image, cv2.COLOR_BGR2HSV).astype(np.float32) # 找到对应色相的区域——设计原因只调整目标颜色不影响其他颜色 hue_mask np.abs(hsv[:, :, 0] - hue) 10 hue_mask hue_mask (hsv[:, :, 1] 0) # 排除无彩色区域 # 提升饱和度 hsv[:, :, 1][hue_mask] np.clip( hsv[:, :, 1][hue_mask] * (target_saturation / max(hsv[:, :, 1][hue_mask].mean(), 0.01)), 0, 255 ) return cv2.cvtColor(hsv.astype(np.uint8), cv2.COLOR_HSV2BGR) def generate_restoration_report(self, mural: MuralAnalysis, tiles: List[MuralTile]) - Dict: 生成修复建议报告——设计原因综合评估优先级修复方案 # 损毁分析 analyzer DamageAnalyzer() damages analyzer.analyze(tiles) priority analyzer.compute_priority(damages) critical analyzer.identify_critical_regions(tiles) # 修复建议——设计原因不同损毁类型用不同修复策略 recommendations [] if damages.get(DamageType.FLAKING, 0) 0.1: recommendations.append({ type: 剥落修复, method: 注射丙烯酸树脂加固, area_pct: round(damages[DamageType.FLAKING] * 100, 1), urgency: 高 }) if damages.get(DamageType.FADING, 0) 0.3: recommendations.append({ type: 虚拟复原, method: 基于颜料样本的色度重建, area_pct: round(damages[DamageType.FADING] * 100, 1), urgency: 低 }) if damages.get(DamageType.EFFLORESCENCE, 0) 0.05: recommendations.append({ type: 酥碱治理, method: 氯化物去除环境湿度控制, area_pct: round(damages[DamageType.EFFLORESCENCE] * 100, 1), urgency: 高 }) return { mural_id: mural.mural_id, overall_damage_score: round(priority, 3), damage_details: { d.value: round(v, 3) for d, v in damages.items() if v 0 }, critical_regions: len(critical), repair_recommendations: recommendations, estimated_repair_duration: self._estimate_duration(critical) } def _estimate_duration(self, critical_regions: List[Dict]) - str: 估算修复时长——设计原因帮助制定保护计划 if len(critical_regions) 0: return 无需立即修复 elif len(critical_regions) 5: return 约1-2周 elif len(critical_regions) 15: return 约1个月 else: return 需要2个月以上 class MuralKnowledgeGraph: 壁画知识图谱——设计原因结构化存储壁画多维信息 def __init__(self): self.nodes: Dict[str, Dict] {} self.edges: List[Tuple[str, str, str]] [] # (from, to, relation) def add_mural(self, analysis: MuralAnalysis): 添加壁画节点——设计原因壁画是知识图谱的核心实体 node_id analysis.mural_id self.nodes[node_id] { type: mural, cave: analysis.cave_number, position: analysis.wall_position, dynasty: analysis.estimated_dynasty.value if analysis.estimated_dynasty else 未知, scene: analysis.scene_type or 未识别, total_figures: analysis.total_figures, damage_score: analysis.overall_damage_score } # 人物关联 for figure_type, count in analysis.figures.items(): if count 0: figure_node ffigure_{figure_type.value} if figure_node not in self.nodes: self.nodes[figure_node] { type: figure, name: figure_type.value } self.edges.append((node_id, figure_node, contains)) def query_by_dynasty(self, dynasty: Dynasty) - List[str]: 按朝代查询——设计原因最常见的检索维度 return [ node_id for node_id, node in self.nodes.items() if node.get(type) mural and node.get(dynasty) dynasty.value ] def query_by_figure(self, figure_type: FigureType) - List[str]: 按人物类型查询——设计原因专家研究特定人物的演变 results [] for from_node, to_node, relation in self.edges: if relation contains and figure_type.value in to_node: results.append(from_node) return results def query_by_scene(self, scene_type: str) - List[str]: 按场景查询——设计原因经变画的比较研究 return [ node_id for node_id, node in self.nodes.items() if node.get(type) mural and node.get(scene) scene_type ] class DunhuangMuralSystem: 敦煌壁画分析系统——设计原因端到端的壁画分析 def __init__(self): self.detector MuralObjectDetector() self.classifier DynastyClassifier() self.restorer VirtualRestorer() self.knowledge_graph MuralKnowledgeGraph() def analyze_mural(self, mural_id: str, cave_number: str, wall_position: str, image_path: str, inscriptions: List[str] None) - Dict: 完整壁画分析——设计原因多维度并行分析 # 初始化分析对象 analysis MuralAnalysis( mural_idmural_id, cave_numbercave_number, wall_positionwall_position, estimated_dynastyNone, dynasty_confidence0.0, inscriptionsinscriptions or [] ) # 1. 图像分块——设计原因超大图必须分块处理 image Image.open(image_path) tiles self._split_image(image) # 2. 人物检测——设计原因统计各类人物数量 for tile in tiles: self.detector.detect_figures(tile) # 汇总人物统计 figure_counts defaultdict(int) for tile in tiles: for obj in tile.objects_detected: for ft in FigureType: if obj[type] ft.value: figure_counts[ft] 1 analysis.figures dict(figure_counts) analysis.total_figures sum(figure_counts.values()) # 3. 年代分类 dynasty, confidence self.classifier.classify(analysis, tiles) analysis.estimated_dynasty dynasty analysis.dynasty_confidence confidence # 4. 损毁评估——设计原因量化壁画保存状态 damage_analyzer DamageAnalyzer() damages damage_analyzer.analyze(tiles) analysis.damage_assessment damages analysis.overall_damage_score damage_analyzer.compute_priority(damages) # 5. 生成修复报告 repair_report self.restorer.generate_restoration_report( analysis, tiles ) # 6. 更新知识图谱 self.knowledge_graph.add_mural(analysis) return { analysis: { mural_id: mural_id, dynasty: dynasty.value if dynasty else 未知, confidence: round(confidence, 3), figures: { ft.value: count for ft, count in analysis.figures.items() }, damage_score: round(analysis.overall_damage_score, 3), }, repair_report: repair_report } def _split_image(self, image: Image.Image, tile_size: int 512) - List[MuralTile]: 图像分块——设计原因标准大小方便批处理 tiles [] w, h image.size for y in range(0, h, tile_size): for x in range(0, w, tile_size): x2 min(x tile_size, w) y2 min(y tile_size, h) tile_img np.array(image.crop((x, y, x2, y2))) tiles.append(MuralTile( tile_idftile_{x}_{y}, imagetile_img, position(x, y, x2, y2) )) return tiles # 使用示例 def analyze_dunhuang_mural_demo(): system DunhuangMuralSystem() # 分析一幅壁画 result system.analyze_mural( mural_idDH_MG_045_S, cave_number第45窟, wall_position西壁龛内南侧, image_pathdunhuang_cave45_south.jpg, inscriptions[大唐大历十一年岁次丙辰...], ) print(f年代判断: {result[analysis][dynasty]}) print(f置信度: {result[analysis][confidence]:.2%}) print(f损毁评分: {result[analysis][damage_score]:.3f}) print(f修复建议: {result[repair_report][repair_recommendations]}) analyze_dunhuang_mural_demo()整个系统的价值不在于替代文物专家的工作而在于完成专家不方便做或来不及做的事大规模损毁分级4.5万平方米的壁画一人一日只能巡查约50平方米。AI 可以在数小时内给出全量的损毁评分和修复优先级排序。跨朝代风格对比通过知识图谱专家可以在几秒内找到所有唐代绘有双手合十菩萨的壁画——这在纯人工检索中需要翻阅数千张照片。褪色复原评估AI 推断的复原图提供给修复专家参考而不是用于决策。四、个性化边界权衡自动化 vs 专家复核AI 的年代判断准确率约 75-80%在明确的风格特征下但对过渡期如北周-隋之间的准确率降至 50%。解决的现实方法是AI 标注置信度高置信度0.9的自动入库中等置信度0.7-0.9的标注提示供专家快速确认低置信度0.7的完全流转给专家人工鉴定。损毁检测灵敏度 vs 误报率损毁检测过敏感会把正常的绘制笔触误判为裂痕尤其是在飞天的衣纹线条中。敦煌壁画中有些剥落实际上是历史上的人为铲除灭佛运动所致。这些非自然的损毁在修复时可能有不同的处理策略——AI 需要学会区分自然老化和人为破坏。数据隐私 vs 开放共享高清壁画数据是文化遗产机构的数字资产开放使用有助于学术研究但涉及版权和保护措施。AI 分析过程中需要进行数据脱敏并在模型输出中去掉精确的地理坐标和洞窟内部保护措施信息。五、总结敦煌壁画 AI 理解采用多模态方法整合视觉分析、文本识别、颜料分析、年代归类四个维度的信息。视觉分析需覆盖人物检测、风格分类、损毁检测、色彩分析四路任务。文本分析通过古文 OCR 与经文内容匹配辅助场景识别。损毁评估采用八种损毁类型的加权评分体系剥落和酥碱权重最高。知识图谱将壁画、人物、技法、年代四大类节点关联支持多维度检索。实施中需权衡自动化与专家复核的分工、损毁检测灵敏度与误报控制、数据开放与版权保护的边界。核心价值在于自动化完成大规模壁画保护工作中的重复性评估让专家专注于决策和修复方案设计。