Skip to content

feat(ocr): enable configurable OpenCV ONNX backend - #58

Open
axechaso wants to merge 1 commit into
EasyConNS:devfrom
axechaso:feat/generic-onnx-ocr
Open

axechaso wants to merge 1 commit into
EasyConNS:devfrom
axechaso:feat/generic-onnx-ocr

Conversation

@axechaso

Copy link
Copy Markdown
Contributor

背景

仓库中已经有 OnnxDetector、OnnxRecognizer 和 OpenCV 5 DNN 的托管封装,但当前随 Windows 程序分发的 ezcv_native.dll 没有导出 DNN/ONNX 入口,实际初始化会抛出 EntryPointNotFoundException;脚本层也没有可用的四参数 OCR_INIT 入口来选择 ONNX 后端。

这个 PR 把现有能力补成可实际使用、可配置的通用 ONNX OCR 后端。默认 Tesseract 路径保持不变,也没有引入额外的 ONNX Runtime 包。

实现内容

  • OcrEngineCache 根据 engineMode 选择 Tesseract 或 OpenCV ONNX 工厂,支持 ONNX、ONNX:CPU、ONNX:OPENCL、ONNX:VULKAN、ONNX:CUDA。
  • 新增通用 JSON 模型清单,可配置检测/识别模型路径、字符词典、输入尺寸与对齐、通道顺序、归一化参数、CTC blank 索引和可选空格类别。
  • CTC 解码支持多字符 Unicode 词典项,以及 [T,C]、[1,T,C] 和尾部单例维度输出。
  • 修正 OpenCV BlobFromImage 的归一化语义,并让 Paddle DB 检测预处理参数也可配置。
  • 开放 ECS 的二参数和四参数 OCR_INIT;显式初始化 ONNX 后,后续 OCR 调用不会再把同一语言静默覆盖回 Tesseract。
  • 初始化替换失败时保留原来可工作的识别器,并通过 LastError 暴露失败原因。
  • 用 OpenCV 5.0.0 重新构建 Windows ezcv_native.dll,使现有 DNN P/Invoke 入口真正存在。该 DLL 只依赖仓库现有的 opencv_world500.dll 和 KERNEL32.dll。
  • 增加使用文档和单元/集成测试。

范围边界

  • 不包含任何特定游戏的脚本、模型、词典、标签、截图、坐标、名称表或识别规则。
  • 不增加独立 OCR 窗口;仍通过原有脚本/宿主 OCR 接口使用。
  • 不提交测试用 ONNX 模型。
  • 当前通用适配层明确支持 Paddle 风格的 DB 检测与 CTC 识别模型;ONNX 只是容器格式,其他输入输出协议仍需要相应适配。

ECS 示例

$ok = OCR_INIT("sample", __APP__ + "/Models/sample", "ONNX", "sample_ocr.json")
$text = OCR(100, 80, 420, 64, "sample")
$confidence = OCR_CONF()

完整清单格式见 docs/OnnxOcr.md。

验证

  • dotnet format EasyCon2.slnx --verify-no-changes --no-restore:通过。
  • ONNX 专项测试(不提供外部模型):16 通过,1 跳过。
  • 使用本地通用 PaddleOCR ONNX 模型做真实 OpenCV 5 DNN 推理:17/17 通过;验证结果文本非空且置信度有效。模型未提交。
  • 完整解决方案排除一项仓库既有基线失败后:EasyCon.Lsp.Tests 66/66、EasyCon.Tests 733 通过/17 跳过、EasyCon.WinInput.Tests 11/11。
  • 未排除时仅有既有 CsvTestExample_AutoLoadAndShadowUntilFfi 失败:该测试在 Windows 上实际未抛异常,但断言分支仍要求捕获“非 Windows 平台”异常,与本次 OCR 改动无关。
  • 已核对新版 ezcv_native.dll 导出 ezcv_dnn_read_net_from_onnx、ezcv_dnn_blob_from_image、ezcv_dnn_net_set_input、ezcv_dnn_net_forward 等入口。
  • 仓库 opencv_world500.dll 与 OpenCV 5.0.0 官方 Windows 包 SHA-256 一致:7BC06231BF3CFD287E0B6853A78F78E00CEB58266F3CB49642F428EA6F4D1518。

