voc_dataset/
lib.rs

1//! Simple loader for the PASCAL Visual Object Classes (VOC)
2//!
3//! This crate supports dataset formats from VOC2007 to VOC2012.
4
5mod common;
6pub mod types;
7
8pub use crate::types::*;
9
10use crate::common::*;
11
12/// The sample corresponds to an image along with annotations
13#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14pub struct Sample {
15    pub image_path: PathBuf,
16    pub annotation: Annotation,
17}
18
19/// Load VOC data directory
20pub fn load<P: AsRef<Path>>(dataset_dir: P) -> Result<Vec<Sample>> {
21    let dataset_dir_r = dataset_dir.as_ref();
22    let image_dir = dataset_dir_r.join("JPEGImages");
23    let annotations_dir = dataset_dir_r.join("Annotations");
24
25    let samples = image_dir
26        .read_dir()?
27        .map(|entry_result| -> Result<Option<_>> {
28            let entry = entry_result?;
29            if entry.file_type()?.is_file() {
30                let path = entry.path();
31                if let Some(ext) = path.extension() {
32                    if ext == "jpg" {
33                        let name = path.file_stem().unwrap();
34                        return Ok(Some((name.to_owned(), path.to_owned())));
35                    }
36                }
37            }
38            Ok(None)
39        })
40        .filter_map(|arg| match arg {
41            Ok(None) => None,
42            Ok(Some(pair)) => Some(Ok(pair)),
43            Err(err) => Some(Err(err)),
44        })
45        .map(|arg| {
46            let (image_name, image_path) = arg?;
47            let mut xml_path = annotations_dir.join(&image_name);
48            ensure!(xml_path.set_extension("xml"), "set_extension() failed");
49            info!("Loading {}", xml_path.display());
50
51            // File annotation xml
52            let content = fs::read_to_string(&xml_path)
53                .with_context(|| format!("cannot open file {}", xml_path.display()))?;
54            let annotation: Annotation = serde_xml_rs::from_str(&content)
55                .with_context(|| format!("failed to parse file {}", xml_path.display()))?;
56
57            // Verify if filename matches
58            let mut file_name = image_name.clone();
59            file_name.push(".jpg");
60            ensure!(
61                file_name == annotation.filename.as_str(),
62                "Expect \"{}\" in <filename>, but get \"{}\"",
63                file_name.to_str().unwrap(),
64                annotation.filename,
65            );
66
67            let sample = Sample {
68                image_path,
69                annotation,
70            };
71
72            Ok(sample)
73        })
74        .collect::<Result<Vec<Sample>, _>>()?;
75
76    Ok(samples)
77}