use anyhow::Result;
use std::ffi::OsStr;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::Path;
#[derive(Debug, Default, PartialEq)]
pub struct KittiAnnotation {
pub category: String,
pub truncation: f32,
pub occlusion: i16,
pub alpha: f32,
pub xmin: f32,
pub ymin: f32,
pub xmax: f32,
pub ymax: f32,
pub h: f32,
pub w: f32,
pub l: f32,
pub x: f32,
pub y: f32,
pub z: f32,
pub ry: f32,
pub score: f32,
}
impl KittiAnnotation {
#[allow(clippy::too_many_arguments)]
pub fn new(
category: String,
truncation: f32,
occlusion: i16,
alpha: f32,
xmin: f32,
ymin: f32,
xmax: f32,
ymax: f32,
height: f32,
width: f32,
length: f32,
xc: f32,
yc: f32,
zc: f32,
ry: f32,
score: f32,
) -> Self {
Self {
category,
truncation,
occlusion,
alpha,
xmin,
ymin,
xmax,
ymax,
h: height,
w: width,
l: length,
x: xc,
y: yc,
z: zc,
ry,
score,
}
}
pub fn get_2d_bounding_box(self) -> [f32; 4] {
[self.xmin, self.ymin, self.xmax, self.ymax]
}
pub fn get_3d_bounding_box(self) -> [f32; 7] {
[self.x, self.y, self.z, self.h, self.w, self.l, self.ry]
}
}
pub fn read_annotation_file(kitti_annotations_path: String) -> Result<Vec<KittiAnnotation>> {
let extension = Path::new(&kitti_annotations_path).extension();
if extension != Some(OsStr::new("txt")) {
panic!(
"KITTI annotation file are in txt format and it received an got {:?}.",
extension
);
}
let file = File::open(kitti_annotations_path).expect("This file does not exist");
let file = BufReader::new(file);
let mut annotation: Vec<KittiAnnotation> = vec![];
for line in file.lines() {
let line = line?;
let data: Vec<&str> = line.split_whitespace().collect();
if data[0] != "DontCare" {
let anno = KittiAnnotation::new(
data[0].to_string(),
data[1].parse()?,
data[2].parse()?,
data[3].parse()?,
data[4].parse()?,
data[5].parse()?,
data[6].parse()?,
data[7].parse()?,
data[8].parse()?,
data[9].parse()?,
data[10].parse()?,
data[11].parse()?,
data[12].parse()?,
data[13].parse()?,
data[14].parse()?,
1.0,
);
annotation.push(anno);
}
}
Ok(annotation)
}