Skip to content

Features Module Reference

Provides feature detection, descriptor computation, and descriptor matching.

FeatureDetector

rust
pub enum FeatureType {
    ORB,
    BRISK,
    AKAZE,
    SIFT,
}

pub struct FeatureDetector;

impl FeatureDetector {
    pub fn new(detector_type: FeatureType) -> Self;
    pub fn with_max_features(self, max: usize) -> Self;
    pub fn detect<B: Backend>(&self, image: &Image<B>) -> Result<Vec<KeyPoint>>;
    pub fn compute<B: Backend>(&self, image: &Image<B>, keypoints: &[KeyPoint]) -> Result<Tensor<B, 2>>;
}

KeyPoint

rust
pub struct KeyPoint {
    pub pt: Point<f64>,
    pub size: f64,
    pub angle: f64,
    pub response: f64,
    pub octave: i32,
    pub class_id: i32,
}

impl KeyPoint {
    pub fn new(x: f64, y: f64, size: f64) -> Self;
}

BFMatcher

Brute-force matcher for comparing feature descriptors.

rust
pub struct BFMatcher;

impl BFMatcher {
    pub fn match_descriptors<B: Backend>(
        &self,
        query: &Tensor<B, 2>,
        train: &Tensor<B, 2>,
    ) -> Result<Vec<DMatch>>;
}

DMatch

rust
pub struct DMatch {
    pub query_idx: usize,
    pub train_idx: usize,
    pub img_idx: usize,
    pub distance: f32,
}

Example

rust
use iris::prelude::*;
use burn::backend::wgpu::Wgpu;

type Backend = Wgpu;
let device = Default::default();
let img = Image::<Backend>::open("input.jpg", &device)?;

// Detect keypoints
let detector = FeatureDetector::new(FeatureType::ORB).with_max_features(500);
let keypoints = detector.detect(&img)?;
println!("Detected {} keypoints", keypoints.len());

// Compute ORB descriptors
let descriptors = detector.compute(&img, &keypoints)?;
println!("Descriptor shape: {:?}", descriptors.dims());

Template Matching

rust
pub enum TemplateMatchMethod {
    TmSqdiff,        // Sum of squared differences
    TmSqdiffNormed,  // Normalized SSD
    TmCcorr,         // Cross-correlation
    TmCcorrNormed,   // Normalized cross-correlation
    TmCcoeff,        // Cross-correlation coefficient
    TmCcoeffNormed,  // Normalized cross-correlation coefficient
}

pub fn template_match<B: Backend>(
    source: &Image<B>,
    template: &Image<B>,
    method: TemplateMatchMethod,
) -> Result<Tensor<B, 2>>;

// Also available as a method on Image:
impl<B: Backend> Image<B> {
    pub fn template_match(&self, template: &Image<B>, method: TemplateMatchMethod)
        -> Result<Tensor<B, 2>>;
}

Example

rust
use iris::prelude::*;

let device = WgpuDevice::default();
let source: Image<Wgpu> = Image::open("scene.png", &device)?;
let template: Image<Wgpu> = Image::open("object.png", &device)?;

// Find the object in the scene using normalized cross-correlation
let result = source.template_match(&template, TemplateMatchMethod::TmCcoeffNormed)?;

// Result is a 2D tensor where the maximum indicates best match position
let flat: Vec<f32> = result.clone().into_data().iter::<f32>().collect();
let max_idx = flat.iter().enumerate().max_by(|a, b| a.1.partial_cmp(b.1).unwrap()).unwrap().0;
let match_y = max_idx / result.dims()[1];
let match_x = max_idx % result.dims()[1];
println!("Best match at ({}, {})", match_x, match_y);

FLANN Matcher

Fast Library for Approximate Nearest Neighbors matcher for efficient descriptor matching on large datasets.

rust
pub struct FlannMatcher {
    k: usize,
    trees: usize,
    checks: usize,
}

impl FlannMatcher {
    pub fn new() -> Self;
    pub fn with_k(self, k: usize) -> Self;
    pub fn with_trees(self, trees: usize) -> Self;
    pub fn with_checks(self, checks: usize) -> Self;
    pub fn find_matches<B: Backend>(
        &self,
        desc1: &Tensor<B, 2>,
        desc2: &Tensor<B, 2>,
    ) -> Result<Vec<DMatch>>;
}

Parameters

FieldDefaultDescription
k2Number of nearest neighbors to find per query descriptor.
trees5Number of trees in the KD-tree index. More trees improve accuracy at cost of speed.
checks32Number of checks during search. Higher values improve accuracy.

Example

rust
use iris::prelude::*;

let device = WgpuDevice::default();
let img1 = Image::<Wgpu>::open("frame1.jpg", &device)?;
let img2 = Image::<Wgpu>::open("frame2.jpg", &device)?;

let detector = FeatureDetector::new(FeatureType::ORB).with_max_features(1000);
let kp1 = detector.detect(&img1)?;
let kp2 = detector.detect(&img2)?;
let desc1 = detector.compute(&img1, &kp1)?;
let desc2 = detector.compute(&img2, &kp2)?;

// Fast approximate matching with FLANN
let matcher = FlannMatcher::new().with_k(2).with_trees(8);
let matches = matcher.find_matches(&desc1, &desc2)?;
println!("Found {} matches", matches.len());

Released under the MIT License.