OCRX 自学习与自定义模型使用说明
编写日期：2026-10-08

这份说明对应本次优化后的功能。软件验收数据、完整运行包版本及实际测试结论，以同批交付的验收回执为准。下面的外部训练命令是操作示例，本次没有在本机执行模型训练，也没有生成新的训练权重。

一、先理解：现在的“学习”怎样影响下次识别

OCRX 有两个层次：日常使用的本地校审反馈，以及另外开展的模型微调。

本地校审反馈的流程是：
原始图纸像素 → OCR 初步结果 → 人工修正或确认 → 保存文字裁图和正确答案 → 下次 OCR 对相似裁图核实后纠正结果。

例如原图是 AM804，模型偶尔输出 AM8O4。你把它修订为 AM804，软件保存这块真实裁图、原识别文字、修订文字、原文件指纹、页码、识别框和修订记录。下次找到足够相似的图像时，可以把相应结果纠正为 AM804。这里依靠的是图像证据；不会仅因为你在两张图纸中改过同一个错词，就把所有同名内容全局替换。

连续把同一个框从 A 修成 B，再修成 C，当前有效答案应是最新的 C。旧修订保留为历史，但不再作为并列有效答案导出。撤销会撤回相应反馈；重做会恢复对应的人工结果。删除框会撤回它的有效反馈。反复点击同一个框不会凭空增加独立样本数量。

这个层次不会改变 ONNX 模型的参数，不是“每改一次就训练一次神经网络”。在完全不同的字体、字号、缩放、内容或新布局上，它不保证生效。图像不够相似，或者匹配到互相矛盾的有效答案时，软件保留模型结果，留给人工校审。

模型微调则是：积累经过核实的图像与真值 → 在外部训练环境调整网络参数 → 评估 → 导出兼容 ONNX → 在 OCRX 中使用新模型。这个层次才可能学会一类字体和场景，并改善没有见过的新样本。OCRX 当前提供样本积累、导出和自定义模型加载，尚未内置自动训练、自动验收或自动发布新模型。

二、日常怎样操作，才能把修订变成可靠反馈

1. 先打开图纸并识别，放大核实原图的真实文字。
2. 检查识别框是否覆盖一整行，并核实角度。不要把含两三行的大框当成一行真值；不要把邻近图形、另一行文字或水印当成目标文字。
3. 文字错误：在结果表中修改文字，或在框上右键选择“修改文字”。逐字核实型号、下划线、小数点、括号、数量和大小写后提交。
4. 文字正确：在框上右键选择“审核通过（锁定 100%）”。这也能积累正确样本，防止样本库只剩下错误案例。
   多条文字都已核实：在右侧结果列表中按 Ctrl 单击追加选择，或按 Shift 单击连续选择，右键已选行，选择“批量审核通过”。每条非原生有效文字分别记录学习反馈，整组可一次撤销。
   需要重读多个框：多选后右键“重新识别所选区域（替换校审结果，可撤销）”。成功才替换该条校审结果并撤回旧真值；失败或无文字保留原文字及校审锁定。原生 PDF 文字不重读，结束后查看状态栏汇总。新结果请再次核实后审核，避免把未经确认的 OCR 当作学习真值。
5. 漏检：手工加框并输入你核实的文字。框选后由机器重新识别得到的未经确认结果，还不能直接当成人工真值；核实后再修改或审核。
6. 已经人工修改或审核锁定的框，调整位置、尺寸或角度后，会更新对应裁图反馈。先把方向和框调正确，再确认文字，训练裁图与答案才相符。
7. 软件会把裁图和索引保存放入后台队列。界面出现“已交给后台记录”表示已排队，不代表磁盘保存已经完成。保存失败会显示原因。正常退出时软件会等待队列保存完成。
8. 如需明确确认样本已经落盘，可以从顶部“导出 PDF”图标右侧箭头选择“导出校审训练数据集…”，选择一个新的目录，等待“校审训练数据已导出：N 条有效样本”。导出任务排在之前的修订之后，包含已完成保存的当前有效样本。

