feat(model): 新增 ModelLoader 链式构建 API 及 ORT GPU/Tract 多线程配置

- 在 ddddocr-core 中定义 ModelBuilder Trait 及其错误类型
- ddddocr-ort 支持 use_gpu、device_id 及 num_threads 链式配置与 CUDA 硬件加速
- ddddocr-tract 基于 multithread-mm 特性支持 CPU 线程数控制
- 支持基于 tract-linalg 配置推理线程数,显式引入 tract-linalg 的 multithread-mm 特性,控制 GEMM 算子并发
- 优化线程池加载策略,适配 Tokio 异步及 CLI 等多场景
This commit is contained in:
2026-07-27 20:22:24 +08:00
parent 44dae08221
commit 7d159c5702
28 changed files with 1583 additions and 70 deletions

View File

@@ -1,18 +1,17 @@
use anyhow::Context;
use ddddocr_core::det::DetectionResult;
use ddddocr_core::{Detector, ModelMetadata, Normalization, Ocr, Slider};
use ddddocr_core::{DetectionResult, ModelBuilder};
use ddddocr_core::{Detector, ModelMetadata, Normalization, Slider};
// 假设你的包名是这个
use ddddocr_tract::{DetSession, OcrSession,OcrBuilder};
use ddddocr_tract::{DetSession, OcrBuilder, OcrSession};
use image::{DynamicImage, ImageBuffer, Luma, Rgb};
use std::fs;
use std::path::Path;
use tract_onnx::model;
mod char_slice;
use char_slice::CHARSET_BETA;
use ddddocr_core::ocr::Resize;
use ddddocr_core::Resize;
use ddddocr_tract::loader::ModelLoader;
use ddddocr_tract::loader::{ TractModelLoader};
fn load_image<P: AsRef<Path>>(path: P) -> anyhow::Result<image::DynamicImage> {
// 1. 先将泛型转为具体的 &Path 引用
@@ -105,10 +104,9 @@ fn save_rust_result(result: &ImageBuffer<Luma<f32>, Vec<f32>>, filename: &str) {
}
#[test]
fn test_full_classification() {
let model = ModelLoader::model_for_path(
"D:\\CNWei\\CNW\\Rust\\ddddocr-rs\\models\\common_sml2h3_f32.onnx",
)
.expect("模型加载失败");
let model = TractModelLoader::builder()
.model_for_path("D:\\CNWei\\CNW\\Rust\\ddddocr-rs\\models\\common_sml2h3_f32.onnx")
.expect("模型加载失败");
let metadata = ModelMetadata::from_static_slice(
CHARSET_BETA,
false,
@@ -127,7 +125,8 @@ fn test_full_classification() {
// .predict(&img)
// .expect("识别过程出错")
// .into_text();
let result = OcrBuilder::new().build(&ocr)
let result = OcrBuilder::new()
.build(&ocr)
.predict(&img)
.expect("识别过程出错")
.into_text();
@@ -138,7 +137,8 @@ fn test_full_classification() {
#[test]
fn test_det_load() -> anyhow::Result<()> {
let det_model =
ModelLoader::model_for_path("D:\\CNWei\\CNW\\Rust\\ddddocr-rs\\models\\common_det.onnx")
TractModelLoader::builder()
.model_for_path("D:\\CNWei\\CNW\\Rust\\ddddocr-rs\\models\\common_det.onnx")
.expect("模型加载失败");
let det = DetSession::new(det_model);
let image_path = "D:/CNWei/CNW/Rust/ddddocr-rs/samples/det1.png";
@@ -240,9 +240,11 @@ fn test_real_slide_comparison() {
#[test]
fn test_resolve_shape_logic_direct() {
// 创建一个哑 ModelLoader 实例session 用不上,因为我们直接测私有方法)
let loader = ModelLoader::model_for_path(
let loader = TractModelLoader::builder()
.model_for_path(
// "D:\\CNWei\\CNW\\Rust\\ddddocr-rs\\models\\common_sml2h3_f32.onnx",
"D:\\CNWei\\CNW\\Rust\\ddddocr-rs\\models\\common_huashi666_i64.onnx",
)
.expect("建立测试模型图失败");
println!("{:?}", loader.model().inputs);
}