Added a 4:3 pyramid down tool.

This commit is contained in:
Davis King 2011-07-13 15:32:45 -04:00
parent b3682d98bb
commit 59f6905284

View File

@ -546,6 +546,259 @@ namespace dlib
private:
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class pyramid_down_4_3 : noncopyable
{
public:
template <typename T>
vector<double,2> point_down (
const vector<T,2>& p
) const
{
const double ratio = 3.0/4.0;
//do return (p - vector<T,2>(1,1))*ratio;
return p*ratio - vector<double,2>(ratio,ratio);
}
template <typename T>
vector<double,2> point_up (
const vector<T,2>& p
) const
{
const double ratio = 4.0/3.0;
return p*ratio + vector<T,2>(1,1);
}
// -----------------------------
template <typename T>
vector<double,2> point_down (
const vector<T,2>& p,
unsigned int levels
) const
{
vector<double,2> temp = p;
for (unsigned int i = 0; i < levels; ++i)
temp = point_down(temp);
return temp;
}
template <typename T>
vector<double,2> point_up (
const vector<T,2>& p,
unsigned int levels
) const
{
vector<double,2> temp = p;
for (unsigned int i = 0; i < levels; ++i)
temp = point_up(temp);
return temp;
}
// -----------------------------
rectangle rect_up (
const rectangle& rect
) const
{
return rectangle(point_up(rect.tl_corner()), point_up(rect.br_corner()));
}
rectangle rect_up (
const rectangle& rect,
unsigned int levels
) const
{
return rectangle(point_up(rect.tl_corner(),levels), point_up(rect.br_corner(),levels));
}
// -----------------------------
rectangle rect_down (
const rectangle& rect
) const
{
return rectangle(point_down(rect.tl_corner()), point_down(rect.br_corner()));
}
rectangle rect_down (
const rectangle& rect,
unsigned int levels
) const
{
return rectangle(point_down(rect.tl_corner(),levels), point_down(rect.br_corner(),levels));
}
// -----------------------------
private:
template <typename T, typename U>
struct both_images_rgb
{
const static bool value = pixel_traits<typename T::type>::rgb &&
pixel_traits<typename U::type>::rgb;
};
public:
template <
typename in_image_type,
typename out_image_type
>
typename disable_if<both_images_rgb<in_image_type,out_image_type> >::type operator() (
const in_image_type& original,
out_image_type& down
) const
{
// make sure requires clause is not broken
DLIB_ASSERT(original.nr() > 10 && original.nc() > 10 &&
is_same_object(original, down) == false,
"\t void pyramid_down_4_3::operator()"
<< "\n\t original.nr(): " << original.nr()
<< "\n\t original.nc(): " << original.nc()
<< "\n\t is_same_object(original, down): " << is_same_object(original, down)
<< "\n\t this: " << this
);
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::has_alpha == false );
const long size_in = 4;
const long size_out = 3;
typedef typename pixel_traits<typename in_image_type::type>::basic_pixel_type bp_type;
typedef typename promote<bp_type>::type ptype;
down.set_size(size_out*((original.nr()-2)/size_in), size_out*((original.nc()-2)/size_in));
long rr = 1;
for (long r = 0; r < down.nr(); r+=size_out)
{
long cc = 1;
for (long c = 0; c < down.nc(); c+=size_out)
{
ptype block[size_in][size_in];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate block
assign_pixel(down[r][c] , (block[0][0]*25 + block[1][0]*5 + block[0][1]*5 + block[1][1])/(36*256));
assign_pixel(down[r][c+1] , (block[0][1]*5 + block[0][2]*5 + block[1][1] + block[1][2])/(12*256));
assign_pixel(down[r][c+2] , (block[0][3]*25 + block[1][3]*5 + block[0][2]*5 + block[1][2])/(36*256));
assign_pixel(down[r+1][c] , (block[1][0]*5 + block[2][0]*5 + block[1][1] + block[2][1])/(12*256));
assign_pixel(down[r+1][c+1] , (block[1][1] + block[1][2] + block[2][1] + block[2][2])/(4*256));
assign_pixel(down[r+1][c+2] , (block[1][3]*5 + block[2][3]*5 + block[1][2] + block[2][2])/(12*256));
assign_pixel(down[r+2][c] , (block[3][0]*25 + block[2][0]*5 + block[3][1]*5 + block[2][1])/(36*256));
assign_pixel(down[r+2][c+1] , (block[3][1]*5 + block[3][2]*5 + block[2][1] + block[2][2])/(12*256));
assign_pixel(down[r+2][c+2] , (block[3][3]*25 + block[2][3]*5 + block[3][2]*5 + block[2][2])/(36*256));
cc += size_in;
}
rr += size_in;
}
}
private:
struct rgbptype
{
uint32 red;
uint32 green;
uint32 blue;
};
public:
// ------------------------------------------
// OVERLOAD FOR RGB TO RGB IMAGES
// ------------------------------------------
template <
typename in_image_type,
typename out_image_type
>
typename enable_if<both_images_rgb<in_image_type,out_image_type> >::type operator() (
const in_image_type& original,
out_image_type& down
) const
{
// make sure requires clause is not broken
DLIB_ASSERT(original.nr() > 10 && original.nc() > 10 &&
is_same_object(original, down) == false,
"\t void pyramid_down_4_3::operator()"
<< "\n\t original.nr(): " << original.nr()
<< "\n\t original.nc(): " << original.nc()
<< "\n\t is_same_object(original, down): " << is_same_object(original, down)
<< "\n\t this: " << this
);
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::has_alpha == false );
const long size_in = 4;
const long size_out = 3;
down.set_size(size_out*((original.nr()-2)/size_in), size_out*((original.nc()-2)/size_in));
long rr = 1;
for (long r = 0; r < down.nr(); r+=size_out)
{
long cc = 1;
for (long c = 0; c < down.nc(); c+=size_out)
{
rgbptype block[size_in][size_in];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate block
down[r][c].red = (block[0][0].red*25 + block[1][0].red*5 + block[0][1].red*5 + block[1][1].red )/(36*256);
down[r][c].green = (block[0][0].green*25 + block[1][0].green*5 + block[0][1].green*5 + block[1][1].green)/(36*256);
down[r][c].blue = (block[0][0].blue*25 + block[1][0].blue*5 + block[0][1].blue*5 + block[1][1].blue )/(36*256);
down[r][c+1].red = (block[0][1].red*5 + block[0][2].red*5 + block[1][1].red + block[1][2].red )/(12*256);
down[r][c+1].green = (block[0][1].green*5 + block[0][2].green*5 + block[1][1].green + block[1][2].green)/(12*256);
down[r][c+1].blue = (block[0][1].blue*5 + block[0][2].blue*5 + block[1][1].blue + block[1][2].blue )/(12*256);
down[r][c+2].red = (block[0][3].red*25 + block[1][3].red*5 + block[0][2].red*5 + block[1][2].red )/(36*256);
down[r][c+2].green = (block[0][3].green*25 + block[1][3].green*5 + block[0][2].green*5 + block[1][2].green)/(36*256);
down[r][c+2].blue = (block[0][3].blue*25 + block[1][3].blue*5 + block[0][2].blue*5 + block[1][2].blue )/(36*256);
down[r+1][c].red = (block[1][0].red*5 + block[2][0].red*5 + block[1][1].red + block[2][1].red )/(12*256);
down[r+1][c].green = (block[1][0].green*5 + block[2][0].green*5 + block[1][1].green + block[2][1].green)/(12*256);
down[r+1][c].blue = (block[1][0].blue*5 + block[2][0].blue*5 + block[1][1].blue + block[2][1].blue )/(12*256);
down[r+1][c+1].red = (block[1][1].red + block[1][2].red + block[2][1].red + block[2][2].red )/(4*256);
down[r+1][c+1].green = (block[1][1].green + block[1][2].green + block[2][1].green + block[2][2].green)/(4*256);
down[r+1][c+1].blue = (block[1][1].blue + block[1][2].blue + block[2][1].blue + block[2][2].blue )/(4*256);
down[r+1][c+2].red = (block[1][3].red*5 + block[2][3].red*5 + block[1][2].red + block[2][2].red )/(12*256);
down[r+1][c+2].green = (block[1][3].green*5 + block[2][3].green*5 + block[1][2].green + block[2][2].green)/(12*256);
down[r+1][c+2].blue = (block[1][3].blue*5 + block[2][3].blue*5 + block[1][2].blue + block[2][2].blue )/(12*256);
down[r+2][c].red = (block[3][0].red*25 + block[2][0].red*5 + block[3][1].red*5 + block[2][1].red )/(36*256);
down[r+2][c].green = (block[3][0].green*25 + block[2][0].green*5 + block[3][1].green*5 + block[2][1].green)/(36*256);
down[r+2][c].blue = (block[3][0].blue*25 + block[2][0].blue*5 + block[3][1].blue*5 + block[2][1].blue )/(36*256);
down[r+2][c+1].red = (block[3][1].red*5 + block[3][2].red*5 + block[2][1].red + block[2][2].red )/(12*256);
down[r+2][c+1].green = (block[3][1].green*5 + block[3][2].green*5 + block[2][1].green + block[2][2].green)/(12*256);
down[r+2][c+1].blue = (block[3][1].blue*5 + block[3][2].blue*5 + block[2][1].blue + block[2][2].blue )/(12*256);
down[r+2][c+2].red = (block[3][3].red*25 + block[2][3].red*5 + block[3][2].red*5 + block[2][2].red )/(36*256);
down[r+2][c+2].green = (block[3][3].green*25 + block[2][3].green*5 + block[3][2].green*5 + block[2][2].green)/(36*256);
down[r+2][c+2].blue = (block[3][3].blue*25 + block[2][3].blue*5 + block[3][2].blue*5 + block[2][2].blue )/(36*256);
cc += size_in;
}
rr += size_in;
}
}
private:
};
// ----------------------------------------------------------------------------------------