@ca1e

ca1e commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

谢谢这份 PR,PR 描述里的验证都做得很扎实——我在本地把构建、测试和 DLL 声明逐项复核了一遍,结果和描述一致。不过目前有一个合并层面的阻塞问题需要先解决:这个分支基于 0718a15,而 dev 上的 29d6321(ECX capability host model)已经把整个 EzCv 项目连同 ezcv_native.dll 和 CvDnn 封装一起删除,视觉栈迁移到了 OpenCvSharp5.runtime.* NuGet 包。git merge-tree 确认有三处冲突,其中 ezcv_native.dll 是 modify/delete——重新分发这个 DLL 的前提在当前 dev 上已经不存在了,原来 EntryPointNotFoundException 的问题 dev 已经用另一种方式解决;OnnxOcrEngine.cs 也是内容冲突,因为 dev 版本已改用 OpenCvSharp/OpenCvSharp.Dnn

代码本身逐行看下来质量很高,这部分工作不会白费。BlobFromImage 归一化语义的修复是真 bug:OpenCV 是先减 mean 再乘 scale,旧检测代码 mean 用 0-1 尺度配 scale=1/255,mean 项实际上被抵消了 255 倍,识别侧同理,换算成 0-255 尺度的 mean 才是对的。CTC 解码器重写(多字符 Unicode 词条、可配 blankIndex、词典与类数一致性校验、尾部单例维度)我把去重/blank 跳过/索引映射的边界都核对过,是对的。OcrEngineCache 改成先创建成功再 Dispose 旧引擎的修复 + LastError 也很好,有测试锁住。StdLib 里删掉 OCR 内嵌的 OCR_INIT $lang 我确认过三个宿主的 DefaultDataPath 都是 BaseDirectory + "Tessdata",与原来的 __APP__ + "/Tessdata" 等价,行为保持。

建议 rebase 到 29d6321 之后这样处理:丢掉 DLL 变更;把清单加载(OnnxOcrModelConfig)、预处理修复和 PaddleCtcDecoder 移植到 OpenCvSharp5 版的 OnnxOcrEngine.cs 上(注意 dev 的 OnnxEngineFactory 边界仍然收 GpuBackend 并由 OnnxProviderMapper 映射,所以 OcrEngineCacheParseOnnxBackend 和清单配置基本能原样接上);OcrEngineCacheStdLib、测试和 docs/OnnxOcr.md 可以保留。另外 dev 新增的 docs/Functions.md 之后需要补一下 OCR_INIT 两参/四参签名的说明。

本地复核记录(独立 worktree,基于 5afa382):dotnet build EasyCon2.slnx -c Release 0 错误;OnnxOcr 专项 16 通过 / 1 跳过;全套 EasyCon.Tests 747 通过 / 0 失败(macOS,提到的 Windows 基线失败项在 macOS 本就通过,与本次改动无关);新版 DLL 导出表确认含 ezcv_dnn_read_net_from_onnx 等入口,导入表仅 opencv_world500.dll + KERNEL32.dll,与描述一致。

几个小事顺带提一下:AlignWidthmultiple > maximum 的病态配置下会返回非对齐宽度(如 multiple=32、max=20 时返回 20),ValidateOptions 可以拦一下这个组合;PreprocessRecSwapRedBlue=false 时那次 ConvertTo 是纯拷贝,识别路径写入的是另一个 Mat,可以直接用 src 省掉;DefaultEngineMode/DefaultPsmode 目前没有宿主接线,默认值等价旧行为所以无害,但也意味着 ONNX 只能通过显式四参 OCR_INIT 进入。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants