From 17b48b97bb5719b961ed546f524b6aa8d3763ece Mon Sep 17 00:00:00 2001 From: Davis King Date: Sat, 17 Jun 2017 12:34:26 -0400 Subject: [PATCH] Changed the random_cropper's interface so that instead of talking in terms of min and max object height, it's now min and max object size. This way, if you have objects that are short and wide (i.e. objects where the relevant dimension is width rather than height) you will get sensible behavior out of the random cropper. --- dlib/image_transforms/random_cropper.h | 31 +++++++++--------- .../random_cropper_abstract.h | 32 ++++++++++--------- examples/dnn_face_recognition_ex.cpp | 4 +-- examples/dnn_mmod_ex.cpp | 2 +- examples/random_cropper_ex.cpp | 4 +-- 5 files changed, 38 insertions(+), 35 deletions(-) diff --git a/dlib/image_transforms/random_cropper.h b/dlib/image_transforms/random_cropper.h index 1a8658fe1..c8edee22e 100644 --- a/dlib/image_transforms/random_cropper.h +++ b/dlib/image_transforms/random_cropper.h @@ -18,8 +18,8 @@ namespace dlib chip_dims dims = chip_dims(300,300); bool randomly_flip = true; double max_rotation_degrees = 30; - double min_object_height = 0.25; // cropped object will be at least this fraction of the height of the image. - double max_object_height = 0.7; // cropped object will be at most this fraction of the height of the image. + double min_object_size = 0.25; // cropped object will be at least this fraction of the size of the image. + double max_object_size = 0.7; // cropped object will be at most this fraction of the size of the image. double background_crops_fraction = 0.5; double translate_amount = 0.10; @@ -78,24 +78,24 @@ namespace dlib double value ) { max_rotation_degrees = std::abs(value); } - double get_min_object_height ( - ) const { return min_object_height; } - void set_min_object_height ( + double get_min_object_size ( + ) const { return min_object_size; } + void set_min_object_size ( double value ) { DLIB_CASSERT(0 < value); - min_object_height = value; + min_object_size = value; } - double get_max_object_height ( - ) const { return max_object_height; } - void set_max_object_height ( + double get_max_object_size ( + ) const { return max_object_size; } + void set_max_object_size ( double value ) { DLIB_CASSERT(0 < value); - max_object_height = value; + max_object_size = value; } template < @@ -175,7 +175,8 @@ namespace dlib extract_image_chip(img, crop_plan, crop); const rectangle_transform tform = get_mapping_to_chip(crop_plan); - const unsigned long min_object_height_absolute = std::round(min_object_height*crop_plan.rows); + const unsigned long min_object_size_absolute_rows = std::round(min_object_size*crop_plan.rows); + const unsigned long min_object_size_absolute_cols = std::round(min_object_size*crop_plan.cols); // copy rects into crop_rects and set ones that are outside the crop to ignore or // drop entirely as appropriate. @@ -189,7 +190,7 @@ namespace dlib if (get_rect(crop).intersect(rect.rect).area() != 0) { // set to ignore if not totally in the crop or if too small. - if (!get_rect(crop).contains(rect.rect) || rect.rect.height() < min_object_height_absolute) + if (!get_rect(crop).contains(rect.rect) || (rect.rect.height() < min_object_size_absolute_rows && rect.rect.width() < min_object_size_absolute_cols)) rect.ignore = true; crop_rects.push_back(rect); @@ -224,12 +225,12 @@ namespace dlib auto rect = rects[randomly_pick_rect(rects)].rect; // perturb the location of the crop by a small fraction of the object's size. const point rand_translate = dpoint(rnd.get_double_in_range(-translate_amount,translate_amount)*rect.width(), - rnd.get_double_in_range(-translate_amount,translate_amount)*rect.height()); + rnd.get_double_in_range(-translate_amount,translate_amount)*std::max(rect.height(),rect.width())); // perturb the scale of the crop by a fraction of the object's size - const double rand_scale_perturb = rnd.get_double_in_range(min_object_height, max_object_height); + const double rand_scale_perturb = rnd.get_double_in_range(min_object_size, max_object_size); - const long box_size = rect.height()/rand_scale_perturb; + const long box_size = std::max(rect.height(),rect.width())/rand_scale_perturb; crop_rect = centered_rect(center(rect)+rand_translate, box_size, box_size); } else diff --git a/dlib/image_transforms/random_cropper_abstract.h b/dlib/image_transforms/random_cropper_abstract.h index 9348b3d1a..1d28cc318 100644 --- a/dlib/image_transforms/random_cropper_abstract.h +++ b/dlib/image_transforms/random_cropper_abstract.h @@ -35,8 +35,8 @@ namespace dlib - #get_chip_dims() == chip_dims(300,300) - #get_randomly_flip() == true - #get_max_rotation_degrees() == 30 - - #get_min_object_height() == 0.25 - - #get_max_object_height() == 0.7 + - #get_min_object_size() == 0.25 + - #get_max_object_size() == 0.7 - #get_background_crops_fraction() == 0.5 - #get_translate_amount() == 0.1 !*/ @@ -143,46 +143,48 @@ namespace dlib - #get_max_rotation_degrees() == std::abs(value) !*/ - double get_min_object_height ( + double get_min_object_size ( ) const; /*! ensures - When a chip is extracted around an object, the chip will be sized so that - the object's height is at least get_min_object_height() * 100 percent of the - chip height. E.g. if the chip is HEIGHT pixels tall then the object will - be at least HEIGHT*get_min_object_height() pixels tall. This also means - that if get_min_object_height() >1 then the object will be only partially + at least one of the object's height or width are >= get_min_object_size() * + the chip's height and width, respectively. E.g. if the chip is 640x480 + pixels in size then the object will be at least 480*get_min_object_size() + pixels tall or 640*get_min_object_size() pixels wide. This also means + that if get_min_object_size() >1 then the object will only be partially visible in the crop since it will be too big to fit. !*/ - void set_min_object_height ( + void set_min_object_size ( double value ); /*! requires - 0 < value ensures - - #get_min_object_height() == value + - #get_min_object_size() == value !*/ - double get_max_object_height ( + double get_max_object_size ( ) const; /*! ensures - When a chip is extracted around an object, the chip will be sized so that - the object's height is at most get_max_object_height() * 100 percent of the - chip height. E.g. if the chip is HEIGHT pixels tall then the object will - be at most HEIGHT*get_max_object_height() pixels tall. + both the object's height and width are at most get_max_object_size() * + the chip's height and width, respectively. E.g. if the chip is 640x480 + pixels in size then the object will be at most 480*get_max_object_size() + pixels tall and 640*get_max_object_size() pixels wide. !*/ - void set_max_object_height ( + void set_max_object_size ( double value ); /*! requires - 0 < value ensures - - #get_max_object_height() == value + - #get_max_object_size() == value !*/ template < diff --git a/examples/dnn_face_recognition_ex.cpp b/examples/dnn_face_recognition_ex.cpp index cf9394f7f..0c21bdd74 100644 --- a/examples/dnn_face_recognition_ex.cpp +++ b/examples/dnn_face_recognition_ex.cpp @@ -210,9 +210,9 @@ std::vector> jitter_image( thread_local random_cropper cropper; cropper.set_chip_dims(150,150); cropper.set_randomly_flip(true); - cropper.set_max_object_height(0.99999); + cropper.set_max_object_size(0.99999); cropper.set_background_crops_fraction(0); - cropper.set_min_object_height(0.97); + cropper.set_min_object_size(0.97); cropper.set_translate_amount(0.02); cropper.set_max_rotation_degrees(3); diff --git a/examples/dnn_mmod_ex.cpp b/examples/dnn_mmod_ex.cpp index 366fc26e4..1019dee9f 100644 --- a/examples/dnn_mmod_ex.cpp +++ b/examples/dnn_mmod_ex.cpp @@ -152,7 +152,7 @@ int main(int argc, char** argv) try std::vector> mini_batch_labels; random_cropper cropper; cropper.set_chip_dims(200, 200); - cropper.set_min_object_height(0.2); + cropper.set_min_object_size(0.2); dlib::rand rnd; // Run the trainer until the learning rate gets small. This will probably take several // hours. diff --git a/examples/random_cropper_ex.cpp b/examples/random_cropper_ex.cpp index 719d4d6f7..01a2ac5e5 100644 --- a/examples/random_cropper_ex.cpp +++ b/examples/random_cropper_ex.cpp @@ -45,8 +45,8 @@ int main(int argc, char** argv) try // make the objects in the crops have a min and max size of such and such". // You do that by calling these two functions. Here we are saying we want the // objects in our crops to be between 0.2*400 and 0.8*400 pixels in height. - cropper.set_min_object_height(0.2); - cropper.set_max_object_height(0.8); + cropper.set_min_object_size(0.2); + cropper.set_max_object_size(0.8); // The cropper can also randomly mirror and rotate crops, which we ask it to // perform as well. cropper.set_randomly_flip(true);