refactor: 优化图像输入源设计,重构为零污染的 TryFromImage 特征
- 移除原有的 ImageInput 枚举,避免运行时匹配与所有权限制 - 引入自定义 TryFromImage 特征,专用于将不同来源安全转换为 ImageSource - 优化错误处理新增 InvalidBase64Header 错误信息 - 迁移 load_image_from_input 到 image_helper.rs 为后续剥离到业务层做准备
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
use anyhow::Context;
|
||||
use ddddocr_core::det::DetectionResult;
|
||||
use ddddocr_core::{DetBuilder, Detector, ModelMetadata, Ocr, Slider}; // 假设你的包名是这个
|
||||
use ddddocr_tract::{DetSession,OcrSession};
|
||||
use image::{DynamicImage, Rgb};
|
||||
use ddddocr_core::{DetBuilder, Detector, ModelMetadata, Ocr, Slider}; // 假设你的包名是这个
|
||||
use ddddocr_tract::{DetSession, OcrSession};
|
||||
use image::{DynamicImage, ImageBuffer, Luma, Rgb};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use anyhow::Context;
|
||||
use tract_onnx::prelude::{ShapeFact, TDim};
|
||||
|
||||
mod char_slice;
|
||||
@@ -67,7 +67,40 @@ fn save_debug_image(
|
||||
img.save(output_path)?;
|
||||
Ok(())
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
fn save_rust_result(result: &ImageBuffer<Luma<f32>, Vec<f32>>, filename: &str) {
|
||||
let (width, height) = result.dimensions();
|
||||
|
||||
// 1. 寻找最值进行归一化
|
||||
let mut max_val = f32::MIN;
|
||||
let mut min_val = f32::MAX;
|
||||
for p in result.pixels() {
|
||||
if p.0[0] > max_val {
|
||||
max_val = p.0[0];
|
||||
}
|
||||
if p.0[0] < min_val {
|
||||
min_val = p.0[0];
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 创建 8 位灰度图
|
||||
let mut out_buf = ImageBuffer::new(width, height);
|
||||
for y in 0..height {
|
||||
for x in 0..width {
|
||||
let val = result.get_pixel(x, y).0[0];
|
||||
let normalized = if max_val > min_val {
|
||||
((val - min_val) / (max_val - min_val) * 255.0) as u8
|
||||
} else {
|
||||
0u8
|
||||
};
|
||||
out_buf.put_pixel(x, y, Luma([normalized]));
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 保存
|
||||
DynamicImage::ImageLuma8(out_buf).save(filename).unwrap();
|
||||
println!("Rust 结果热力图已保存至: {}", filename);
|
||||
}
|
||||
#[test]
|
||||
fn test_full_classification() {
|
||||
// 1. 初始化模型
|
||||
@@ -84,7 +117,8 @@ fn test_full_classification() {
|
||||
.expect("模型加载失败");
|
||||
|
||||
// 2. 加载测试图片
|
||||
let img = image::open("D:/CNWei/CNW/Rust/ddddocr-rs/samples/code2.png").expect("测试图片不存在");
|
||||
let img =
|
||||
image::open("D:/CNWei/CNW/Rust/ddddocr-rs/samples/code2.png").expect("测试图片不存在");
|
||||
|
||||
// 3. 执行识别
|
||||
let result = Ocr::new(&ocr)
|
||||
@@ -117,7 +151,11 @@ fn test_det_load() -> anyhow::Result<()> {
|
||||
println!("未检测到任何目标。");
|
||||
} else {
|
||||
// 如果 save_debug_image 报错,记得去把它的入参类型和内部访问也改为 DetectionResult
|
||||
save_debug_image(&img, &bboxes, "D:/CNWei/CNW/Rust/ddddocr-rs/samples/result.jpg")?;
|
||||
save_debug_image(
|
||||
&img,
|
||||
&bboxes,
|
||||
"D:/CNWei/CNW/Rust/ddddocr-rs/samples/result.jpg",
|
||||
)?;
|
||||
|
||||
for (i, bbox) in bboxes.iter().enumerate() {
|
||||
// 【修改点 3】将原来的 bbox[0].. 索引访问改为结构体字段访问
|
||||
@@ -133,8 +171,10 @@ fn test_real_slide_match() {
|
||||
|
||||
// 1. 加载你准备好的测试图
|
||||
// 假设图片放在项目根目录下的 assets 文件夹
|
||||
let target_img = load_image("D:/CNWei/CNW/Rust/ddddocr-rs/samples/hua.png").expect("请确保 samples/hua.png 存在");
|
||||
let bg_img = load_image("D:/CNWei/CNW/Rust/ddddocr-rs/samples/huatu.png").expect("请确保 samples/huatu.png 存在");
|
||||
let target_img = load_image("D:/CNWei/CNW/Rust/ddddocr-rs/samples/hua.png")
|
||||
.expect("请确保 samples/hua.png 存在");
|
||||
let bg_img = load_image("D:/CNWei/CNW/Rust/ddddocr-rs/samples/huatu.png")
|
||||
.expect("请确保 samples/huatu.png 存在");
|
||||
|
||||
// 2. 执行匹配
|
||||
// 如果是那种带有明显阴影边缘的复杂滑块,建议 simple_target 传 false
|
||||
@@ -162,8 +202,10 @@ fn test_real_slide_comparison() {
|
||||
|
||||
// 1. 加载你准备好的测试图
|
||||
// 假设图片放在项目根目录下的 assets 文件夹
|
||||
let target_img = load_image("D:/CNWei/CNW/Rust/ddddocr-rs/samples/ken.jpg").expect("请确保 samples/ken.jpg 存在");
|
||||
let bg_img = load_image("D:/CNWei/CNW/Rust/ddddocr-rs/samples/kenyuan.jpg").expect("请确保 samples/kenyuan.jpg 存在");
|
||||
let target_img = load_image("D:/CNWei/CNW/Rust/ddddocr-rs/samples/ken.jpg")
|
||||
.expect("请确保 samples/ken.jpg 存在");
|
||||
let bg_img = load_image("D:/CNWei/CNW/Rust/ddddocr-rs/samples/kenyuan.jpg")
|
||||
.expect("请确保 samples/kenyuan.jpg 存在");
|
||||
|
||||
// 2. 执行匹配
|
||||
// 如果是那种带有明显阴影边缘的复杂滑块,建议 simple_target 传 false
|
||||
@@ -189,7 +231,10 @@ fn test_real_slide_comparison() {
|
||||
#[test]
|
||||
fn test_resolve_shape_logic_direct() {
|
||||
// 创建一个哑 ModelLoader 实例(session 用不上,因为我们直接测私有方法)
|
||||
let loader = ModelLoader::model_for_path("D:\\CNWei\\CNW\\Rust\\ddddocr-rs\\models\\common_sml2h3_f32.onnx",).expect("建立测试模型图失败");
|
||||
let md_info=&loader.model_info().context("信息");
|
||||
println!("md_info: {:?}",md_info);
|
||||
}
|
||||
let loader = ModelLoader::model_for_path(
|
||||
"D:\\CNWei\\CNW\\Rust\\ddddocr-rs\\models\\common_sml2h3_f32.onnx",
|
||||
)
|
||||
.expect("建立测试模型图失败");
|
||||
let md_info = &loader.model_info().context("信息");
|
||||
println!("md_info: {:?}", md_info);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user