每一次有效的人工文字修订、审核、手工录入，都应成为可追溯的正反馈。但“正反馈”仍然需要你给出正确答案。看错型号、误把 AM801 改成 AM804，同样可能教错软件；应使用撤销或再次修订纠正。拖动预览、排序表格、缩放窗口等操作不产生文字真值。原生 PDF 文字的编辑也不会直接作为 OCR 裁图学习样本。

三、样本保存在哪儿，换显卡模式后是否仍可用

默认目录：
%LOCALAPPDATA%\OCRStudio\learning

这是当前 Windows 用户的数据目录，不在 EXE 内。里面按模型保存反馈索引 feedback.json、裁图 images 和修订历史。升级软件时保留这份目录，学习记录才会继续可用。测试或开发可以通过 OCRSTUDIO_LEARNING_ROOT 指定另一目录，日常使用无需设置这个变量。

三个使用相同内置模型的模式共享校审反馈：
标准识别（CPU）、显卡加速（NVIDIA/CUDA）、显卡加速（通用/DirectML）。

自定义模型按模型名称独立保存反馈；不同模型版本应使用不同 name，便于比较和回滚。即使把自定义模型伪装成内置模型的名字，只要替换了模型或字典路径，也不会把它并入内置模型反馈库。旧版三种内置模式的历史样本会参与兼容读取；旧目录和图片保留。

同一个区域的旧修订、撤回记录仍可保留作审计，但纠正和导出只使用当前有效记录。没有取得裁图、空白裁图、损坏图片或图片哈希不符的记录不会当作可用学习样本。遇到保存失败，先解决原因，再重新核实并提交；不要把状态栏的排队提示当成成功回执。

建议在软件正常退出后备份整个 learning 目录和 .ocrproj.json 工程。备份也包含原图内容的局部裁图，按你自己对工程图的管理方式保管。不要只复制 feedback.json 而遗漏 images，也不要手工批量替换索引中的修订文字。

四、怎样验证本地反馈确实起作用

1. 选一块明确识错、原图清晰的文字，保存原识别内容和截图。
2. 修改成正确文字，然后等待上面的数据集导出完成。
3. 使用相同模型在另外的测试工程中重新识别同一原图，检查结果。
4. 同时测试相近但实际不同的型号，如 AM801/AM804、AM130(2)/AM130(3)，应保留各自真实文字。
5. 已人工校审的框默认锁定，普通重新识别不会覆盖它。因此不能仅凭原工程显示了你输入的正确文字，就认定模型已经学会。确需试验时，在测试副本中右键选择“按当前框重新识别（替换校审结果，可撤销）”，或者使用新的测试工程。

软件会比对裁图的形状、内容和局部差异，并拒绝互相矛盾的候选答案。不同数字只占一行很小一部分，因此仅比较整行平均相似度是不够的。当前反馈机制增加了局部图像差异核实，目的是减少把相近型号误改成同一个答案的情况；仍需用你的代表性图纸复查。

五、导出数据集是什么，能训练哪一部分

入口：顶部“导出 PDF”图标右侧箭头 → “导出校审训练数据集…”。
导出范围：当前选择的模型反馈库中的有效样本，不仅限于当前页，也不限于当前图纸。要导出另一个自定义模型，先选中那个模型。多个自定义模型要分别导出。

导出目录形式：
你选择的目录\learned_feedback\模型目录标识\
    images\feedback_0000000.png
    images\feedback_0000001.png
    rec_gt.txt
    metadata.json

rec_gt.txt 使用 UTF-8。每行是相对图片路径、一个真实 Tab 字符、正确文字。例如下面两列之间是 Tab：
images/feedback_0000000.png	喷码:B131.A
images/feedback_0000001.png	端子:AM84(3)

metadata.json 包含原文件指纹、页码、区域、修订事件等信息，便于按来源分组与审查。请用新目录导出每个训练版本；不要把几个不同模型的样本直接混在同一个目录中覆盖。检查导出数量、图片是否完整清晰、每张图与真值是否一致。

这是一份“已裁好的单行图像 → 文字”的识别训练数据集，适用于 rec。它没有完整图页的所有文字多边形标注，因此不能直接用来训练 det，也不能直接训练角度分类器。

