#![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;
fn orb_from_cvimage(cv_img: &CvImage) -> BowResult<Vec<Desc>> {
let mut orb = <dyn opencv::features2d::ORB>::default().unwrap();
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)?;
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)
}
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)
}
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)
}