mirror of https://github.com/davisking/dlib.git
Refactored create_tiled_pyramid() code to remove unnecessary copying. It's now
about 2x faster. The code is cleaner too.
This commit is contained in:
parent
8c2d87db09
commit
9e54a2088a
|
@ -1021,6 +1021,100 @@ namespace dlib
|
|||
nc = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template <typename pyramid_type>
|
||||
void compute_tiled_image_pyramid_details (
|
||||
const pyramid_type& pyr,
|
||||
long nr,
|
||||
long nc,
|
||||
const unsigned long padding,
|
||||
const unsigned long outer_padding,
|
||||
std::vector<rectangle>& rects,
|
||||
long& pyramid_image_nr,
|
||||
long& pyramid_image_nc
|
||||
)
|
||||
{
|
||||
rects.clear();
|
||||
if (nr*nc == 0)
|
||||
{
|
||||
pyramid_image_nr = 0;
|
||||
pyramid_image_nc = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const long min_height = 5;
|
||||
rects.reserve(100);
|
||||
rects.push_back(rectangle(nc,nr));
|
||||
// build the whole pyramid
|
||||
while(true)
|
||||
{
|
||||
find_pyramid_down_output_image_size(pyr, nr, nc);
|
||||
if (nr*nc == 0 || nr < min_height)
|
||||
break;
|
||||
rects.push_back(rectangle(nc,nr));
|
||||
}
|
||||
|
||||
// figure out output image size
|
||||
long total_height = 0;
|
||||
for (auto&& i : rects)
|
||||
total_height += i.height()+padding;
|
||||
total_height -= padding*2; // don't add unnecessary padding to the very right side.
|
||||
long height = 0;
|
||||
long prev_width = 0;
|
||||
for (auto&& i : rects)
|
||||
{
|
||||
// Figure out how far we go on the first column. We go until the next image can
|
||||
// fit next to the previous one, which means we can double back for the second
|
||||
// column of images.
|
||||
if (i.width() <= rects[0].width()-prev_width-(long)padding &&
|
||||
(height-rects[0].height())*2 >= (total_height-rects[0].height()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
height += i.height() + padding;
|
||||
prev_width = i.width();
|
||||
}
|
||||
height -= padding; // don't add unnecessary padding to the very right side.
|
||||
|
||||
const long width = rects[0].width();
|
||||
pyramid_image_nr = height+outer_padding*2;
|
||||
pyramid_image_nc = width+outer_padding*2;
|
||||
|
||||
|
||||
long y = outer_padding;
|
||||
size_t i = 0;
|
||||
while(y < height+(long)outer_padding && i < rects.size())
|
||||
{
|
||||
rects[i] = translate_rect(rects[i],point(outer_padding,y));
|
||||
DLIB_ASSERT(rectangle(pyramid_image_nc,pyramid_image_nr).contains(rects[i]));
|
||||
y += rects[i].height()+padding;
|
||||
++i;
|
||||
}
|
||||
y -= padding;
|
||||
while (i < rects.size())
|
||||
{
|
||||
point p1(outer_padding+width-1,y-1);
|
||||
point p2 = p1 - rects[i].br_corner();
|
||||
rectangle rect(p1,p2);
|
||||
DLIB_ASSERT(rectangle(pyramid_image_nc,pyramid_image_nr).contains(rect));
|
||||
// don't keep going on the last row if it would intersect the original image.
|
||||
if (!rects[0].intersect(rect).is_empty())
|
||||
break;
|
||||
|
||||
rects[i] = rect;
|
||||
y -= rects[i].height()+padding;
|
||||
++i;
|
||||
}
|
||||
|
||||
// Delete any extraneous rectangles if we broke out of the above loop early due to
|
||||
// intersection with the original image.
|
||||
rects.resize(i);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
|
@ -1038,84 +1132,25 @@ namespace dlib
|
|||
{
|
||||
DLIB_ASSERT(!is_same_object(img, out_img));
|
||||
|
||||
rects.clear();
|
||||
if (num_rows(img)*num_columns(img) == 0)
|
||||
{
|
||||
set_image_size(out_img,0,0);
|
||||
return;
|
||||
}
|
||||
|
||||
const long min_height = 5;
|
||||
long out_nr, out_nc;
|
||||
pyramid_type pyr;
|
||||
std::vector<matrix<rgb_pixel>> pyramid;
|
||||
matrix<rgb_pixel> temp;
|
||||
assign_image(temp, img);
|
||||
pyramid.push_back(std::move(temp));
|
||||
// build the whole pyramid
|
||||
while(true)
|
||||
{
|
||||
matrix<rgb_pixel> temp;
|
||||
pyr(pyramid.back(), temp);
|
||||
if (temp.size() == 0 || temp.nr() < min_height)
|
||||
break;
|
||||
pyramid.push_back(std::move(temp));
|
||||
}
|
||||
impl::compute_tiled_image_pyramid_details(pyr, img.nr(), img.nc(), padding, outer_padding, rects, out_nr, out_nc);
|
||||
|
||||
// figure out output image size
|
||||
long total_height = 0;
|
||||
for (auto&& i : pyramid)
|
||||
total_height += i.nr()+padding;
|
||||
total_height -= padding*2; // don't add unnecessary padding to the very right side.
|
||||
long height = 0;
|
||||
long prev_width = 0;
|
||||
for (auto&& i : pyramid)
|
||||
{
|
||||
// Figure out how far we go on the first column. We go until the next image can
|
||||
// fit next to the previous one, which means we can double back for the second
|
||||
// column of images.
|
||||
if (i.nc() <= img.nc()-prev_width-(long)padding &&
|
||||
(height-img.nr())*2 >= (total_height-img.nr()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
height += i.nr() + padding;
|
||||
prev_width = i.nc();
|
||||
}
|
||||
height -= padding; // don't add unnecessary padding to the very right side.
|
||||
|
||||
const long width = img.nc();
|
||||
set_image_size(out_img,height+outer_padding*2,width+outer_padding*2);
|
||||
set_image_size(out_img, out_nr, out_nc);
|
||||
assign_all_pixels(out_img, 0);
|
||||
|
||||
long y = outer_padding;
|
||||
size_t i = 0;
|
||||
while(y < height+(long)outer_padding)
|
||||
{
|
||||
rectangle rect = translate_rect(get_rect(pyramid[i]),point(outer_padding,y));
|
||||
DLIB_ASSERT(get_rect(out_img).contains(rect));
|
||||
rects.push_back(rect);
|
||||
auto si = sub_image(out_img, rect);
|
||||
assign_image(si, pyramid[i]);
|
||||
y += pyramid[i].nr()+padding;
|
||||
++i;
|
||||
}
|
||||
y -= padding;
|
||||
while (i < pyramid.size())
|
||||
{
|
||||
point p1(outer_padding+width-1,y-1);
|
||||
point p2 = p1 - get_rect(pyramid[i]).br_corner();
|
||||
rectangle rect(p1,p2);
|
||||
DLIB_ASSERT(get_rect(out_img).contains(rect));
|
||||
// don't keep going on the last row if it would intersect the original image.
|
||||
if (!get_rect(img).intersect(rect).is_empty())
|
||||
break;
|
||||
rects.push_back(rect);
|
||||
auto si = sub_image(out_img, rect);
|
||||
assign_image(si, pyramid[i]);
|
||||
y -= pyramid[i].nr()+padding;
|
||||
++i;
|
||||
}
|
||||
if (rects.size() == 0)
|
||||
return;
|
||||
|
||||
// now build the image pyramid into out_img
|
||||
auto si = sub_image(out_img, rects[0]);
|
||||
assign_image(si, img);
|
||||
for (size_t i = 1; i < rects.size(); ++i)
|
||||
{
|
||||
auto s1 = sub_image(out_img, rects[i-1]);
|
||||
auto s2 = sub_image(out_img, rects[i]);
|
||||
pyr(s1,s2);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue