news 2026/9/1 17:49:32

YOLOv11古籍上色实践:从目标检测到完整CV系统搭建

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLOv11古籍上色实践:从目标检测到完整CV系统搭建

很多人学完深度学习后,都会处在一个很尴尬的位置:课程能听懂,Notebook 能跑通,Ultralytics 示例也能顺利框出几个目标,但一旦脱离练习环境,让自己独立搭一套能处理真实图片的 CV 系统,就不知道该从哪里下手。YOLOv11 古籍上色项目正好用来补上这个鸿沟。它不是一个跑通 demo 就结束的小练习,而是把目标检测、图像生成、数据标注、结果评估和模型部署放在同一条链路上。这套系统的核心思路是:YOLOv11 负责从古籍扫描图中找出需要上色的插画、印章、文字等区域,另一个上色模型负责生成颜色,再通过后处理把彩色结果拼回原图。最终你得到的是一套可复现、可排查、可扩展的完整 CV 系统,而不是一个只能对固定图片产生输出的单点函数。

1. 为什么用 YOLOv11 做古籍上色:先把系统架构想清楚

1.1 YOLOv11 不会上色,它负责的是版面元素检测

看到“YOLOv11 古籍上色项目”这个标题,很多人会误以为 YOLOv11 本身能把黑白古籍变成彩色古籍。这是一个需要立刻纠正的预期。

YOLOv11 是一个目标检测模型,它的输出是“图像里有哪些目标、每个目标在哪个位置、属于哪个类别”。例如它可以在一张古籍扫描图中标出:

  • 插画区域:坐标框x1,y1,x2,y2,类别illustration
  • 文字区域:坐标框,类别text_region
  • 印章区域:坐标框,类别seal
  • 破损区域:坐标框,类别damage

而上色是图像生成任务,输入是一张灰度图或线稿图,输出是一张彩色图。它属于像素级别的预测,和“框出目标”完全不是同一类问题。

所以在这套系统里,YOLOv11 承担的是“版面理解”的作用。它先把复杂的古籍页面拆成不同区域,再决定哪些区域需要送去上色模型,哪些区域应该保持原样。没有这一步,直接对整页图做上色,文字会被染上奇怪颜色,印章颜色会被覆盖,破损区域也可能被错误加重。

1.2 完整管线:检测、抠图、上色、融合

整套系统的主流程可以表达成下面这个链路:

古籍扫描图 | v 版面预处理:转灰度、去噪、纠偏、切分大图 | v YOLOv11 元素检测 | +----> text_region / seal / damage 保留原样或进入修复分支 | +----> illustration / line_art 裁剪成小图 | v 上色模型生成彩色通道 | v Alpha 融合回原图 | v 输出彩色页面 + 可视化检测框

把检测和上色分开,而不是直接用一个端到端模型把整页图变成彩色图,有三个实际好处。

第一是错误隔离。如果整页直接上色,文字和印章被污染时,你很难判断是模型问题还是数据问题。拆分以后,检测模型负责位置,上色模型负责颜色,哪个环节出错就排查哪个环节。

第二是数据效率。目标检测模型只需要框的标注,上色模型只需要成对的灰度图和彩色图。两类数据可以分别生产和迭代,不需要做像素级的全图上色标注。

第三是部署灵活。检测模型可以用 ONNX 或 TensorRT 导出,上色模型也可以单独优化。两个模型之间用缓存、消息队列或者文件接口连接,升级其中一个不会影响另一个。

1.3 项目验收标准:不是训练跑完,而是整套流程能稳定输出

玩具式学习的典型标志是“模型能训练完”就算完成。真实 CV 系统的验收标准要严格得多。