需要区分三个问题：
检测 det：在哪里有文字、框是否漏掉或把多行合并；需要整页或图块及全部文字区域标注。
识别 rec：一个正确文字框里具体是什么字符；本次导出的裁图与真值用于这一层。
方向：文字该按哪个方向读取；需要正确方向信息、可靠裁图或专门方向样本。

你截图里的左侧前缀漏掉、中文多行被误识为竖排，首先涉及检测、分块及框布局。仅微调 rec 不一定解决漏框。型号的 O/0、I/1、小数点和括号等误读更适合用识别裁图微调。先分清错误来自哪一层，避免把一个模型的训练当成所有问题的解法。

六、怎样把积累的样本整理成可训练、可验收的数据

1. 每次训练都冻结一份导出快照，写下日期、软件版本、样本量和来源图纸。旧快照保留。
2. 人工抽检图片和真值，剔除模糊、裁掉字符、包含多行却只有一行答案、角度错误或答案不确定的样本。
3. 按 metadata.json 的 source_sha256/原图纸来源分组，再分训练、验证、测试集。同一图纸的相邻区域、重复型号、几乎相同的裁图不要分到不同集合；同一图纸的不同导出版本也视为同一来源。
4. 可以先按约 80%/10%/10% 分组。几百到上千条经过核实、覆盖多张图纸的样本可以作为起步尝试。这些是实践建议，不是达到效果的门槛，也不是准确率保证。若只有一两张图纸，独立新图纸测试比机械凑比例更重要。
5. 收集真实 SHX 字形、不同字号和线宽、数字与字母混排、括号、下划线、斜体、合法旋转等例子；同时保留一定比例原本正确的中文和通用样本，检查专用字体改善后是否损害一般内容。
6. 训练集用于调整权重；验证集用于选择参数和模型；测试集用于最后一次独立验收。反复根据测试集成绩调参，会使测试失去独立性。

把一份导出目录复制到 PaddleOCR/train_data/ocrx_feedback 后，可建立：
train_data/ocrx_feedback/images/...
train_data/ocrx_feedback/train_list.txt
train_data/ocrx_feedback/val_list.txt
train_data/ocrx_feedback/test_list.txt

三个清单的行格式与 rec_gt.txt 相同，只把来源分到对应列表；模型配置里的 data_dir 指向 ./train_data/ocrx_feedback。不要把同一 rec_gt.txt 同时作为训练与验证列表。

PaddleOCR 的官方识别训练说明支持这种“图片路径 + Tab + 真值”格式，并要求训练和推理使用对应字典：
https://github.com/PaddlePaddle/PaddleOCR/blob/main/docs/version2.x/ppocr/model_train/recognition.md

七、真正微调模型怎样做（外部操作示例，未在本机执行）

训练需要独立的 PaddleOCR/PaddlePaddle 环境，以及与你选用架构匹配的可训练权重（通常为 .pdparams）。OCRX 自带的是推理 ONNX；不能直接把这个 ONNX 路径填入 Global.pretrained_model 当作 Paddle 训练检查点。先取得相应架构的官方训练权重，或使用你自己保存的训练检查点。

不要在 OCRX 的运行包内安装训练依赖。创建单独训练工作目录和环境，记录 PaddleOCR 提交版本、Paddle/Paddle2ONNX 版本、训练配置、字典和训练/验证列表。

当前内置识别模型是 PP-OCRv6 Small。官方对应配置是 configs/rec/PP-OCRv6/PP-OCRv6_small_rec.yml，使用 SVTR_LCNet/PPLCNetV4 small 和对应的字符字典。请复制完整官方配置再修改数据与微调参数，保留匹配架构；不能把旧 PP-OCRv3 示例架构或别的训练权重直接混用。
官方当前配置核实来源：
https://github.com/PaddlePaddle/PaddleOCR/blob/main/configs/rec/PP-OCRv6/PP-OCRv6_small_rec.yml

在 PaddleOCR 训练工作目录，PowerShell 示例：
Copy-Item -LiteralPath '.\configs\rec\PP-OCRv6\PP-OCRv6_small_rec.yml' -Destination '.\configs\rec\PP-OCRv6\OCRX_SHX_v1.yml'

