abow 0.4.2

Visual bag of words for fast image matching
Documentation
#![cfg(feature = "opencv")]
use crate::{BowErr, BowResult, Desc};
use opencv::{
    self,
    prelude::{Feature2DTrait, MatTraitConst},
};
use std::{convert::TryInto, path::Path};

type CvImage = opencv::prelude::Mat;
type CvMat = opencv::core::Mat;

/// Extract orb keypoint descriptors from an image. Mostly for testing & example purposes.
fn orb_from_cvimage(cv_img: &CvImage) -> BowResult<Vec<Desc>> {
    // Create detector
    let mut orb = <dyn opencv::features2d::ORB>::default().unwrap();

    // Detect keypoints and compute descriptors
    let mut kps = opencv::types::VectorOfKeyPoint::new();
    let mut desc = CvMat::default();
    let mask = CvMat::default();
    orb.detect_and_compute(cv_img, &mask, &mut kps, &mut desc, false)?;

    // Copy data from CvMat into descriptor buffer
    std::panic::catch_unwind(|| {
        (0..kps.len())
            .map(|i| {
                (0..32)
                    .map(|j| *desc.at_2d::<u8>(i as i32, j).unwrap())
                    .collect::<Vec<_>>()
                    .try_into()
                    .unwrap()
            })
            .collect()
    })
    .map_err(|_| BowErr::OpenCvDecode)
}

/// Use opencv to load an image and extract orb keypoint descriptors.
pub fn load_img_get_kps<P: AsRef<Path>>(path: P) -> BowResult<Vec<Desc>> {
    let img: CvImage = opencv::imgcodecs::imread(
        path.as_ref().to_str().unwrap(),
        opencv::imgcodecs::IMREAD_GRAYSCALE,
    )
    .unwrap();
    orb_from_cvimage(&img)
}

/// Extract orb keypoint descriptors from all images in directory using opencv.
pub fn all_kps_from_dir<P: AsRef<Path>>(path: P) -> BowResult<Vec<Desc>> {
    let mut features: Vec<Desc> = Vec::new();
    for entry in (path.as_ref().read_dir()?).flatten() {
        println!("Extracting keypoint descriptors from {:?}", entry.path());
        features.extend(load_img_get_kps(&entry.path())?);
    }
    Ok(features)
}