feat: 优化 slide.rs

This commit is contained in:
2026-05-11 22:54:05 +08:00
parent 0df9022411
commit 0923d92150
3 changed files with 115 additions and 96 deletions

View File

@@ -1,23 +1,24 @@
use ddddocr_rs::models::slide::Slide;
use ddddocr_rs::{DdddOcr, DdddOcrBuilder}; // 假设你的包名是这个
use image::Rgb;
use std::fs;
use std::path::Path;
use image::Rgb;
use ddddocr_rs::{DdddOcr, DdddOcrBuilder}; // 假设你的包名是这个
use ddddocr_rs::models::slide::Slide;
fn load_image<P: AsRef<Path>>(path: P) -> anyhow::Result<image::DynamicImage> {
// 1. 先将泛型转为具体的 &Path 引用
let path_ref = path.as_ref();
// 2. 调用 open 时传入引用utils::open 支持 AsRef<Path>
image::open(path_ref)
.map_err(|e| {
// 3. 此时 path_ref 依然有效,可以安全地在闭包中使用
anyhow::anyhow!("无法加载图片 {:?}: {}", path_ref, e)
})
image::open(path_ref).map_err(|e| {
// 3. 此时 path_ref 依然有效,可以安全地在闭包中使用
anyhow::anyhow!("无法加载图片 {:?}: {}", path_ref, e)
})
}
/// 将检测结果绘制在图像上并保存
fn save_debug_image( image_bytes: &[u8], bboxes: &Vec<Vec<i32>>, output_path: &str) -> anyhow::Result<()> {
fn save_debug_image(
image_bytes: &[u8],
bboxes: &Vec<Vec<i32>>,
output_path: &str,
) -> anyhow::Result<()> {
let dynamic_img = image::load_from_memory(image_bytes)?;
let mut img = dynamic_img.to_rgb8();
let (width, height) = img.dimensions();
@@ -35,16 +36,24 @@ fn save_debug_image( image_bytes: &[u8], bboxes: &Vec<Vec<i32>>, output_path: &s
img.put_pixel(x, y1, red);
img.put_pixel(x, y2, red);
// 如果要加粗,多画一行
if y1 + 1 < height { img.put_pixel(x, y1 + 1, red); }
if y2.saturating_sub(1) > 0 { img.put_pixel(x, y2 - 1, red); }
if y1 + 1 < height {
img.put_pixel(x, y1 + 1, red);
}
if y2.saturating_sub(1) > 0 {
img.put_pixel(x, y2 - 1, red);
}
}
// 绘制纵向线条
for y in y1..=y2 {
img.put_pixel(x1, y, red);
img.put_pixel(x2, y, red);
// 如果要加粗,多画一列
if x1 + 1 < width { img.put_pixel(x1 + 1, y, red); }
if x2.saturating_sub(1) > 0 { img.put_pixel(x2 - 1, y, red); }
if x1 + 1 < width {
img.put_pixel(x1 + 1, y, red);
}
if x2.saturating_sub(1) > 0 {
img.put_pixel(x2 - 1, y, red);
}
}
}
@@ -66,43 +75,44 @@ fn test_full_classification() {
assert!(!result.is_empty());
}
#[test]
fn test_det_load()->anyhow::Result<()>{
fn test_det_load() -> anyhow::Result<()> {
let det = DdddOcrBuilder::new().det().build()?;
let image_path = "samples/det1.png";
let image_bytes = fs::read(image_path)
.map_err(|e| anyhow::anyhow!("无法读取图片 {}: {}", image_path, e))?;
let image_bytes =
fs::read(image_path).map_err(|e| anyhow::anyhow!("无法读取图片 {}: {}", image_path, e))?;
println!("图片读取成功,字节大小: {}", image_bytes.len());
let bboxes =det.detection(&image_bytes)?;
println!(":?{}",det);
let bboxes = det.detection(&image_bytes)?;
println!(":?{}", det);
println!("检测到的目标数量: {}", bboxes.len());
if bboxes.is_empty() {
println!("未检测到任何目标。");
} else {
save_debug_image(&image_bytes, &bboxes, "samples/result.jpg")?;
for (i, bbox) in bboxes.iter().enumerate() {
println!("目标 [{}]: x1={}, y1={}, x2={}, y2={}", i, bbox[0], bbox[1], bbox[2], bbox[3]);
println!(
"目标 [{}]: x1={}, y1={}, x2={}, y2={}",
i, bbox[0], bbox[1], bbox[2], bbox[3]
);
}
}
Ok(())
}
#[test]
fn test_real_slide_match() {
let engine = Slide::new();
// 1. 加载你准备好的测试图
// 假设图片放在项目根目录下的 assets 文件夹
let target_img = load_image("samples/hua.png")
.expect("请确保 samples/hua.png 存在");
let bg_img = load_image("samples/huatu.png")
.expect("请确保 samples/huatu.png 存在");
let target_img = load_image("samples/hua.png").expect("请确保 samples/hua.png 存在");
let bg_img = load_image("samples/huatu.png").expect("请确保 samples/huatu.png 存在");
// 2. 执行匹配
// 如果是那种带有明显阴影边缘的复杂滑块,建议 simple_target 传 false
let start = std::time::Instant::now();
let result = engine.slide_match(&target_img, &bg_img, false)
let result = engine
.slide_match(&target_img, &bg_img, false)
.expect("Slide match 执行失败");
let duration = start.elapsed();
@@ -126,15 +136,14 @@ fn test_real_slide_comparison() {
// 1. 加载你准备好的测试图
// 假设图片放在项目根目录下的 assets 文件夹
let target_img = load_image("samples/ken.jpg")
.expect("请确保 samples/ken.jpg 存在");
let bg_img = load_image("samples/kenyuan.jpg")
.expect("请确保 samples/kenyuan.jpg 存在");
let target_img = load_image("samples/ken.jpg").expect("请确保 samples/ken.jpg 存在");
let bg_img = load_image("samples/kenyuan.jpg").expect("请确保 samples/kenyuan.jpg 存在");
// 2. 执行匹配
// 如果是那种带有明显阴影边缘的复杂滑块,建议 simple_target 传 false
let start = std::time::Instant::now();
let result = engine.slide_comparison(&target_img, &bg_img)
let result = engine
.slide_comparison(&target_img, &bg_img)
.expect("Slide match 执行失败");
let duration = start.elapsed();
@@ -150,4 +159,4 @@ fn test_real_slide_comparison() {
assert_eq!(result.target_x, 171);
assert_eq!(result.target_y, 90);
assert!(result.confidence > 0.0);
}
}