feat: 完成 Rust 滑块匹配算法,修复透明留白导致的坐标偏移

- 实现灰度与边缘两种匹配模式
- 对齐 OpenCV NCC 算法逻辑
- 优化图像灰度化与 Alpha 通道转换
- 提升坐标计算精度至像素级
This commit is contained in:
2026-05-08 16:03:33 +08:00
parent 1a329ca273
commit 21bd1c93bf
8 changed files with 294 additions and 250 deletions

View File

@@ -1,6 +1,6 @@
use anyhow::{Context, Result};
use base64::{Engine as _, engine::general_purpose};
use image::{DynamicImage, GenericImageView, ImageBuffer, Rgb, RgbImage};
use image::{DynamicImage, GenericImageView, ImageBuffer, Luma, Rgb, RgbImage};
use std::path::{Path, PathBuf};
use tract_onnx::prelude::tract_ndarray::Array3;
@@ -60,3 +60,51 @@ pub fn png_rgba_white_preprocess(img: &DynamicImage) -> DynamicImage {
DynamicImage::ImageRgb8(background)
}
pub fn image_to_ndarray(img: &DynamicImage) -> Array3<u8> {
let (width, height) = img.dimensions();
// 1. 强制转为 RGB8 (丢弃 Alpha 通道,与 Python 的 target_mode='RGB' 对齐)
let rgb_img = img.to_rgb8();
// 2. 获取原始像素数据
let raw_data = rgb_img.into_raw();
// 3. 构造数组 (通道数改为 3)
Array3::from_shape_vec((height as usize, width as usize, 3), raw_data)
.expect("Failed to construct ndarray from image") // 建议显式报错,而不是返回全黑图
}
#[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);
}