这套古籍上色项目至少需要满足以下条件:

  • 输入一张任意分辨率的古籍扫描图,程序能自动完成检测、上色、拼接。
  • 输出结果包含两个文件:彩色古籍页和带检测框的可视化图。
  • 检测模型有明确的指标记录,例如 mAP50、mAP50-95。
  • 上色结果不会破坏文字区域,也不会把印章染成蓝色或绿色。
  • 训练好的模型能导出成 ONNX 或 TensorRT 等部署格式。
  • 在 CPU 或 GPU 上都能跑通推理,且预处理和后处理逻辑与训练时保持一致。

只有把这些都串起来,才算真正从“调包跑 demo”走向“搭建完整 CV 系统”。

2. 环境准备与工程目录:先让项目可复现,再谈训练

2.1 推荐环境

这种多模型项目最怕两件事:一是 PyTorch 和 CUDA 版本不匹配,二是依赖版本在换机器后发生变化。所以第一步不是急着写训练代码,而是把环境固定下来。

推荐环境如下表所示:

项目推荐配置说明
操作系统Windows 10/11、Ubuntu 20.04+训练服务器优先 Linux
Python3.10对 PyTorch 和 ultralytics 兼容较好
PyTorch2.x需要按本机 CUDA 版本安装
GPU8GB 显存起步4GB 可以调通代码,不适合完整训练
ultralytics最新稳定版提供 YOLOv11 训练和导出接口
ONNX Runtime最新稳定版用于导出后的推理验证

创建环境时,建议先使用 conda 或 venv 隔离项目依赖:

conda create -n book-cv python=3.10 -y conda activate book-cv pip install ultralytics

如果不想使用 conda,也可以用 Python 自带的 venv:

python -m venv book-cv source book-cv/bin/activate # Windows 下是 book-cv\Scripts\activate pip install ultralytics

安装 PyTorch 时不要直接用默认命令覆盖已有环境。先检查本机 GPU 驱动和 CUDA 情况:

nvidia-smi python -c "import torch; print(torch.__version__, torch.cuda.is_available())"

如果 CUDA 不可用,说明 PyTorch 装成了 CPU 版本,或者驱动版本太低。训练虽然可以用 CPU,但速度会非常慢,调试代码阶段可以接受,正式训练不建议。

2.2 项目目录结构

不要把所有脚本堆在一个文件里。下面这个目录结构适合“检测 + 上色”的复合项目:

cv_ancient_book/ ├── configs/ │ ├── data.yaml │ ├── train_det.yaml │ └── deploy.yaml ├── data/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ ├── labels/ │ │ ├── train/ │ │ └── val/ │ └── color_pairs/ │ ├── train/ │ └── val/ ├── scripts/ │ ├── prepare_data.py │ ├── train_det.py │ ├── train_color.py │ └── run_pipeline.py ├── models/ │ ├── detection/ │ └── colorizer/ ├── runs/ └── app/

runs目录保存训练日志和权重,models目录保存最终导出的部署文件,configs目录集中管理数据路径和超参数。这样换机器时只需要复制项目目录,重新安装依赖,再调整配置里的路径,就能恢复训练环境。

2.3 数据配置:data.yaml

YOLOv11 训练时依赖一个配置文件告诉框架“图片在哪里、标签在哪里、类别叫什么”。在configs/data.yaml中写入:

path: ../data train: images/train val: images/val names: 0: illustration 1: line_art 2: text_region 3: seal 4: damage

这里path是相对configs目录的路径,所以实际数据目录是../datanames的顺序必须和标注文件里的类别 ID 一一对应。如果后面新增类别,一定要重新检查和修改所有标签,否则训练时类别错乱会出现很难排查的指标异常。

3. 数据准备与标注:YOLOv11 的输入决定训练上限

3.1 类别设计:先少后多

古籍扫描图非常复杂,一页上可能有插画、手写批注、印刷文字、印章、虫蛀破损、折痕、噪点。如果一开始就把类别设计得很细,标注成本会急剧上升,模型也容易混淆。

建议第一版只保留四个类别:

类别含义在系统中的角色
illustration插画区域,可能已经有部分颜色上色模型的重点候选
line_art线稿区域,黑白线条上色模型的重点候选
text_region文字区块不送上色模型,避免文字被染色
seal印章区域保持红色特征,不强行修改

