1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use thiserror::Error;
pub mod vocab;
pub use vocab::Vocabulary;
pub mod opencv_utils;
#[cfg(feature = "opencv")]
pub use opencv_utils::*;
pub type Desc = [u8; 32];
pub type BoW = Vec<f32>;
pub type DirectIdx = Vec<Vec<usize>>;
pub trait BoWTrait {
fn l1(&self, other: &Self) -> f32;
fn l2(&self, other: &Self) -> f32;
}
impl BoWTrait for BoW {
fn l1(&self, other: &Self) -> f32 {
1. - 0.5
* (self
.iter()
.zip(other)
.fold(0., |a, (b, c)| a + (b - c).abs()))
}
fn l2(&self, _other: &Self) -> f32 {
unimplemented!()
}
}
type Result<T> = std::result::Result<T, BowErr>;
#[derive(Error, Debug)]
pub enum BowErr {
#[error("Io Error")]
Io(#[from] std::io::Error),
#[cfg(feature = "bincode")]
#[error("Vocabulary Serialization Error")]
Bincode(#[from] bincode::Error),
#[cfg(feature = "opencv")]
#[error("Opencv Error")]
OpenCvInternal(#[from] opencv::Error),
#[cfg(feature = "opencv")]
#[error("Opencv Descriptor decode error")]
OpenCvDecode,
}
#[cfg(test)]
mod test {
use super::*;
use std::path::{Path, PathBuf};
#[ignore]
#[test]
fn test_recall() {
let features = all_kps_from_dir("data/train").unwrap();
println!("Detected {} ORB keypoints.", features.len());
for &k in &[6_usize, 8_usize, 10_usize] {
for &l in &[3_usize, 4_usize, 5_usize] {
for _ in 0..2 {
let voc = Vocabulary::create(&features, k, l).unwrap();
let mut bows: Vec<(PathBuf, BoW)> = Vec::new();
for entry in Path::new("data/test").read_dir().expect("Error").flatten() {
let new_feat = load_img_get_kps(&entry.path()).unwrap();
bows.push((
entry.path(),
voc.transform_with_direct_idx(&new_feat).unwrap().0,
));
}
let num = |s: &str| -> usize {
let s = s.strip_suffix(".jpg").unwrap();
s.parse().unwrap()
};
bows.sort_by(|a, b| {
num(a.0.file_name().unwrap().to_str().unwrap())
.partial_cmp(&num(b.0.file_name().unwrap().to_str().unwrap()))
.unwrap()
});
let mut cost = 0;
for (f1, bow1) in bows.iter().skip(12).take(158) {
let mut scores: Vec<(f32, usize, i32)> = Vec::new();
let reference = num(f1.file_name().unwrap().to_str().unwrap());
for (f2, bow2) in bows.iter() {
let d = bow1.l1(bow2);
let matched = num(f2.file_name().unwrap().to_str().unwrap());
let cost = i32::abs(matched as i32 - reference as i32);
scores.push((d, matched, cost));
}
let base_cost = 0 + 1 + 1 + 2 + 2 + 3 + 3 + 4 + 4 + 5 + 5 + 6;
scores.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap());
for m in scores[..12].iter() {
cost += m.2;
}
cost -= base_cost;
}
println!("k: {}, l: {}. Total Cost: {}", k, l, cost);
}
}
}
}
}