///|
pub fn BoundingBox::area(self : BoundingBox) -> Double {
if self.width <= 0.0 || self.height <= 0.0 {
0.0
} else {
self.width * self.height
}
}
///|
pub fn BoundingBox::right(self : BoundingBox) -> Double {
self.x + self.width
}
///|
pub fn BoundingBox::bottom(self : BoundingBox) -> Double {
self.y + self.height
}
///|
fn max_double(a : Double, b : Double) -> Double {
if a > b {
a
} else {
b
}
}
///|
fn min_double(a : Double, b : Double) -> Double {
if a < b {
a
} else {
b
}
}
///|
pub fn BoundingBox::intersection_area(
self : BoundingBox,
other : BoundingBox,
) -> Double {
let left = max_double(self.x, other.x)
let top = max_double(self.y, other.y)
let right = min_double(self.right(), other.right())
let bottom = min_double(self.bottom(), other.bottom())
if right <= left || bottom <= top {
0.0
} else {
(right - left) * (bottom - top)
}
}
///|
pub fn BoundingBox::iou(self : BoundingBox, other : BoundingBox) -> Double {
let inter = self.intersection_area(other)
let union = self.area() + other.area() - inter
if union <= 0.0 {
0.0
} else {
inter / union
}
}
///|
pub fn BoundingBox::is_inside_image(
self : BoundingBox,
width : Int,
height : Int,
) -> Bool {
self.x >= 0.0 &&
self.y >= 0.0 &&
self.right() <= width.to_double() &&
self.bottom() <= height.to_double()
}
///|
pub fn filter_annotations_by_label(
annotations : ArrayView[Annotation],
label : String,
) -> Array[Annotation] {
Array::from_iter(annotations.iter().filter(fn(item) { item.label == label }))
}
///|
pub fn filter_annotations_by_confidence(
annotations : ArrayView[Annotation],
min_confidence : Double,
) -> Array[Annotation] {
Array::from_iter(
annotations.iter().filter(fn(item) { item.confidence >= min_confidence }),
)
}
///|
pub fn validate_annotation(
annotation : Annotation,
image_width : Int,
image_height : Int,
) -> Unit raise VisionFormatError {
if annotation.confidence < 0.0 || annotation.confidence > 1.0 {
raise VisionFormatError::InvalidNumber("confidence must be in [0, 1]")
}
if annotation.bbox.area() <= 0.0 {
raise VisionFormatError::InvalidShape(
"annotation box must have positive area",
)
}
if !annotation.bbox.is_inside_image(image_width, image_height) {
raise VisionFormatError::InvalidShape(
"annotation box is outside image bounds",
)
}
}