1pub mod gpu_sift;
2pub mod gpu_sift_v2;
3pub mod keypoints;
4pub mod sift;
5pub mod utils;
6#[cfg(target_arch = "wasm32")]
7pub mod wasm;
8
9use std::str::FromStr;
10
11pub use gpu_sift::{GpuSiftConfig, GpuSiftContext};
13pub use gpu_sift_v2::{GpuSiftConfigV2, GpuSiftV2};
14pub use keypoints::KeyPoint;
15pub use sift::{convert_f32_to_grayimage_normalized, load_image_dyn, save_gray_image, Sift};
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum SiftBackend {
20 Cpu,
22 WebGpu,
24 WebGpuWithCpuFallback,
26 WebGpuV2,
28}
29
30impl Default for SiftBackend {
31 fn default() -> Self {
32 SiftBackend::WebGpuWithCpuFallback
33 }
34}
35
36impl FromStr for SiftBackend {
37 type Err = String;
38
39 fn from_str(value: &str) -> Result<Self, Self::Err> {
40 let normalized = value.trim().to_lowercase();
41 match normalized.as_str() {
42 "cpu" => Ok(SiftBackend::Cpu),
43 "webgpu" | "wgpu" | "gpu" => Ok(SiftBackend::WebGpu),
44 "auto" | "fallback" | "prefer-gpu" => Ok(SiftBackend::WebGpuWithCpuFallback),
45 "gpuv2" | "gpu-v2" | "webgpu-v2" | "v2" => Ok(SiftBackend::WebGpuV2),
46 _ => Err(format!("Unknown SIFT backend: {value}")),
47 }
48 }
49}
50
51use image::{open, DynamicImage, GrayImage, Rgb, RgbImage}; use imageproc::drawing::{draw_filled_circle_mut, draw_line_segment_mut}; pub fn load_and_convert_image(path: &str) -> GrayImage {
57 let img = open(path).expect("Failed to open image");
58 img.into_luma8()
59}
60
61pub fn draw_keypoints_to_image(
71 img: &DynamicImage,
72 keypoints: &[KeyPoint],
73 color: Rgb<u8>,
74) -> RgbImage {
75 let mut rgb_image = img.to_rgb8();
77
78 for kp in keypoints {
80 let x = kp.x;
81 let y = kp.y;
82 let size: f32 = 2.0; let angle = kp.angle; let radius = (size * 3.0).round() as i32;
88 let display_radius = radius.max(2);
90
91 draw_filled_circle_mut(&mut rgb_image, (x as i32, y as i32), display_radius, color);
93
94 let x_end = x + (display_radius as f32 * angle.cos());
96 let y_end = y + (display_radius as f32 * angle.sin());
97
98 draw_line_segment_mut(
100 &mut rgb_image,
101 (x, y), (x_end, y_end), color,
104 );
105
106 draw_filled_circle_mut(
108 &mut rgb_image,
109 (x as i32, y as i32),
110 1, color,
112 );
113 }
114
115 rgb_image
116}