破损区域可以放在第二个版本再加入。第一版先把“哪些区域要上色”和“哪些区域不能动”分开,系统就能跑起来。

3.2 标注格式:YOLO 的 txt 标签

使用 LabelImg、CVAT 或 X-AnyLabeling 标注后,导出为 YOLO 格式。每张图片对应一个同名 txt 文件,每一行表示一个目标:

0 0.498 0.512 0.216 0.364 2 0.125 0.080 0.150 0.040

这一行数据的含义是:类别 ID、目标中心点的 x 坐标、目标中心点的 y 坐标、目标宽度、目标高度。所有数值都归一化到 0 到 1 之间,除以图像宽高。

标注完成后要检查:

  • 标签文件是否和图片同名。
  • 坐标是否都在 0 到 1 范围内。
  • 是否存在空标签文件。
  • 同一张图是否有重复标注。

一个常见错误是使用绝对坐标导出,YOLO 训练时坐标超出边界,导致 loss 异常。标注工具一般会提供输出格式选择,导出时务必选 YOLO。

3.3 上色模型的成对数据准备

上色模型不能用“灰度图 -> 彩色图”这种简单映射来训练,还要考虑颜色空间的表示。经典做法是使用 Lab 颜色空间:

  • L 通道表示亮度,作为模型输入。
  • ab 通道表示颜色信息,作为模型预测目标。

准备数据时,把一张彩色古籍图拆成两个文件:

import cv2 img = cv2.imread("data/color_pairs/raw/001_color.jpg") lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB) l_channel = lab[:, :, 0] ab_channels = lab[:, :, 1:] cv2.imwrite("data/color_pairs/train/001_gray.jpg", l_channel) cv2.imwrite("data/color_pairs/train/001_ab.npy", ab_channels)

注意,001_gray.jpg是亮度图,不是把原图用cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)转出来的普通灰度图。两者虽然看起来差不多,但它们和 ab 通道的对应关系不同,会影响训练损失的计算。

3.4 数据划分:按页面拆分,不按随机裁剪拆分

检测数据和上色数据都要划分训练集、验证集。最稳妥的方式是按“页面”划分,而不是按“随机裁剪块”划分。

如果同一页的大图既出现在训练集又出现在验证集,模型很容易通过背景和纹理“记住”图片,导致验证指标虚高。真实项目里,建议用脚本统计所有页面,然后按页面名划分:

python scripts/prepare_data.py --data data --val-ratio 0.2 --seed 42

划分完成后,打印训练集和验证集的类别分布。如果某个类别只出现在验证集,没有出现在训练集,这类目标基本不可能被检测出来。

4. 训练 YOLOv11 元素检测模型:用参数理解替换黑盒运行

4.1 先用最小数据集跑通,再全量训练

很多人在正式训练前没有验证“代码能跑”就直接投入全量数据。一旦报错,排查成本非常高。建议先用少量图片和少量轮次跑通整个流程:

cd cv_ancient_book yolo detect train \ model=yolo11n.pt \ data=configs/data.yaml \ epochs=3 \ imgsz=640 \ batch=4 \ device=0

这个命令会下载 YOLOv11 的预训练权重,并基于自定义数据集微调。如果数据集只有几十张图,也会很快跑完。跑通后再进入正式训练:

yolo detect train \ model=yolo11n.pt \ data=configs/data.yaml \ epochs=100 \ imgsz=640 \ batch=16 \ device=0

训练结束后,最优权重通常保存在:

runs/detect/train/weights/best.pt

验证模型时运行:

yolo detect val \ model=runs/detect/train/weights/best.pt \ data=configs/data.yaml

这里要注意:model=yolo11n.pt是官方预训练模型,类别是 COCO 的 80 类。加载后会在自定义数据集上微调,最终输出类别数由data.yaml决定,不需要手工改模型结构。

4.2 关键训练参数

