#[derive(Debug, Clone)]
pub struct MatchResult {
pub x: u32,
pub y: u32,
pub width: u32,
pub height: u32,
pub confidence: f32,
pub scale: f32,
}
impl MatchResult {
pub fn new(x: u32, y: u32, width: u32, height: u32, confidence: f32, scale: f32) -> Self {
Self { x, y, width, height, confidence, scale }
}
pub fn center(&self) -> (u32, u32) {
(self.x + self.width / 2, self.y + self.height / 2)
}
pub fn center_f32(&self) -> (f32, f32) {
(self.x as f32 + self.width as f32 / 2.0, self.y as f32 + self.height as f32 / 2.0)
}
pub fn bounds(&self) -> (u32, u32, u32, u32) {
(self.x, self.y, self.width, self.height)
}
pub fn right(&self) -> u32 {
self.x + self.width
}
pub fn bottom(&self) -> u32 {
self.y + self.height
}
pub fn area(&self) -> u32 {
self.width * self.height
}
pub fn overlaps(&self, other: &MatchResult) -> bool {
self.x < other.right()
&& self.right() > other.x
&& self.y < other.bottom()
&& self.bottom() > other.y
}
pub fn iou(&self, other: &MatchResult) -> f32 {
if !self.overlaps(other) {
return 0.0;
}
let inter_x1 = self.x.max(other.x);
let inter_y1 = self.y.max(other.y);
let inter_x2 = self.right().min(other.right());
let inter_y2 = self.bottom().min(other.bottom());
let inter_area = (inter_x2 - inter_x1) * (inter_y2 - inter_y1);
let union_area = self.area() + other.area() - inter_area;
if union_area == 0 { 0.0 } else { inter_area as f32 / union_area as f32 }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_match_result_center() {
let result = MatchResult::new(100, 200, 50, 40, 0.9, 1.0);
assert_eq!(result.center(), (125, 220));
}
#[test]
fn test_match_result_bounds() {
let result = MatchResult::new(100, 200, 50, 40, 0.9, 1.0);
assert_eq!(result.bounds(), (100, 200, 50, 40));
assert_eq!(result.right(), 150);
assert_eq!(result.bottom(), 240);
assert_eq!(result.area(), 2000);
}
#[test]
fn test_match_result_overlaps() {
let r1 = MatchResult::new(100, 100, 50, 50, 0.9, 1.0);
let r2 = MatchResult::new(120, 120, 50, 50, 0.8, 1.0);
let r3 = MatchResult::new(200, 200, 50, 50, 0.7, 1.0);
assert!(r1.overlaps(&r2));
assert!(!r1.overlaps(&r3));
}
#[test]
fn test_match_result_iou() {
let r1 = MatchResult::new(0, 0, 100, 100, 0.9, 1.0);
let r2 = MatchResult::new(50, 50, 100, 100, 0.8, 1.0);
let iou = r1.iou(&r2);
assert!((iou - 0.143).abs() < 0.01);
}
#[test]
fn test_match_result_iou_no_overlap() {
let r1 = MatchResult::new(0, 0, 50, 50, 0.9, 1.0);
let r2 = MatchResult::new(100, 100, 50, 50, 0.8, 1.0);
assert_eq!(r1.iou(&r2), 0.0);
}
}