1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
use super::bbox_modify;
use rand::distributions::{IndependentSample, Range};
use std::fs::create_dir_all;
use std::path::Path;
use std::path::PathBuf;
use std::env::current_dir;
use imageproc::affine::{translate};
use image::ColorType;
use image;
use rand::ThreadRng;
use super::translation_lambda;

#[derive(Debug)]
pub struct FileMapping {
    pub jpg_pathbuf_in: PathBuf,
    pub xml_pathbuf_in: PathBuf,
    pub jpg_pathbuf_out: PathBuf,
    pub xml_pathbuf_out: PathBuf,
}

impl FileMapping {
    pub fn new(jpg_pathbuf_in: PathBuf, output_dirname: &str) -> FileMapping {
        let jpg_filename = jpg_pathbuf_in.file_name()
            .expect("Failed to get filename").to_str()
            .expect("Failed to convert filename to str");
        let jpg_parent_pathbuf = jpg_pathbuf_in
            .parent()
            .expect("Failed to get parent dir");
        let jpg_parent_dirname = jpg_parent_pathbuf
            .file_name()
            .expect("Failed to get dirname of parent")
            .to_str()
            .expect("Failed to convert parent dirname to str");
        assert_eq!(jpg_parent_dirname, "JPEGImages");
        let input_pathbuf = jpg_parent_pathbuf
            .parent()
            .expect("Failed to get data root.");
        let data_parent = match input_pathbuf.parent() {
            None => panic!("Failed to get the parent folder of data root."),
            Some(p) if p == Path::new("") => current_dir().expect("Failed to get cwd"),
            Some(p) => p.to_owned(),
        };
        let xml_pathbuf_in = input_pathbuf
            .join("Annotations")
            .join(jpg_filename)
            .with_extension("xml");
        let output_pathbuf = data_parent
            .join(output_dirname);

        let output_jpg_subpath = output_pathbuf.join("JPEGImages");
        let output_xml_subpath = output_pathbuf.join("Annotations");
        if !output_jpg_subpath.exists() {
            create_dir_all(output_jpg_subpath.as_path())
                .expect("Failed to create jpg subpath.");
        }
        if !output_xml_subpath.exists() {
            create_dir_all(output_xml_subpath.as_path())
                .expect("Failed to create xml subpath.");
        }
        let jpg_pathbuf_out = output_jpg_subpath
            .join(Path::new(jpg_filename));
        let xml_pathbuf_out = output_xml_subpath
            .join(Path::new(jpg_filename))
            .with_extension("xml");
        FileMapping {
            jpg_pathbuf_in: jpg_pathbuf_in.clone(),
            xml_pathbuf_in,
            jpg_pathbuf_out,
            xml_pathbuf_out,
        }
    }

    pub fn process(&self, delta_x_percent: f32, delta_y_percent: f32, rng: &mut ThreadRng) {

        let img = image::open(self.jpg_pathbuf_in.as_path())
            .expect("Failed to read image.")
            .to_rgb();
        let width = img.width();
        let height = img.height();
        let w = width as f32;
        let h = height as f32;
        let delta_x_max = (w * delta_x_percent / 100.0) as i32;
        let delta_y_max = (h * delta_y_percent / 100.0) as i32;
        let x_range = Range::new(-delta_x_max, delta_x_max);
        let y_range = Range::new(-delta_y_max, delta_y_max);
        let delta_x = x_range.ind_sample(rng);
        let delta_y = y_range.ind_sample(rng);
        bbox_modify(self.xml_pathbuf_in.as_path(),
                    self.xml_pathbuf_out.as_path(),
                    &*translation_lambda(delta_x, delta_y))
            .expect("Failed to modify xml");
        let translated_img = translate(&img, (delta_x, delta_y));
        image::save_buffer(self.jpg_pathbuf_out.as_path(),
                           &translated_img,
                           width,
                           height,
                           ColorType::RGB(8))
            .expect("Failed to save modified image.");
    }
}