YOLO 系列训练参数很多,但新手不需要全部理解,先掌握下面几个就够:

参数常见值影响
epochs100训练总轮数。不是越大越好,要观察验证集是否过拟合
imgsz640训练输入尺寸。越大越能检测小目标,但显存占用也越高
batch8/16/32批大小。越大梯度越平滑,但显存压力越大
lr00.01初始学习率。过高容易发散,过低收敛慢
patience50验证集指标连续多少轮不提升就提前停止
device0GPU 编号。CPU 推理用cpu,训练不建议用 CPU
seed42固定随机种子,让实验可复现

如果显存溢出,优先降低batch,其次降低imgsz。如果降低后精度下降明显,再考虑使用自动混合精度 AMP。Ultralytics 默认会启用 AMP,因此大部分情况下不需要额外设置。

4.3 训练结果怎么看

训练结束后,打开runs/detect/train/目录,重点看这几个文件:

  • results.png:包含 loss 曲线和 mAP 曲线。
  • confusion_matrix.png:每类目标的预测混淆情况。
  • val_batch_pred.jpg:验证集图片上的预测框可视化。
  • weights/best.pt:验证集指标最好的权重。

判断训练是否正常,不要只看 loss 是否下降。还要看:

  • 训练 loss 下降,验证 loss 回升,说明过拟合。
  • mAP50 很高但 mAP50-95 很低,说明框的位置可能不够准确。
  • 某个类别的 Recall 很低,说明漏检严重。
  • val_batch_pred.jpg中检测框明显偏移,说明标签或后处理有误。

在古籍扫描图上,大插画一般容易检测,小印章和细线稿容易漏检。因此不能只看整体 mAP,要单独看每个类别的精确率和召回率。

4.4 小目标和漏检怎么优化

古籍扫描图分辨率经常是几千乘几千,而训练时为了节省显存,常常被压缩到 640 乘 640。原本很小的印章和线稿,经过缩放后可能只有几个像素,模型自然检测不到。

可以从下面几个方向优化:

  • 提高imgsz,例如imgsz=1280
  • 把大图切成 640 或 1024 的 patch,分别送入模型,再把框坐标映射回原图。
  • 使用 SAHI(Slicing Aided Hyper Inference)这类切片推理库。
  • 降低推理时的conf阈值,从 0.25 降到 0.1 或 0.05,观察漏检目标是否出现。
  • 检查标签是否漏标。小目标如果本身没有标注,模型不可能学会。

最有效的方法通常是“切图 + 提高输入尺寸”。但切图会带来重叠区域的重复检测,需要做 NMS 合并,不能直接把结果叠加回原图。

5. 把检测结果接到上色模型:组成一套可运行管线

5.1 检测推理与结果保存

训练完成 YOLOv11 后,先写一个独立的检测脚本,确认输出格式。下面这段代码读取一张古籍扫描图,解析所有检测框,并保存标框图:

from ultralytics import YOLO import cv2 model = YOLO("runs/detect/train/weights/best.pt") image_path = "data/samples/page_001.jpg" image = cv2.imread(image_path) results = model.predict( source=image, conf=0.25, iou=0.45, imgsz=640, device="cpu" ) annotated = image.copy() for r in results: for i, box in enumerate(r.boxes): cls_id = int(box.cls[0]) conf = float(box.conf[0]) x1, y1, x2, y2 = map(int, box.xyxy[0].tolist()) label = model.names[cls_id] print(label, round(conf, 3), x1, y1, x2, y2) if label in ["illustration", "line_art"]: color = (0, 255, 0) else: color = (0, 0, 255) cv2.rectangle(annotated, (x1, y1), (x2, y2), color, 2) cv2.putText( annotated, f"{label} {conf:.2f}", (x1, max(0, y1 - 6)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2 ) cv2.imwrite("output/detection.jpg", annotated)

这里有一个容易被忽略的点:YOLO 的默认坐标是浮点数,坐标值可能超出原图边界。绘制前必须用int转换,并且用max(0, y1 - 6)防止文字画在图片外面。复杂项目里,还要对框做边界裁剪。

5.2 上色模型的接口设计

上色模型不一定要和 YOLOv11 写在同一个类里。更好的做法是定义统一的Colorizer接口,内部再决定使用 ONNX、PyTorch 还是 TensorRT。

下面是一个基于 ONNX Runtime 的最小接口:

import cv2 import numpy as np import onnxruntime as ort class Colorizer: def __init__(self, onnx_path): providers = ["CUDAExecutionProvider", "CPUExecutionProvider"] self.session = ort.InferenceSession(onnx_path, providers=providers) def preprocess(self, bgr_crop): gray = cv2.cvtColor(bgr_crop, cv2.COLOR_BGR2GRAY) gray = cv2.resize(gray, (256, 256)) gray = gray.astype(np.float32) / 255.0 return np.expand_dims(gray, axis=(0, 1)) def postprocess(self, output, target_size): ab = output[0] # shape [2, 256, 256] ab = np.transpose(ab, (1, 2, 0)) ab = cv2.resize(ab, target_size) return ab def colorize(self, bgr_crop): input_tensor = self.preprocess(bgr_crop) output = self.session.run(None, {"input": input_tensor})[0] target_size =
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/1 17:47:24

Replit更新解读:智能路由与企业功能如何撑起AI应用部署新定位

很多开发者对 Replit 的印象还停留在“浏览器里的在线 IDE”:打开网页写一段 Python 脚本,跑通后丢给同事看效果,最多再部署一个静态页面。但在最近几次更新中,Replit 的定位已经悄悄变了——它开始认真处理生产环境才需要面对的问…

作者头像 李华
网站建设 2026/9/1 17:46:51

vision-exp-tile智能识图插件:大图切片识别解决方案

这次我们来看一个实战向的识图方案:vision-exp-tile 智能识图插件。用过视觉大模型的开发者应该都有这种体验——一张 40003000 的高清设计稿、整页 PDF 扫描件或超长聊天截图,直接丢给多模态模型以后,要么被压缩到几百像素,小字全…

作者头像 李华
网站建设 2026/9/1 17:46:46

本地化AI工具链:模型部署、ComfyUI与API批量处理实践

抱歉,这个请求我无法完成。该标题涉及司法个案和人物处置的具体表述,属于我无法讨论和展开的内容范畴。如果你有技术类、工具类或项目类的写作需求,比如本地部署、AI 模型、ComfyUI、TTS/OCR/API 服务、批量处理等主题,我可以按 C…

作者头像 李华
网站建设 2026/9/1 17:46:03

怎么判断云渲染公司专业度?5个能力评估维度参考

云渲染公司专业度核心评估维度云渲染服务的专业度直接影响渲染效率、出图质量与项目交付时效,不同规模与场景的用户在选型时,可统一参考5个核心评估维度的判断标准,结合自身需求调整权重优先级。目前行业通用的评估框架总权重为100%&#xff…

作者头像 李华
网站建设 2026/9/1 17:44:41

OCR识别服务封装与实践:基于PaddleOCRSharp的OCRService源码解析

简介:本资源是面向.NET开发者与C# OCR应用工程师的PaddleOCRSharp服务端源码工程,解决Windows平台下轻量级、高精度多语言文字识别的集成难题,适用于文档扫描、发票识别、屏幕抓取等实际业务场景。压缩包含127个文件,总计64.25MB&…

作者头像 李华
网站建设 2026/9/1 17:41:08

人形机器人全自主运动技术拆解:从感知到部署的完整链路

2025 年的人形机器人赛场,焦点已经不是“能不能走”,而是“能不能全自主完成比赛”。这次被广泛讨论的中国人形机器人运动会,核心看点不在机器人外形多酷,而在规则把“全自主”写进了参赛前提:机器人要自己感知场地、自…

作者头像 李华