这次我们来看一个比较特殊的交叉方向:把“汉代制盐”从传统史学课题,变成一个可以用 AI 技术处理的实际项目。表面上看,汉代盐业研究是历史学和考古学的范畴,但落到技术实现上,它涉及古籍 OCR、画像石目标检测、遗址遥感识别、文献知识图谱构建等一系列数字人文处理流程。如果你关心文化遗存数字化、古代文献信息抽取、或者想把一套历史专题数据做成可检索可分析的知识库,这篇文章可以直接收藏。
标题里的Salt Production in HanDynasty 汉代制盐,完全可以作为一个数字化专题项目来落地。它不是简单地把古籍扫描件翻拍上传,而是要解决几个具体问题:如何从汉简、地方志、盐业文献中自动抽取制盐工艺段落;如何在画像石拓片、盐井遗址照片中定位蒸锅、盐井、灶台、输卤管道等目标;如何把分散在不同文献里的盐官、盐场、产量信息关联起来,形成时间线;又如何把这一整套能力封装成接口,供后续研究平台调用。
下面会按照“项目能力速览 -> 场景边界 -> 环境准备 -> 数据构建 -> 模型训练 -> 功能测试 -> API 与批量任务 -> 性能观察 -> 问题排查 -> 最佳实践”的顺序展开。整体内容偏向工程落地,而不是学术论述。没有实际运行环境和模型权重,所以涉及显存、帧率、精度的地方,都会用通用测试思路代替,避免给你一个不存在的“实测数字”。
1. 核心能力速览
“汉代制盐”数字化项目是一个典型的多模态历史信息处理任务,它的核心能力不是单一模型,而是一个组合管线。
| 能力项 | 说明 |
|---|---|
| 项目类型 | 数字人文 / 文化遗产数字化 / 多模态信息抽取 |
| 主要功能 | 古籍 OCR、盐业图像目标检测、文献实体关系抽取、知识图谱构建、检索问答 |
| 输入数据 | 古籍扫描件、画像石拓片、遗址照片、盐业文献文本、地名数据 |
| 输出数据 | 结构化文本、检测框标注、实体关系三元组、时间线、知识图谱 JSON |
| 硬件需求 | 低配置可用 CPU 跑 OCR,目标检测建议准备 NVIDIA GPU;显存大小需根据模型实际选择 |
| 支持平台 | Windows / Linux / macOS 均可,涉及深度学习训练建议 Linux 或 WSL2 |
| 启动方式 | 命令行训练、Web API 服务、批量任务脚本 |
| 是否支持 API | 支持,通过 FastAPI 或 Flask 封装检测与抽取服务 |
| 是否支持批量任务 | 支持,按目录扫描输入,输出 JSON / CSV |
| 适合场景 | 历史文献整理、盐业考古辅助分析、博物馆数字化、专题知识库建设 |
从项目结构上看,它并不是一个开箱即用的一键包,而更像是一套需要结合数据定制的技术方案。如果你只是想把几十页汉代盐业史料转成文字,那单独跑 OCR 就够了。但如果你要识别画像石中的制盐工序,或者把各类文献里的盐官、盐场、产量做关联分析,就需要拆成多个子任务来处理。
2. 适用场景与使用边界
任何数字人文项目都不能只谈技术,还要谈数据的合法性和使用边界。“汉代制盐”这套思路适合以下场景:
- 博物馆或研究机构对馆藏盐业相关文物进行数字化登记,形成图像与文本的对照检索。
- 历史学者需要从大量古籍中快速定位制盐工艺相关段落,减少通读成本。
- 考古现场对盐井遗址、灶址、盐场遗址的照片进行初步分类和标注辅助。
- 地方文化专题数据库建设,把散落在志书、碑刻、学术论文里的盐业信息统一成结构化数据。
同时,它也有明显不适用的情况。
第一,它不适合用来做考古断代的直接依据。模型输出的检测框和识别文本只是研究辅助,不能替代专业考古人员的判断。第二,它不适合处理现代商用盐业技术资料。汉代的制盐技术背景和现代工业制盐差异很大,模型和研究范围应该严格限定在历史专题内,否则容易出现概念混淆。第三,如果面向公众做展示,需要特别注意文物图像的版权归属,不能因为模型输出了图像标注就认为可以随意对外发布。
在合规层面,需要明确三个原则:文物图像使用必须有授权;人物肖像和声音素材不适用于此类历史专题,除非来自公开历史图像且符合相关法律;任何个人或机构基于该成果发布研究成果时,应标注数据来源和模型局限性。
3. 环境准备与前置条件
在开始处理汉代制盐数据之前,先确认硬件和软件环境。因为这是一个多步骤管线,环境配置决定了你能做到哪一步。
3.1 系统与基础工具
操作系统建议优先使用 Linux 或 Windows 的 WSL2 环境,原因主要在于后续训练 YOLO 或检测 Transformer 模型时,Linux 下 CUDA 生态更省心。纯 CPU 做 OCR 和文本抽取,Windows 也能跑,但如果计划训练目标检测模型,显卡驱动和容器支持是关键。
需要提前装好的工具包括:
- Python 3.9 及以上版本,推荐 3.10 或 3.11。
- Git,用于拉取代码和版本管理。
- CUDA Toolkit 和 cuDNN,具体版本取决于 PyTorch 或 PaddleOCR 的要求。
- Docker(可选),适合把 OCR、检测、检索封装成独立服务。
3.2 Python 依赖
下面给出一份通用依赖文件,实际版本号需要根据所选模型框架调整:
# requirements.txt 示例,具体版本需要按项目实际锁定 paddleocr paddlepaddle-gpu torch torchvision ultralytics fastapi uvicorn pydantic opencv-python pillow pandas pymysql redis安装命令:
pip install -r requirements.txt如果使用 PaddleOCR 做古籍文字识别,建议单独参考 PaddleOCR 官方安装说明,因为它依赖的 PaddlePaddle 版本和 CUDA 版本对应关系比较严格。更有把握的做法是使用独立虚拟环境,避免多个深度学习框架之间的版本冲突。
3.3 GPU 与显存判断
目标检测任务如果使用 YOLOv8n 或 YOLOv8s 这类轻量模型,8GB 到 12GB 显存的显卡通常可以覆盖训练和小批量推理。如果换成更重的模型,显存需求会明显上升。由于没有实际运行模型权重和参数配置,这里不给具体数字,只给判断思路:
- 训练阶段看
batch_size、图像分辨率、模型参数量。训练报CUDA out of memory时,优先降低 batch size 和分辨率。 - 推理阶段看单张图像的尺寸。画像石拓片往往是长图,直接全图推理容易爆显存,建议切片推理再拼接结果。
- 纯 CPU 推理也可以跑,但速度会明显下降。对于批量古籍 OCR,如果耐心足够,CPU 也能完成;如果要做交互式查验,建议还是用 GPU。
3.4 数据目录规划
先建立清晰的数据目录,避免后面模型训练和批量任务把目录搞乱:
han_salt/ ├── data/ │ ├── raw_images/ # 原始画像石、遗址照片 │ ├── raw_docs/ # 古籍扫描件 PDF │ ├── labels/ # 标注结果 │ └── outputs/ # 模型输出 ├── models/ │ ├── text_det/ # OCR 检测模型 │ ├── obj_det/ # 盐业目标检测模型 │ └── ner/ # 命名实体识别模型 ├── scripts/ │ ├── ocr_batch.py │ ├── detect_batch.py │ └── build_graph.py └── deploy/ ├── api.py └── config.yaml这个目录结构既服务于训练阶段,也方便后续 API 和批量任务管理。
4. 数据准备与标注:构建汉代制盐专题数据集
模型能不能用,首先取决于数据怎么整理。汉代制盐的数据来源很分散,需要拆成图像和文本两条线分别处理。
4.1 图像数据:画像石、拓片与遗址照片
汉代的制盐图像信息主要藏在画像石、画像砖、陶器纹饰和部分壁画中。常见元素包括盐井、井架、提卤桶、熬盐灶、锅釜、输卤槽、人物劳作图等。
采集这类图像时要注意:
- 图像分辨率尽量高,因为画像石拓片的细节线条非常关键。
- 同一个拓片可能需要多种光照条件下的翻拍,以便模型学习线条变化。
- 如果条件允许,加入线稿重绘版本作为增强数据,有助于提升检测效果。
- 遗址照片应当包含环境上下文,不能只拍单个灶坑,否则模型难以区分盐业遗址和普通居址。
标注格式建议采用 YOLO 或 COCO 格式。下面是一个 YOLO 格式标注说明:
# class_id, x_center, y_center, width, height 0, 0.352, 0.621, 0.214, 0.318 1, 0.712, 0.248, 0.154, 0.207其中:
0表示盐井1表示灶台2表示锅釜3表示输卤槽
如果是一张拓片里同时包含多个目标,就写出多行。标注工具可以使用 LabelImg、X-AnyLabeling 或 Label Studio。更稳妥的做法是让考古专业人员参与抽样复核,因为部分画像石的抽象线条很容易误标。
4.2 文本数据:古籍文献与地方志
汉代制盐的文本资料包括《史记》《汉书》中的盐铁记录,以及后世地方志里对盐井、盐场、盐官的记载。需要处理的任务主要是段落分类、命名实体识别和关系抽取。
以“盐官”为例,文本中可能出现“蜀郡临邛”“广都盐井”“南安”等专名。命名实体识别需要标记类型,例如:
[ { "text": "广都盐井", "label": "盐井", "start": 4, "end": 8 }, { "text": "蜀郡", "label": "地名", "start": 0, "end": 2 } ]如果你不想从零训练 NER 模型,也可以先用规则加词典的方式做初版:整理一份汉代盐业专名表,通过字符串匹配抽取出候选实体,再用分类模型过滤。这种方式启动快,适合数据量不大、专名相对固定的专题。
4.3 数据增强与样本平衡
汉代制盐图像数据量通常不会很大,必须依赖数据增强提模型泛化能力。对于拓片和画像石图像,适合的增强包括:
- 随机旋转、平移、缩放。
- 亮度对比度调整,模拟不同光照条件。
- 高斯模糊与噪声,模拟拓片磨损。
- 随机裁剪,让模型学会在局部纹理里找目标。
文本数据同样可以增强:把古籍原文中的通假字替换随机处理,或者对实体词进行位置扰动,但这些增强不能改变语义。对历史实体而言,人为引入错误专名反而会降低抽取效果,所以文本增强要保守。
5. 模型训练与效果验证
数据准备好了,下面进入训练和验证环节。这里以一项目标检测子任务为例,给出完整实验流程;OCR 和 NER 任务可以参照类似思路。
5.1 目标检测模型训练
如果使用 YOLOv8,数据配置文件data.yaml大致如下:
# 数据配置示例 path: ./han_salt_dataset train: images/train val: images/val names: 0: salt_well 1: stove 2: pan 3: brine_trough训练命令:
yolo detect train model=yolov8s.pt data=data.yaml epochs=100 imgsz=640 batch=8如果显存不足,把batch降到 4 或 2,同时把imgsz降到 512 或 416。画像石长图建议先做切片。切片时每张图会有重叠区域,推理后再用 NMS 合并重复框,避免一个目标被切成两半导致漏检或重复检测。
5.2 验证指标怎么看
目标检测最核心的指标是mAP50和mAP50-95。对于汉代画像石这类线条复杂、目标区域不明显的图像,mAP50更重要,因为考古辅助标注看重的是“有没有找到大致位置”,而不是严格的像素级定位。
同时还要关注每个类别的召回率。盐井和灶台容易被漏检,如果召回率低于可接受水平,优先补充该类别样本,再进行训练。不要只看总体 mAP,一个类别的准确率可能被其他类别数量掩盖。
5.3 图像切片推理示例
训练完成后,可以写一个批量检测脚本。下面给出一个通用 Python 示例:
from ultralytics import YOLO model = YOLO("runs/detect/train/weights/best.pt") def detect_single_image(image_path, output_dir): results = model.predict( source=image_path, conf=0.4, iou=0.5, save=True, project=output_dir, name="pred" ) return results if __name__ == "__main__": detect_single_image("./data/raw_images/huaxiangshi_001.jpg", "./data/outputs")这个脚本会把检测结果图保存在output_dir/pred下,并把标签信息一并输出。实际应用时,可以根据需要把结果再转成 GeoJSON 或 JSON 格式,便于研究者在地理信息平台上查看。
5.4 OCR 文本识别测试
古籍扫描件先做版面分析,再做文字识别。通用的 OCR 工具库可以直接调用:
import paddleocr ocr = paddleocr.PaddleOCR(use_angle_cls=True, lang="ch", use_gpu=True) def ocr_pdf_page(image_path): result = ocr.ocr(image_path, cls=True) lines = [] for line in result: for word_info in line: text = word_info[1][0] score = word_info[1][1] lines.append({"text": text, "score": score}) return lines如果目标是“汉代制盐”相关文本,建议对 OCR 结果再做一次关键词过滤,只保留包含“盐”“井”“灶”“煎”“煮”“盐官”等字词的句子。这样可以大幅减少后续 NER 的处理量。
6. 接口 API 与批量任务
研究项目不能只停留在训练脚本阶段,还需要把能力开放出来,方便历史学者上传图片或录入文本,即时得到结构化结果。
6.1 FastAPI 服务封装
用 FastAPI 封装一个统一入口,请求图片路径或 Base64 编码,返回检测框与 OCR 文本,是一个比较自然的做法。示例代码如下:
from fastapi import FastAPI, File, UploadFile import shutil import tempfile from detect import predict_image # 自定义函数 app = FastAPI() @app.post("/analyze") async def analyze(file: UploadFile = File(...)): with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tmp: shutil.copyfileobj(file.file, tmp) tmp_path = tmp.name result = predict_image(tmp_path) return {"status": "ok", "result": result}这是一个典型的上传图片接口。部署时需要注意请求体大小限制。画像石高清图可能达到几十 MB,需要在反向代理或 FastAPI 配置中调大上传限制。
6.2 批量任务设计
批量任务建议采用“文件夹扫描 + 结果落盘”的方式,而不是把所有结果一次性放回内存。对一个包含上百张拓片的目录,处理流程如下:
- 遍历输入目录,生成任务列表。
- 对每张图片先做类型判断(拓片、照片、手绘线稿)。
- 分别调用 OCR、目标检测和 NER 模块。
- 将结构化结果写入 JSON 文件,并用文件名关联原图。
- 汇总为
summary.csv,供研究者快速浏览。
批处理脚本里要加入重试机制。如果某张图片因为内存不足或模型推理错误中断,不能影响整批任务。简单做法就是在循环里捕获异常并跳过,记录失败原因:
import traceback def process_one(image_path): try: result = predict_image(image_path) return result except Exception: traceback.print_exc() return {"error": "failed"}7. 资源占用与性能观察
“汉代制盐”这个项目的数据密度不高,但对图像分辨率要求很高。观察资源占用时,重点关注三个环节:OCR 推理、目标检测推理、批量任务并发。
7.1 显存观察方法
如果使用 NVIDIA GPU,可以通过nvidia-smi查看实时显存占用:
watch -n 1 nvidia-smi也可以用 Python 在推理脚本中打印当前显存使用情况:
import torch if torch.cuda.is_available(): print(torch.cuda.memory_reserved()) print(torch.cuda.memory_allocated())更实用的方法是控制变量:先跑单张图,记录显存峰值;再逐步提高 batch size 或图像分辨率,找到当前硬件能承受的上限。不要一次性把分辨率调到最大,否则很容易CUDA out of memory。
7.2 分辨率、批量数和文本长度的影响
画像石拓片检测对分辨率非常敏感。整体趋势是:分辨率越高,检测小目标的效果越好,但显存和耗时也越高。合理做法是先对长图做切片,每张切片保持输入分辨率不超过模型预期,而不是简单把整张拓片缩放到模型输入尺寸。
批量任务里如果同时跑 OCR 和检测,内存和显存都会出现叠加占用。建议一次只跑一个模型,或者把服务拆成两个独立进程。
7.3 CPU 和 GPU 差异
CPU 推理优势是无需显存,适合小规模验证和文本抽取。如果只是从几十页古籍里抽取制盐相关句子,CPU 完全可行。但大量图像目标检测和高分辨率 OCR,GPU 会明显更快。一个稳妥的部署方案是:图片类任务走 GPU,文本抽取走 CPU,这样资源利用率更高。
8. 常见问题与排查方法
数字人文项目在落地时容易遇到下面几类问题,这里整理成排查表格。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| OCR 识别出大量乱码 | 古籍字体被模型识别成现代低质量文本 | 查看原图清晰度和版面分析结果 | 换用繁体/古籍专用 OCR 模型,或者对图像做二值化和腐蚀处理 |
| 目标检测漏检盐井 | 样本数量不足或原图分辨率过低 | 检查该类别召回率,查看切片是否切断目标 | 补充样本,调整切片重叠率 |
| 训练时报显存不足 | batch size 或输入分辨率过高 | 查看报错信息,确认imgsz和batch | 降低 batch size,使用梯度累积,或改用轻量网络 |
| 批量任务中途卡住 | 单张图片推理失败导致线程阻塞 | 检查日志和错误信息 | 加入超时控制和异常捕获,失败自动跳过 |
| API 上传大图超时 | 反向代理请求体限制过小 | 查看 Nginx 或 FastAPI 日志 | 调大上传限制,或改为上传文件路径方式 |
| 实体抽取结果重复过多 | 同义地名和异体字未归一化 | 检查 NER 后处理逻辑 | 加入实体归一化表,例如“临邛”和“临邛县”合并 |
其中,大量乱码问题在汉代制盐文献中尤其常见,因为地方志和古籍普遍使用繁体字和异体字,个别字形与常见训练集差异很大。解决思路是先做图像增强,再切换古籍专用 OCR 模型,最后对结果做领域词典校正。
9. 最佳实践与使用建议
做“汉代制盐”这类数字人文项目,最怕的不是模型不够强,而是数据管理混乱,导致结果不可追溯。下面几条建议值得参考。
第一,第一次跑通流程时,用最小数据量。先拿几张清晰的画像石拓片和几页古籍扫描件,跑通“图片 -> OCR / 目标检测 -> JSON 输出”的完整链路,确认管线没有断裂,再扩展到全量数据。
第二,保留一套最小可运行配置。把数据配置、依赖版本、命令写进 README 或 Makefile,方便以后复现。数字人文研究项目通常会中途停几个月再启动,如果没有固化环境,重新安装依赖会浪费大量时间。
第三,模型输出必须经过人工复核。尤其是目标检测边界框和 OCR 文字,不能直接作为最终研究结论。一个可行的复核方式是把模型输出结果转成 HTML 报告,标注出置信度较低且需要人工确认的条目。
第四,数据目录要规范化。原始素材、标注文件、模型权重、输出结果分开放,并且在上传前做文件哈希记录,防止后续处理时数据被意外覆盖。
第五,涉及文物图像和古籍数据时,一定要确认授权。汉代制盐相关画像石拓片和古籍扫描件,很多来自博物馆和图书馆,不能因为个人研究用途就随意公开传播。
10. 总结与下一步
“汉代制盐”这个主题最适合的切入点,不是训练一个“万能考古模型”,而是先做出一个能用的专题知识抽取管线:把画像石上的盐井、灶台检测出来,把古籍里的盐官、盐场、工艺词抽出来,再把它们按地点和时间关联成结构化知识。
最值得先试的功能是“图片上传 -> 自动标注”,因为它最直观,也能快速让历史学者看到 AI 的辅助价值。最容易踩的坑是古籍 OCR 乱码和长图检测漏检,这两类问题几乎必然遇到,解决办法只有两个方向:增加领域数据,调整预处理流程。
后续可以扩展的方向包括:把检测结果接入 WebGIS,形成汉代盐业遗址空间分布图;把文本抽取结果构建成知识图谱,支持“某个盐场的产量变化”这类问句;也可以加入时间信息,让研究者按朝代时间轴浏览盐业制度演变。
如果你正准备做汉代盐业数字化,建议不要一上来就追求大而全的平台,先把“单张拓片检测 + 单页古籍 OCR + JSON 输出”这一条链路跑通。这条链路稳定之后,再考虑 API 封装、批量任务和知识图谱,会顺利得多。