viewercloud/
annotation.rs

1//! KITTI Annotation file parsing.
2use anyhow::Result;
3use std::ffi::OsStr;
4use std::fs::File;
5use std::io::prelude::*;
6use std::io::BufReader;
7use std::path::Path;
8/// Struct to reprensent every KITTI annotation.
9#[derive(Debug, Default, PartialEq)]
10pub struct KittiAnnotation {
11    /// Describes the type of object:
12    /// 'Car', 'Van', 'Truck',
13    /// 'Pedestrian', 'Person_sitting',
14    /// 'Cyclist', 'Tram',
15    /// 'Misc' or 'DontCare'.
16    pub category: String,
17    /// Float from 0 (non-truncated)
18    /// to 1 (truncated), where truncated refers
19    /// to the object leaving image boundaries
20    pub truncation: f32,
21    /// Integer (0,1,2,3) indicating occlusion state:
22    /// 0 = fully visible,
23    /// 1 = partly occluded,
24    /// 2 = largely occluded,
25    /// 3 = unknown
26    pub occlusion: i16,
27    /// Observation angle of object, ranging [-pi..pi]
28    pub alpha: f32,
29    /// 2D bounding box xmin of object in the image
30    pub xmin: f32,
31    /// 2D bounding box ymin of object in the image
32    pub ymin: f32,
33    /// 2D bounding box xmax of object in the image
34    pub xmax: f32,
35    /// 2D bounding box ymax of object in the image
36    pub ymax: f32,
37    /// 3D object dimensions  height(in meters)
38    pub h: f32,
39    /// 3D object dimensions width (in meters)
40    pub w: f32,
41    /// 3D object dimensions length (in meters)
42    pub l: f32,
43    /// 3D object location x in camera coordinates (in meters)
44    pub x: f32,
45    /// 3D object location y in camera coordinates (in meters)
46    pub y: f32,
47    /// 3D object location z in camera coordinates (in meters)
48    pub z: f32,
49    /// Rotation ry around Y-axis in camera coordinates [-pi..pi]
50    pub ry: f32,
51    /// Score indicating confidence in detection [0..1]
52    /// If coming from gound truth score is 1.0
53    pub score: f32,
54}
55
56impl KittiAnnotation {
57    /// Create a KittiAnnotation
58    #[allow(clippy::too_many_arguments)]
59    pub fn new(
60        category: String,
61        truncation: f32,
62        occlusion: i16,
63        alpha: f32,
64        xmin: f32,
65        ymin: f32,
66        xmax: f32,
67        ymax: f32,
68        height: f32,
69        width: f32,
70        length: f32,
71        xc: f32,
72        yc: f32,
73        zc: f32,
74        ry: f32,
75        score: f32,
76    ) -> Self {
77        Self {
78            category,
79            truncation,
80            occlusion,
81            alpha,
82            xmin,
83            ymin,
84            xmax,
85            ymax,
86            h: height,
87            w: width,
88            l: length,
89            x: xc,
90            y: yc,
91            z: zc,
92            ry,
93            score,
94        }
95    }
96    /// Return the 2D BoundingBox in image coordinates system
97    pub fn get_2d_bounding_box(self) -> [f32; 4] {
98        [self.xmin, self.ymin, self.xmax, self.ymax]
99    }
100    /// Return the 3D BoundingBox in the Lidar coordinates system
101    pub fn get_3d_bounding_box(self) -> [f32; 7] {
102        [self.x, self.y, self.z, self.h, self.w, self.l, self.ry]
103    }
104}
105
106/// Parse a KITTI annotation file describe in the DevKit
107pub fn read_annotation_file(kitti_annotations_path: String) -> Result<Vec<KittiAnnotation>> {
108    let extension = Path::new(&kitti_annotations_path).extension();
109    if extension != Some(OsStr::new("txt")) {
110        panic!(
111            "KITTI annotation file are in txt format and it received an got {:?}.",
112            extension
113        );
114    }
115    let file = File::open(kitti_annotations_path).expect("This file does not exist");
116    let file = BufReader::new(file);
117    let mut annotation: Vec<KittiAnnotation> = vec![];
118    for line in file.lines() {
119        let line = line?;
120        let data: Vec<&str> = line.split_whitespace().collect();
121        if data[0] != "DontCare" {
122            let anno = KittiAnnotation::new(
123                data[0].to_string(),
124                data[1].parse()?,
125                data[2].parse()?,
126                data[3].parse()?,
127                data[4].parse()?,
128                data[5].parse()?,
129                data[6].parse()?,
130                data[7].parse()?,
131                data[8].parse()?,
132                data[9].parse()?,
133                data[10].parse()?,
134                data[11].parse()?,
135                data[12].parse()?,
136                data[13].parse()?,
137                data[14].parse()?,
138                1.0,
139            );
140            annotation.push(anno);
141        }
142    }
143    Ok(annotation)
144}