Commit fe3d5901 authored by Davis King's avatar Davis King

Clarified the spec for extract_image_chips() and also made it so the user can

explicitly specify the dimensions of the extracted chips.
parent 5d659af7
...@@ -1398,15 +1398,49 @@ namespace dlib ...@@ -1398,15 +1398,49 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct chip_dims
{
chip_dims (
unsigned long rows_,
unsigned long cols_
) : rows(rows_), cols(cols_) { }
unsigned long rows;
unsigned long cols;
};
struct chip_details struct chip_details
{ {
chip_details() : size(0), angle(0) {} chip_details() : angle(0), rows(0), cols(0) {}
chip_details(const rectangle& rect_, unsigned long size_) : rect(rect_),size(size_),angle(0) {} chip_details(const rectangle& rect_, unsigned long size) : rect(rect_),angle(0)
chip_details(const rectangle& rect_, unsigned long size_, double angle_) : rect(rect_),size(size_),angle(angle_) {} { compute_dims_from_size(size); }
chip_details(const rectangle& rect_, unsigned long size, double angle_) : rect(rect_),angle(angle_)
{ compute_dims_from_size(size); }
chip_details(const rectangle& rect_, const chip_dims& dims) :
rect(rect_),angle(0),rows(dims.rows), cols(dims.cols) {}
chip_details(const rectangle& rect_, const chip_dims& dims, double angle_) :
rect(rect_),angle(angle_),rows(dims.rows), cols(dims.cols) {}
rectangle rect; rectangle rect;
unsigned long size;
double angle; double angle;
unsigned long rows;
unsigned long cols;
inline unsigned long size() const
{
return rows*cols;
}
private:
void compute_dims_from_size (
unsigned long size
)
{
const double relative_size = std::sqrt(size/(double)rect.area());
rows = static_cast<unsigned long>(rect.height()*relative_size + 0.5);
cols = static_cast<unsigned long>(size/(double)rows + 0.5);
}
}; };
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -1425,11 +1459,11 @@ namespace dlib ...@@ -1425,11 +1459,11 @@ namespace dlib
#ifdef ENABLE_ASSERTS #ifdef ENABLE_ASSERTS
for (unsigned long i = 0; i < chip_locations.size(); ++i) for (unsigned long i = 0; i < chip_locations.size(); ++i)
{ {
DLIB_CASSERT(chip_locations[i].size != 0 && DLIB_CASSERT(chip_locations[i].size() != 0 &&
chip_locations[i].rect.is_empty() == false, chip_locations[i].rect.is_empty() == false,
"\t void extract_image_chips()" "\t void extract_image_chips()"
<< "\n\t Invalid inputs were given to this function." << "\n\t Invalid inputs were given to this function."
<< "\n\t chip_locations["<<i<<"].size: " << chip_locations[i].size << "\n\t chip_locations["<<i<<"].size(): " << chip_locations[i].size()
<< "\n\t chip_locations["<<i<<"].rect.is_empty(): " << chip_locations[i].rect.is_empty() << "\n\t chip_locations["<<i<<"].rect.is_empty(): " << chip_locations[i].rect.is_empty()
); );
} }
...@@ -1447,7 +1481,7 @@ namespace dlib ...@@ -1447,7 +1481,7 @@ namespace dlib
{ {
long depth = 0; long depth = 0;
rectangle rect = pyr.rect_down(chip_locations[i].rect); rectangle rect = pyr.rect_down(chip_locations[i].rect);
while (rect.area() > chip_locations[i].size) while (rect.area() > chip_locations[i].size())
{ {
rect = pyr.rect_down(rect); rect = pyr.rect_down(rect);
++depth; ++depth;
...@@ -1468,15 +1502,12 @@ namespace dlib ...@@ -1468,15 +1502,12 @@ namespace dlib
chips.resize(chip_locations.size()); chips.resize(chip_locations.size());
for (unsigned long i = 0; i < chips.size(); ++i) for (unsigned long i = 0; i < chips.size(); ++i)
{ {
const double relative_size = std::sqrt(chip_locations[i].size/(double)chip_locations[i].rect.area()); chips[i].set_size(chip_locations[i].rows, chip_locations[i].cols);
const long chip_height = static_cast<long>(chip_locations[i].rect.height()*relative_size + 0.5);
const long chip_width = static_cast<long>(chip_locations[i].size/(double)chip_height + 0.5);
chips[i].set_size(chip_height, chip_width);
// figure out which level in the pyramid to use to extract the chip // figure out which level in the pyramid to use to extract the chip
int level = -1; int level = -1;
rectangle rect = chip_locations[i].rect; rectangle rect = chip_locations[i].rect;
while (pyr.rect_down(rect).area() > chip_locations[i].size) while (pyr.rect_down(rect).area() > chip_locations[i].size())
{ {
++level; ++level;
rect = pyr.rect_down(rect); rect = pyr.rect_down(rect);
......
...@@ -858,6 +858,25 @@ namespace dlib ...@@ -858,6 +858,25 @@ namespace dlib
!*/ !*/
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
struct chip_dims
{
/*!
WHAT THIS OBJECT REPRESENTS
This is a simple tool for passing in a pair of row and column values to the
chip_details constructor.
!*/
chip_dims (
unsigned long rows_,
unsigned long cols_
) : rows(rows_), cols(cols_) { }
unsigned long rows;
unsigned long cols;
};
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
struct chip_details struct chip_details
...@@ -868,8 +887,8 @@ namespace dlib ...@@ -868,8 +887,8 @@ namespace dlib
another image. In particular, it specifies that the image chip is another image. In particular, it specifies that the image chip is
contained within the rectangle this->rect and that prior to extraction the contained within the rectangle this->rect and that prior to extraction the
image should be rotated counter-clockwise by this->angle radians. Finally, image should be rotated counter-clockwise by this->angle radians. Finally,
the extracted chip should have this->size pixels in it regardless of the the extracted chip should have this->rows rows and this->cols columns in it
size of this->rect. regardless of the shape of this->rect.
!*/ !*/
...@@ -878,8 +897,10 @@ namespace dlib ...@@ -878,8 +897,10 @@ namespace dlib
/*! /*!
ensures ensures
- #rect.is_empty() == true - #rect.is_empty() == true
- #size == 0 - #size() == 0
- #angle == 0 - #angle == 0
- #rows == 0
- #cols == 0
!*/ !*/
chip_details( chip_details(
...@@ -889,8 +910,18 @@ namespace dlib ...@@ -889,8 +910,18 @@ namespace dlib
/*! /*!
ensures ensures
- #rect == rect_ - #rect == rect_
- #size == size_ - #size() == size_
- #angle == 0 - #angle == 0
- #rows and #cols is set such that the total size of the chip is as close
to size_ as possible but still matches the aspect ratio of rect_.
- As long as size_ and the aspect ratio of of rect_ stays constant then
#rows and #cols will always have the same values. This means that, for
example, if you want all your chips to have the same dimensions then
ensure that size_ is always the same and also that rect_ always has the
same aspect ratio. Otherwise the calculated values of #rows and #cols
may be different for different chips. Alternatively, you can use the
chip_details constructor below that lets you specify the exact values for
rows and cols.
!*/ !*/
chip_details( chip_details(
...@@ -901,13 +932,57 @@ namespace dlib ...@@ -901,13 +932,57 @@ namespace dlib
/*! /*!
ensures ensures
- #rect == rect_ - #rect == rect_
- #size == size_ - #size() == size_
- #angle == angle_ - #angle == angle_
- #rows and #cols is set such that the total size of the chip is as close
to size_ as possible but still matches the aspect ratio of rect_.
- As long as size_ and the aspect ratio of of rect_ stays constant then
#rows and #cols will always have the same values. This means that, for
example, if you want all your chips to have the same dimensions then
ensure that size_ is always the same and also that rect_ always has the
same aspect ratio. Otherwise the calculated values of #rows and #cols
may be different for different chips. Alternatively, you can use the
chip_details constructor below that lets you specify the exact values for
rows and cols.
!*/
chip_details(
const rectangle& rect_,
const chip_dims& dims
);
/*!
ensures
- #rect == rect_
- #size() == dims.rows*dims.cols
- #angle == 0
- #rows == dims.rows
- #cols == dims.cols
!*/
chip_details(
const rectangle& rect_,
const chip_dims& dims,
double angle_
);
/*!
ensures
- #rect == rect_
- #size() == dims.rows*dims.cols
- #angle == angle_
- #rows == dims.rows
- #cols == dims.cols
!*/
inline unsigned long size() const { return rows*cols; }
/*!
ensures
- returns the number of pixels in this chip. This is just rows*cols.
!*/ !*/
rectangle rect; rectangle rect;
unsigned long size;
double angle; double angle;
unsigned long rows;
unsigned long cols;
}; };
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
...@@ -940,21 +1015,11 @@ namespace dlib ...@@ -940,21 +1015,11 @@ namespace dlib
- for all valid i: - for all valid i:
- #chips[i] == The image chip extracted from the position - #chips[i] == The image chip extracted from the position
chip_locations[i].rect in img. chip_locations[i].rect in img.
- #chips[i].nr()/#chips[i].nc() is approximately equal to - #chips[i].nr() == chip_locations[i].rows
chip_locations[i].rect.height()/chip_locations[i].rect.width() (i.e. the - #chips[i].nc() == chip_locations[i].cols
aspect ratio of the chip is as similar as possible to the aspect ratio of
the rectangle that defines the chip's location in the original image)
- #chips[i].size() is as close to chip_locations[i].size as possible given that
we attempt to keep the chip's aspect ratio similar to chip_locations[i].rect.
- The image will have been rotated counter-clockwise by - The image will have been rotated counter-clockwise by
chip_locations[i].angle radians, around the center of chip_locations[i].angle radians, around the center of
chip_locations[i].rect, before the chip was extracted. chip_locations[i].rect, before the chip was extracted.
- As long as chip_locations[i].size and the aspect ratio of of
chip_locations[i].rect stays constant then the dimensions of #chips[i] is
always the same. This means that, for example, if you want all your
chips to have the same dimensions then ensure that chip_location[i].size
is always the same and also that chip_location[i].rect always has the
same aspect ratio.
- Any pixels in an image chip that go outside img are set to 0 (i.e. black). - Any pixels in an image chip that go outside img are set to 0 (i.e. black).
!*/ !*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment