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

explicitly specify the dimensions of the extracted chips.
This commit is contained in:
Davis King 2014-02-08 17:46:35 -05:00
parent 5d659af761
commit fe3d5901c1
2 changed files with 126 additions and 30 deletions

View File

@ -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
{
chip_details() : size(0), angle(0) {}
chip_details(const rectangle& rect_, unsigned long size_) : rect(rect_),size(size_),angle(0) {}
chip_details(const rectangle& rect_, unsigned long size_, double angle_) : rect(rect_),size(size_),angle(angle_) {}
chip_details() : angle(0), rows(0), cols(0) {}
chip_details(const rectangle& rect_, unsigned long size) : rect(rect_),angle(0)
{ 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;
unsigned long size;
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
#ifdef ENABLE_ASSERTS
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,
"\t void extract_image_chips()"
<< "\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()
);
}
@ -1447,7 +1481,7 @@ namespace dlib
{
long depth = 0;
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);
++depth;
@ -1468,15 +1502,12 @@ namespace dlib
chips.resize(chip_locations.size());
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());
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);
chips[i].set_size(chip_locations[i].rows, chip_locations[i].cols);
// figure out which level in the pyramid to use to extract the chip
int level = -1;
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;
rect = pyr.rect_down(rect);

View File

@ -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
@ -868,8 +887,8 @@ namespace dlib
another image. In particular, it specifies that the image chip is
contained within the rectangle this->rect and that prior to extraction the
image should be rotated counter-clockwise by this->angle radians. Finally,
the extracted chip should have this->size pixels in it regardless of the
size of this->rect.
the extracted chip should have this->rows rows and this->cols columns in it
regardless of the shape of this->rect.
!*/
@ -878,8 +897,10 @@ namespace dlib
/*!
ensures
- #rect.is_empty() == true
- #size == 0
- #size() == 0
- #angle == 0
- #rows == 0
- #cols == 0
!*/
chip_details(
@ -889,8 +910,18 @@ namespace dlib
/*!
ensures
- #rect == rect_
- #size == size_
- #size() == size_
- #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(
@ -901,13 +932,57 @@ namespace dlib
/*!
ensures
- #rect == rect_
- #size == size_
- #size() == size_
- #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;
unsigned long size;
double angle;
unsigned long rows;
unsigned long cols;
};
// ----------------------------------------------------------------------------------------
@ -940,21 +1015,11 @@ namespace dlib
- for all valid i:
- #chips[i] == The image chip extracted from the position
chip_locations[i].rect in img.
- #chips[i].nr()/#chips[i].nc() is approximately equal to
chip_locations[i].rect.height()/chip_locations[i].rect.width() (i.e. the
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.
- #chips[i].nr() == chip_locations[i].rows
- #chips[i].nc() == chip_locations[i].cols
- The image will have been rotated counter-clockwise by
chip_locations[i].angle radians, around the center of
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).
!*/