Skip to main content

fast_canny/
workspace.rs

1use crate::kernel::{self, SobelKernel};
2use bumpalo::Bump;
3use std::time::Instant;
4
5impl std::fmt::Debug for CannyWorkspace {
6    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7        f.debug_struct("CannyWorkspace")
8            .field("width", &self.width)
9            .field("height", &self.height)
10            .field("capacity", &self.capacity)
11            .finish_non_exhaustive()
12    }
13}
14
15pub struct CannyWorkspace {
16    pub width: usize,
17    pub height: usize,
18    pub capacity: usize,
19    pub buffer_a: Vec<f32>, // 梯度幅值
20    pub buffer_b: Vec<f32>, // 高斯平滑输出
21    pub dir_map: Vec<u8>,   // 梯度方向(独立缓冲区)
22    pub edge_map: Vec<u8>,  // 最终边缘图
23    pub arena: Bump,
24    pub(crate) kernel: Box<dyn SobelKernel>,
25}
26
27impl CannyWorkspace {
28    pub fn new(width: usize, height: usize) -> Result<Self, crate::CannyError> {
29        if width < 3 || height < 3 {
30            return Err(crate::CannyError::InvalidDimensions { width, height });
31        }
32        let t0 = Instant::now();
33        let capacity = width * height;
34        let arena_bytes = (capacity / 20) * std::mem::size_of::<usize>();
35        let ws = Self {
36            width,
37            height,
38            capacity,
39            buffer_a: vec![0.0f32; capacity],
40            buffer_b: vec![0.0f32; capacity],
41            dir_map: vec![0u8; capacity],
42            edge_map: vec![0u8; capacity],
43            arena: Bump::with_capacity(arena_bytes),
44            kernel: kernel::detect(),
45        };
46        log::info!(
47            "[CannyWorkspace::new] {}x{}, ~{} KB, {:?}",
48            width,
49            height,
50            (capacity * 10 + arena_bytes) / 1024,
51            t0.elapsed()
52        );
53        Ok(ws)
54    }
55
56    /// 帧间重置:O(W×H) 清零 edge_map,O(1) 重置 arena。
57    #[inline(always)]
58    pub fn reset(&mut self) {
59        self.arena.reset();
60        self.edge_map.fill(0);
61    }
62
63    #[inline(always)]
64    pub(crate) fn kernel(&self) -> &dyn SobelKernel {
65        self.kernel.as_ref()
66    }
67}