编辑这个完整配置中的对应项：
Global.pretrained_model：匹配 PP-OCRv6 small 架构的训练权重路径。
Global.save_model_dir：./output/OCRX_SHX_v1。
Global.character_dict_path：与权重匹配的字典；保持字符顺序。不要为了加入几个词而随意重排或缩减字典。
Train.dataset.data_dir 和 Eval.dataset.data_dir：./train_data/ocrx_feedback。
Train.dataset.label_file_list：训练列表路径。
Eval.dataset.label_file_list：验证列表路径。
Global.max_text_length：应容纳你的最长真值；官方配置的默认值是 25。调整时要保持整个配置中的关联项一致。
学习率、批大小、训练轮数、评估频率：先用小规模试验确认环境和数据能跑，再根据验证集选择。较低学习率、小批量和较短初始训练周期可作为微调尝试，不能直接把默认大数据集参数当成你的小样本最优参数。
Windows 数据加载若遇到多进程问题，可先将训练和验证的 num_workers 设为 0；CPU/GPU 能否训练取决于独立 Paddle 环境，而不是 OCRX 是否已经安装显卡推理组件。

训练、验证、导出示例（路径中的 best_accuracy 是示例检查点前缀，须换成实际存在的权重）：
python tools/train.py -c configs/rec/PP-OCRv6/OCRX_SHX_v1.yml -o Global.pretrained_model=./pretrain_models/PP-OCRv6_small_rec/best_accuracy Global.save_model_dir=./output/OCRX_SHX_v1
python tools/eval.py -c configs/rec/PP-OCRv6/OCRX_SHX_v1.yml -o Global.checkpoints=./output/OCRX_SHX_v1/best_accuracy
python tools/export_model.py -c configs/rec/PP-OCRv6/OCRX_SHX_v1.yml -o Global.pretrained_model=./output/OCRX_SHX_v1/best_accuracy Global.save_inference_dir=./inference/OCRX_SHX_v1

训练输出是检查点，部署需要先导出推理模型，再按已安装 Paddle2ONNX 对对应推理格式进行转换。新版 Paddle 的推理结构文件可能是 inference.json，旧 IR 示例为 inference.pdmodel；以实际导出文件和所用工具版本为准。不要盲目把两种格式的文件名互换。

若你的导出确实得到 inference.pdmodel 与 inference.pdiparams，官方文档中的传统命令形式为：
paddle2onnx --model_dir ./inference/OCRX_SHX_v1 --model_filename inference.pdmodel --params_filename inference.pdiparams --save_file ./inference/OCRX_SHX_v1/rec.onnx --opset_version 11 --enable_onnx_checker True

这条是兼容性示例，不是对任何新版 PP-OCRv6 导出的转换成功保证。转换后需要检查动态输入尺寸、算子/IR 版本、预处理和解码输出，实际运行 OCRX 的 CPU 以及所需 GPU 后端验证。仅把模型扩展名改成 .onnx 不构成转换。
官方转换说明：
https://github.com/PaddlePaddle/PaddleOCR/blob/main/deploy/paddle2onnx/readme.md

OCRX 支持 rec_keys 字典路径。使用自定义识别模型时，字典内容和顺序必须与训练/导出模型一致；模型自带的 dictionary 元数据也必须一致，不能只凭文件名判断匹配。RapidOCR 官方说明了将字典放入 ONNX 元数据以及读取它的方法：
https://github.com/RapidAI/RapidOCRDocs/blob/main/docs/blog/posts/rec_dict_onnx.md

八、怎样把自定义 ONNX 装入 OCRX

1. 保留完整运行包和原内置模型。在 EXE 旁新建 models/SHX-v1，放入已验证的 rec.onnx 和对应 dict.txt。若只改识别模型，可继续使用内置检测模型。
2. 首次使用时，内置配置通常在 EXE 旁的 _internal/model_profiles.json。如果 EXE 同目录还没有 model_profiles.json，先从 _internal 复制一份到 EXE 同目录，再编辑这份外部配置；已经存在外部配置时，先备份并保留其已有项。OCRX 优先读取 EXE 同目录的配置，否则读取 _internal 内置配置。该文件最外层是 {"profiles": [...]}，不是单独一个模型对象。
3. 在现有 profiles 数组中追加新条目，保留已有项。下面是包含默认项和新模型项的完整结构示例。请按你的实际文件保留其它既有配置，不要直接用它覆盖已经修改过的个人配置。

{
  "profiles": [
    {
      "name": "RapidOCR PP-OCRv6 Small (CPU)",
      "display_name": "CPU",
      "engine": "rapidocr",
      "box_thresh": 0.45,
      "text_score": 0.45
    },
    {
      "name": "RapidOCR PP-OCRv6 Small (GPU · CUDA)",
      "display_name": "CUDA GPU",
      "engine": "rapidocr",
      "provider": "cuda",
      "box_thresh": 0.45,
      "text_score": 0.45
    },
    {
      "name": "RapidOCR PP-OCRv6 Small (GPU · DirectML)",
      "display_name": "DirectML GPU",
      "engine": "rapidocr",
      "provider": "directml",
      "box_thresh": 0.45,
      "text_score": 0.45
    },
    {
      "name": "RapidOCR Custom ONNX",
      "display_name": "自定义 ONNX",
      "engine": "rapidocr",
      "det_model": "models/det.onnx",
      "rec_model": "models/rec.onnx",
      "rec_keys": "models/dict.txt",
      "box_thresh": 0.40,
      "text_score": 0.40
    },
    {
      "name": "SHX-connector-rec-v1",
      "display_name": "工程线束专用 v1（CPU）",
      "engine": "rapidocr",
      "provider": "cpu",
      "det_model": null,
      "rec_model": "models/SHX-v1/rec.onnx",
      "rec_keys": "models/SHX-v1/dict.txt",
      "box_thresh": 0.45,
      "text_score": 0.45
    }
  ]
}

4. JSON 必须为有效 UTF-8，字符串用双引号；相对路径按 model_profiles.json 所在目录解析。重启 OCRX，选择“工程线束专用 v1（CPU）”。缺文件或后端不可用时，这个模型不能正常使用。
5. 同时准备 GPU 版本配置时，应在独立新条目中指定 provider 为 cuda 或 directml，并在实际后端验证兼容性。自定义配置按 name 隔离反馈；不同自定义名字不会像内置三模式那样自动共用一份库。
6. 发布下一次训练模型时使用 SHX-connector-rec-v2 和 models/SHX-v2 等新名字、目录，保留 v1。遇到回归，在模型下拉框选回 v1 或标准识别即可回滚；不要直接覆盖原 rec.onnx 使版本不可追踪。

九、怎样判断训练真的更适合你的场景

用从未参加训练、验证的新图纸评估，同一份测试图必须用原模型和新模型对比。记录完整行正确率、字符错误率、型号/数量/括号准确率、漏框和重复框、方向错误数、整页耗时。不要只看几个训练过的裁图变好了。

评估训练权重本身时，使用隔离的空反馈目录或新的模型版本名，避免本地记忆把模型错误纠正后，误以为网络已经学会。对整页测试还要记录检测框是否完整；rec 成绩好不能代替 det 验收。测试最终导出的 ONNX，与训练框架输出对照，确认转换、预处理和字典没有改变结果。

达到你设定的目标，并且原本正确的通用内容没有明显回退后，再日常使用。保留旧模型、配置、测试集、训练日志和有效样本快照，这样一次训练失败也能回退。

十、建议采用的长期循环

每次使用：识别 → 核实 → 修订/审核 → 后台保存有效样本。
定期整理：导出 → 抽检 → 按来源分组 → 记录错误类型与样本覆盖。
阶段更新：独立训练 → 验证选择 → ONNX 转换 → 新图纸回归 → 注册新版本模型。

日常本地反馈解决“见过且足够相似的图像反复识错”；经过独立验收的训练权重改善更广的字体和场景。把人工修订保留下来、保证真值正确、保留独立测试图纸，才是让 OCRX 持续适应你的工程线束图纸的可执行办法。
