Commit 7c88acb8 authored by Davis King's avatar Davis King

Changed the pyramid down objects so that they make better use of the

available image data.  Previously, more pixels on the right and bottom
of the image were cropped than was necessary.
parent 200ee395
...@@ -446,14 +446,20 @@ namespace dlib ...@@ -446,14 +446,20 @@ namespace dlib
typedef typename pixel_traits<typename in_image_type::type>::basic_pixel_type bp_type; typedef typename pixel_traits<typename in_image_type::type>::basic_pixel_type bp_type;
typedef typename promote<bp_type>::type ptype; typedef typename promote<bp_type>::type ptype;
down.set_size(size_out*((original.nr()-2)/size_in), size_out*((original.nc()-2)/size_in)); const long full_nr = size_out*((original.nr()-2)/size_in);
const long part_nr = (size_out*(original.nr()-2))/size_in;
const long full_nc = size_out*((original.nc()-2)/size_in);
const long part_nc = (size_out*(original.nc()-2))/size_in;
down.set_size(part_nr, part_nc);
long rr = 1; long rr = 1;
for (long r = 0; r < down.nr(); r+=size_out) long r;
for (r = 0; r < full_nr; r+=size_out)
{ {
long cc = 1; long cc = 1;
for (long c = 0; c < down.nc(); c+=size_out) long c;
for (c = 0; c < full_nc; c+=size_out)
{ {
ptype block[size_in][size_in]; ptype block[size_in][size_in];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3); separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
...@@ -466,8 +472,41 @@ namespace dlib ...@@ -466,8 +472,41 @@ namespace dlib
cc += size_in; cc += size_in;
} }
if (part_nc - full_nc == 1)
{
ptype block[size_in][2];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*9 + block[1][0]*3 + block[0][1]*3 + block[1][1])/(16*256));
assign_pixel(down[r+1][c] , (block[2][0]*9 + block[1][0]*3 + block[2][1]*3 + block[1][1])/(16*256));
}
rr += size_in; rr += size_in;
} }
if (part_nr - full_nr == 1)
{
long cc = 1;
long c;
for (c = 0; c < full_nc; c+=size_out)
{
ptype block[2][size_in];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*9 + block[1][0]*3 + block[0][1]*3 + block[1][1])/(16*256));
assign_pixel(down[r][c+1] , (block[0][2]*9 + block[1][2]*3 + block[0][1]*3 + block[1][1])/(16*256));
cc += size_in;
}
if (part_nc - full_nc == 1)
{
ptype block[2][2];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*9 + block[1][0]*3 + block[0][1]*3 + block[1][1])/(16*256));
}
}
} }
...@@ -508,14 +547,20 @@ namespace dlib ...@@ -508,14 +547,20 @@ namespace dlib
const long size_in = 3; const long size_in = 3;
const long size_out = 2; const long size_out = 2;
down.set_size(size_out*((original.nr()-2)/size_in), size_out*((original.nc()-2)/size_in)); const long full_nr = size_out*((original.nr()-2)/size_in);
const long part_nr = (size_out*(original.nr()-2))/size_in;
const long full_nc = size_out*((original.nc()-2)/size_in);
const long part_nc = (size_out*(original.nc()-2))/size_in;
down.set_size(part_nr, part_nc);
long rr = 1; long rr = 1;
for (long r = 0; r < down.nr(); r+=size_out) long r;
for (r = 0; r < full_nr; r+=size_out)
{ {
long cc = 1; long cc = 1;
for (long c = 0; c < down.nc(); c+=size_out) long c;
for (c = 0; c < full_nc; c+=size_out)
{ {
rgbptype block[size_in][size_in]; rgbptype block[size_in][size_in];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3); separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
...@@ -539,8 +584,53 @@ namespace dlib ...@@ -539,8 +584,53 @@ namespace dlib
cc += size_in; cc += size_in;
} }
if (part_nc - full_nc == 1)
{
rgbptype block[size_in][2];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*9 + block[1][0].red*3 + block[0][1].red*3 + block[1][1].red)/(16*256);
down[r][c].green = (block[0][0].green*9 + block[1][0].green*3 + block[0][1].green*3 + block[1][1].green)/(16*256);
down[r][c].blue = (block[0][0].blue*9 + block[1][0].blue*3 + block[0][1].blue*3 + block[1][1].blue)/(16*256);
down[r+1][c].red = (block[2][0].red*9 + block[1][0].red*3 + block[2][1].red*3 + block[1][1].red)/(16*256);
down[r+1][c].green = (block[2][0].green*9 + block[1][0].green*3 + block[2][1].green*3 + block[1][1].green)/(16*256);
down[r+1][c].blue = (block[2][0].blue*9 + block[1][0].blue*3 + block[2][1].blue*3 + block[1][1].blue)/(16*256);
}
rr += size_in; rr += size_in;
} }
if (part_nr - full_nr == 1)
{
long cc = 1;
long c;
for (c = 0; c < full_nc; c+=size_out)
{
rgbptype block[2][size_in];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*9 + block[1][0].red*3 + block[0][1].red*3 + block[1][1].red)/(16*256);
down[r][c].green = (block[0][0].green*9 + block[1][0].green*3 + block[0][1].green*3 + block[1][1].green)/(16*256);
down[r][c].blue = (block[0][0].blue*9 + block[1][0].blue*3 + block[0][1].blue*3 + block[1][1].blue)/(16*256);
down[r][c+1].red = (block[0][2].red*9 + block[1][2].red*3 + block[0][1].red*3 + block[1][1].red)/(16*256);
down[r][c+1].green = (block[0][2].green*9 + block[1][2].green*3 + block[0][1].green*3 + block[1][1].green)/(16*256);
down[r][c+1].blue = (block[0][2].blue*9 + block[1][2].blue*3 + block[0][1].blue*3 + block[1][1].blue)/(16*256);
cc += size_in;
}
if (part_nc - full_nc == 1)
{
rgbptype block[2][2];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*9 + block[1][0].red*3 + block[0][1].red*3 + block[1][1].red)/(16*256);
down[r][c].green = (block[0][0].green*9 + block[1][0].green*3 + block[0][1].green*3 + block[1][1].green)/(16*256);
down[r][c].blue = (block[0][0].blue*9 + block[1][0].blue*3 + block[0][1].blue*3 + block[1][1].blue)/(16*256);
}
}
} }
private: private:
...@@ -673,14 +763,20 @@ namespace dlib ...@@ -673,14 +763,20 @@ namespace dlib
typedef typename pixel_traits<typename in_image_type::type>::basic_pixel_type bp_type; typedef typename pixel_traits<typename in_image_type::type>::basic_pixel_type bp_type;
typedef typename promote<bp_type>::type ptype; typedef typename promote<bp_type>::type ptype;
down.set_size(size_out*((original.nr()-2)/size_in), size_out*((original.nc()-2)/size_in)); const long full_nr = size_out*((original.nr()-2)/size_in);
const long part_nr = (size_out*(original.nr()-2))/size_in;
const long full_nc = size_out*((original.nc()-2)/size_in);
const long part_nc = (size_out*(original.nc()-2))/size_in;
down.set_size(part_nr, part_nc);
long rr = 1; long rr = 1;
for (long r = 0; r < down.nr(); r+=size_out) long r;
for (r = 0; r < full_nr; r+=size_out)
{ {
long cc = 1; long cc = 1;
for (long c = 0; c < down.nc(); c+=size_out) long c;
for (c = 0; c < full_nc; c+=size_out)
{ {
ptype block[size_in][size_in]; ptype block[size_in][size_in];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3); separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
...@@ -699,9 +795,115 @@ namespace dlib ...@@ -699,9 +795,115 @@ namespace dlib
assign_pixel(down[r+2][c+2] , (block[3][3]*25 + block[2][3]*5 + block[3][2]*5 + block[2][2])/(36*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; cc += size_in;
} }
if (part_nc - full_nc == 2)
{
ptype block[size_in][3];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial 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+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+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));
}
else if (part_nc - full_nc == 1)
{
ptype block[size_in][2];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial 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+1][c] , (block[1][0]*5 + block[2][0]*5 + block[1][1] + block[2][1])/(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));
}
rr += size_in; rr += size_in;
} }
if (part_nr - full_nr == 2)
{
long cc = 1;
long c;
for (c = 0; c < full_nc; c+=size_out)
{
ptype block[3][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));
cc += size_in;
}
if (part_nc - full_nc == 2)
{
ptype block[3][3];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial 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+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));
}
else if (part_nc - full_nc == 1)
{
ptype block[3][2];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial 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+1][c] , (block[1][0]*5 + block[2][0]*5 + block[1][1] + block[2][1])/(12*256));
}
}
else if (part_nr - full_nr == 1)
{
long cc = 1;
long c;
for (c = 0; c < full_nc; c+=size_out)
{
ptype block[2][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));
cc += size_in;
}
if (part_nc - full_nc == 2)
{
ptype block[2][3];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial 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));
}
else if (part_nc - full_nc == 1)
{
ptype block[2][2];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*25 + block[1][0]*5 + block[0][1]*5 + block[1][1])/(36*256));
}
}
} }
private: private:
...@@ -741,14 +943,20 @@ namespace dlib ...@@ -741,14 +943,20 @@ namespace dlib
const long size_in = 4; const long size_in = 4;
const long size_out = 3; const long size_out = 3;
down.set_size(size_out*((original.nr()-2)/size_in), size_out*((original.nc()-2)/size_in)); const long full_nr = size_out*((original.nr()-2)/size_in);
const long part_nr = (size_out*(original.nr()-2))/size_in;
const long full_nc = size_out*((original.nc()-2)/size_in);
const long part_nc = (size_out*(original.nc()-2))/size_in;
down.set_size(part_nr, part_nc);
long rr = 1; long rr = 1;
for (long r = 0; r < down.nr(); r+=size_out) long r;
for (r = 0; r < full_nr; r+=size_out)
{ {
long cc = 1; long cc = 1;
for (long c = 0; c < down.nc(); c+=size_out) long c;
for (c = 0; c < full_nc; c+=size_out)
{ {
rgbptype block[size_in][size_in]; rgbptype block[size_in][size_in];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3); separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
...@@ -792,103 +1000,278 @@ namespace dlib ...@@ -792,103 +1000,278 @@ namespace dlib
cc += size_in; cc += size_in;
} }
rr += size_in; if (part_nc - full_nc == 2)
} {
} rgbptype block[size_in][3];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
private: // bi-linearly interpolate partial 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+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);
class pyramid_down_5_4 : noncopyable 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);
public: 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);
template <typename T> 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);
vector<double,2> point_down ( 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);
const vector<T,2>& p 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);
) const
{
const double ratio = 4.0/5.0;
//do return (p - vector<T,2>(1,1))*ratio;
return p*ratio - vector<double,2>(ratio,ratio);
} }
if (part_nc - full_nc == 1)
template <typename T>
vector<double,2> point_up (
const vector<T,2>& p
) const
{ {
const double ratio = 5.0/4.0; rgbptype block[size_in][2];
return p*ratio + vector<T,2>(1,1); separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
}
// ----------------------------- // bi-linearly interpolate partial 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);
template <typename T> 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);
vector<double,2> point_down ( 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);
const vector<T,2>& p, 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);
unsigned int levels
) const 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);
vector<double,2> temp = p; 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);
for (unsigned int i = 0; i < levels; ++i)
temp = point_down(temp);
return temp;
} }
template <typename T> rr += size_in;
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 ( if (part_nr - full_nr == 2)
const rectangle& rect
) const
{ {
return rectangle(point_up(rect.tl_corner()), point_up(rect.br_corner())); long cc = 1;
} long c;
for (c = 0; c < full_nc; c+=size_out)
rectangle rect_up (
const rectangle& rect,
unsigned int levels
) const
{ {
return rectangle(point_up(rect.tl_corner(),levels), point_up(rect.br_corner(),levels)); rgbptype block[3][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);
rectangle rect_down ( 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);
const rectangle& rect 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);
) const 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);
{
return rectangle(point_down(rect.tl_corner()), point_down(rect.br_corner()));
}
rectangle rect_down ( 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);
const rectangle& rect, 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);
unsigned int levels 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);
) const
{
return rectangle(point_down(rect.tl_corner(),levels), point_down(rect.br_corner(),levels));
}
// ----------------------------- 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);
cc += size_in;
}
if (part_nc - full_nc == 2)
{
rgbptype block[3][3];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial 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+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);
}
if (part_nc - full_nc == 1)
{
rgbptype block[3][2];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial 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+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);
}
}
if (part_nr - full_nr == 1)
{
long cc = 1;
long c;
for (c = 0; c < full_nc; c+=size_out)
{
rgbptype block[2][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);
cc += size_in;
}
if (part_nc - full_nc == 2)
{
rgbptype block[2][3];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial 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);
}
if (part_nc - full_nc == 1)
{
rgbptype block[2][2];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial 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);
}
}
}
private:
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class pyramid_down_5_4 : noncopyable
{
public:
template <typename T>
vector<double,2> point_down (
const vector<T,2>& p
) const
{
const double ratio = 4.0/5.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 = 5.0/4.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: private:
template <typename T, typename U> template <typename T, typename U>
...@@ -926,14 +1309,20 @@ namespace dlib ...@@ -926,14 +1309,20 @@ namespace dlib
typedef typename pixel_traits<typename in_image_type::type>::basic_pixel_type bp_type; typedef typename pixel_traits<typename in_image_type::type>::basic_pixel_type bp_type;
typedef typename promote<bp_type>::type ptype; typedef typename promote<bp_type>::type ptype;
down.set_size(size_out*((original.nr()-2)/size_in), size_out*((original.nc()-2)/size_in)); const long full_nr = size_out*((original.nr()-2)/size_in);
const long part_nr = (size_out*(original.nr()-2))/size_in;
const long full_nc = size_out*((original.nc()-2)/size_in);
const long part_nc = (size_out*(original.nc()-2))/size_in;
down.set_size(part_nr, part_nc);
long rr = 1; long rr = 1;
for (long r = 0; r < down.nr(); r+=size_out) long r;
for (r = 0; r < full_nr; r+=size_out)
{ {
long cc = 1; long cc = 1;
for (long c = 0; c < down.nc(); c+=size_out) long c;
for (c = 0; c < full_nc; c+=size_out)
{ {
ptype block[size_in][size_in]; ptype block[size_in][size_in];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3); separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
...@@ -961,58 +1350,303 @@ namespace dlib ...@@ -961,58 +1350,303 @@ namespace dlib
cc += size_in; cc += size_in;
} }
rr += size_in;
}
} if (part_nc - full_nc == 3)
{
ptype block[size_in][4];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
private: // bi-linearly interpolate partial block
struct rgbptype assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
assign_pixel(down[r][c+1] , (block[0][1]*35 + block[0][2]*21 + block[1][1]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r][c+2] , (block[0][3]*35 + block[0][2]*21 + block[1][3]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r+1][c] , (block[1][0]*35 + block[1][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
assign_pixel(down[r+1][c+1] , (block[1][1]*25 + block[1][2]*15 + block[2][1]*15 + block[2][2]*9 )/(64*256));
assign_pixel(down[r+1][c+2] , (block[1][2]*15 + block[1][3]*25 + block[2][2]*9 + block[2][3]*15)/(64*256));
assign_pixel(down[r+2][c] , (block[3][0]*35 + block[3][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
assign_pixel(down[r+2][c+1] , (block[3][1]*25 + block[3][2]*15 + block[2][1]*15 + block[2][2]*9 )/(64*256));
assign_pixel(down[r+2][c+2] , (block[3][2]*15 + block[3][3]*25 + block[2][2]*9 + block[2][3]*15)/(64*256));
assign_pixel(down[r+3][c] , (block[4][0]*49 + block[3][0]*7 + block[4][1]*7 + block[3][1] )/(64*256));
assign_pixel(down[r+3][c+1] , (block[4][1]*35 + block[4][2]*21 + block[3][1]*5 + block[3][2]*3 )/(64*256));
assign_pixel(down[r+3][c+2] , (block[4][3]*35 + block[4][2]*21 + block[3][3]*5 + block[3][2]*3 )/(64*256));
}
else if (part_nc - full_nc == 2)
{ {
uint32 red; ptype block[size_in][3];
uint32 green; separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
uint32 blue;
};
public: // bi-linearly interpolate partial block
// ------------------------------------------ assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
// OVERLOAD FOR RGB TO RGB IMAGES assign_pixel(down[r][c+1] , (block[0][1]*35 + block[0][2]*21 + block[1][1]*5 + block[1][2]*3 )/(64*256));
// ------------------------------------------
template < assign_pixel(down[r+1][c] , (block[1][0]*35 + block[1][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
typename in_image_type, assign_pixel(down[r+1][c+1] , (block[1][1]*25 + block[1][2]*15 + block[2][1]*15 + block[2][2]*9 )/(64*256));
typename out_image_type
> assign_pixel(down[r+2][c] , (block[3][0]*35 + block[3][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
typename enable_if<both_images_rgb<in_image_type,out_image_type> >::type operator() ( assign_pixel(down[r+2][c+1] , (block[3][1]*25 + block[3][2]*15 + block[2][1]*15 + block[2][2]*9 )/(64*256));
const in_image_type& original,
out_image_type& down assign_pixel(down[r+3][c] , (block[4][0]*49 + block[3][0]*7 + block[4][1]*7 + block[3][1] )/(64*256));
) const assign_pixel(down[r+3][c+1] , (block[4][1]*35 + block[4][2]*21 + block[3][1]*5 + block[3][2]*3 )/(64*256));
}
else if (part_nc - full_nc == 1)
{ {
// make sure requires clause is not broken ptype block[size_in][2];
DLIB_ASSERT(original.nr() > 10 && original.nc() > 10 && separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
is_same_object(original, down) == false,
"\t void pyramid_down_5_4::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 ); // bi-linearly interpolate partial block
COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::has_alpha == false ); assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
const long size_in = 5; assign_pixel(down[r+1][c] , (block[1][0]*35 + block[1][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
const long size_out = 4;
down.set_size(size_out*((original.nr()-2)/size_in), size_out*((original.nc()-2)/size_in)); assign_pixel(down[r+2][c] , (block[3][0]*35 + block[3][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
assign_pixel(down[r+3][c] , (block[4][0]*49 + block[3][0]*7 + block[4][1]*7 + block[3][1] )/(64*256));
}
rr += size_in;
}
long rr = 1; if (part_nr - full_nr == 3)
for (long r = 0; r < down.nr(); r+=size_out)
{ {
long cc = 1; long cc = 1;
for (long c = 0; c < down.nc(); c+=size_out) long c;
for (c = 0; c < full_nc; c+=size_out)
{ {
rgbptype block[size_in][size_in]; ptype block[4][size_in];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
assign_pixel(down[r][c+1] , (block[0][1]*35 + block[0][2]*21 + block[1][1]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r][c+2] , (block[0][3]*35 + block[0][2]*21 + block[1][3]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r][c+3] , (block[0][4]*49 + block[0][3]*7 + block[1][4]*7 + block[1][3] )/(64*256));
assign_pixel(down[r+1][c] , (block[1][0]*35 + block[1][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
assign_pixel(down[r+1][c+1] , (block[1][1]*25 + block[1][2]*15 + block[2][1]*15 + block[2][2]*9 )/(64*256));
assign_pixel(down[r+1][c+2] , (block[1][2]*15 + block[1][3]*25 + block[2][2]*9 + block[2][3]*15)/(64*256));
assign_pixel(down[r+1][c+3] , (block[1][3]*5 + block[1][4]*35 + block[2][3]*3 + block[2][4]*21)/(64*256));
assign_pixel(down[r+2][c] , (block[3][0]*35 + block[3][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
assign_pixel(down[r+2][c+1] , (block[3][1]*25 + block[3][2]*15 + block[2][1]*15 + block[2][2]*9 )/(64*256));
assign_pixel(down[r+2][c+2] , (block[3][2]*15 + block[3][3]*25 + block[2][2]*9 + block[2][3]*15)/(64*256));
assign_pixel(down[r+2][c+3] , (block[3][3]*5 + block[3][4]*35 + block[2][3]*3 + block[2][4]*21)/(64*256));
cc += size_in;
}
if (part_nc - full_nc == 3)
{
ptype block[4][4];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
assign_pixel(down[r][c+1] , (block[0][1]*35 + block[0][2]*21 + block[1][1]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r][c+2] , (block[0][3]*35 + block[0][2]*21 + block[1][3]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r+1][c] , (block[1][0]*35 + block[1][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
assign_pixel(down[r+1][c+1] , (block[1][1]*25 + block[1][2]*15 + block[2][1]*15 + block[2][2]*9 )/(64*256));
assign_pixel(down[r+1][c+2] , (block[1][2]*15 + block[1][3]*25 + block[2][2]*9 + block[2][3]*15)/(64*256));
assign_pixel(down[r+2][c] , (block[3][0]*35 + block[3][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
assign_pixel(down[r+2][c+1] , (block[3][1]*25 + block[3][2]*15 + block[2][1]*15 + block[2][2]*9 )/(64*256));
assign_pixel(down[r+2][c+2] , (block[3][2]*15 + block[3][3]*25 + block[2][2]*9 + block[2][3]*15)/(64*256));
}
else if (part_nc - full_nc == 2)
{
ptype block[4][3];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
assign_pixel(down[r][c+1] , (block[0][1]*35 + block[0][2]*21 + block[1][1]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r+1][c] , (block[1][0]*35 + block[1][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
assign_pixel(down[r+1][c+1] , (block[1][1]*25 + block[1][2]*15 + block[2][1]*15 + block[2][2]*9 )/(64*256));
assign_pixel(down[r+2][c] , (block[3][0]*35 + block[3][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
assign_pixel(down[r+2][c+1] , (block[3][1]*25 + block[3][2]*15 + block[2][1]*15 + block[2][2]*9 )/(64*256));
}
else if (part_nc - full_nc == 1)
{
ptype block[4][2];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
assign_pixel(down[r+1][c] , (block[1][0]*35 + block[1][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
assign_pixel(down[r+2][c] , (block[3][0]*35 + block[3][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
}
}
else if (part_nr - full_nr == 2)
{
long cc = 1;
long c;
for (c = 0; c < full_nc; c+=size_out)
{
ptype block[3][size_in];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
assign_pixel(down[r][c+1] , (block[0][1]*35 + block[0][2]*21 + block[1][1]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r][c+2] , (block[0][3]*35 + block[0][2]*21 + block[1][3]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r][c+3] , (block[0][4]*49 + block[0][3]*7 + block[1][4]*7 + block[1][3] )/(64*256));
assign_pixel(down[r+1][c] , (block[1][0]*35 + block[1][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
assign_pixel(down[r+1][c+1] , (block[1][1]*25 + block[1][2]*15 + block[2][1]*15 + block[2][2]*9 )/(64*256));
assign_pixel(down[r+1][c+2] , (block[1][2]*15 + block[1][3]*25 + block[2][2]*9 + block[2][3]*15)/(64*256));
assign_pixel(down[r+1][c+3] , (block[1][3]*5 + block[1][4]*35 + block[2][3]*3 + block[2][4]*21)/(64*256));
cc += size_in;
}
if (part_nc - full_nc == 3)
{
ptype block[3][4];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
assign_pixel(down[r][c+1] , (block[0][1]*35 + block[0][2]*21 + block[1][1]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r][c+2] , (block[0][3]*35 + block[0][2]*21 + block[1][3]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r+1][c] , (block[1][0]*35 + block[1][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
assign_pixel(down[r+1][c+1] , (block[1][1]*25 + block[1][2]*15 + block[2][1]*15 + block[2][2]*9 )/(64*256));
assign_pixel(down[r+1][c+2] , (block[1][2]*15 + block[1][3]*25 + block[2][2]*9 + block[2][3]*15)/(64*256));
}
else if (part_nc - full_nc == 2)
{
ptype block[3][3];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
assign_pixel(down[r][c+1] , (block[0][1]*35 + block[0][2]*21 + block[1][1]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r+1][c] , (block[1][0]*35 + block[1][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
assign_pixel(down[r+1][c+1] , (block[1][1]*25 + block[1][2]*15 + block[2][1]*15 + block[2][2]*9 )/(64*256));
}
else if (part_nc - full_nc == 1)
{
ptype block[3][2];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
assign_pixel(down[r+1][c] , (block[1][0]*35 + block[1][1]*5 + block[2][0]*21 + block[1][1]*3 )/(64*256));
}
}
else if (part_nr - full_nr == 1)
{
long cc = 1;
long c;
for (c = 0; c < full_nc; c+=size_out)
{
ptype block[2][size_in];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
assign_pixel(down[r][c+1] , (block[0][1]*35 + block[0][2]*21 + block[1][1]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r][c+2] , (block[0][3]*35 + block[0][2]*21 + block[1][3]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r][c+3] , (block[0][4]*49 + block[0][3]*7 + block[1][4]*7 + block[1][3] )/(64*256));
cc += size_in;
}
if (part_nc - full_nc == 3)
{
ptype block[2][4];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
assign_pixel(down[r][c+1] , (block[0][1]*35 + block[0][2]*21 + block[1][1]*5 + block[1][2]*3 )/(64*256));
assign_pixel(down[r][c+2] , (block[0][3]*35 + block[0][2]*21 + block[1][3]*5 + block[1][2]*3 )/(64*256));
}
else if (part_nc - full_nc == 2)
{
ptype block[2][3];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
assign_pixel(down[r][c+1] , (block[0][1]*35 + block[0][2]*21 + block[1][1]*5 + block[1][2]*3 )/(64*256));
}
else if (part_nc - full_nc == 1)
{
ptype block[2][2];
separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
assign_pixel(down[r][c] , (block[0][0]*49 + block[1][0]*7 + block[0][1]*7 + block[1][1] )/(64*256));
}
}
}
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_5_4::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 = 5;
const long size_out = 4;
const long full_nr = size_out*((original.nr()-2)/size_in);
const long part_nr = (size_out*(original.nr()-2))/size_in;
const long full_nc = size_out*((original.nc()-2)/size_in);
const long part_nc = (size_out*(original.nc()-2))/size_in;
down.set_size(part_nr, part_nc);
long rr = 1;
long r;
for (r = 0; r < full_nr; r+=size_out)
{
long cc = 1;
long c;
for (c = 0; c < full_nc; c+=size_out)
{
rgbptype block[size_in][size_in];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3); separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate block // bi-linearly interpolate block
...@@ -1083,8 +1717,474 @@ namespace dlib ...@@ -1083,8 +1717,474 @@ namespace dlib
cc += size_in; cc += size_in;
} }
rr += size_in;
if (part_nc - full_nc == 3)
{
rgbptype block[size_in][4];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r][c+1].red = (block[0][1].red*35 + block[0][2].red*21 + block[1][1].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+1].green = (block[0][1].green*35 + block[0][2].green*21 + block[1][1].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+1].blue = (block[0][1].blue*35 + block[0][2].blue*21 + block[1][1].blue*5 + block[1][2].blue*3 )/(64*256);
down[r][c+2].red = (block[0][3].red*35 + block[0][2].red*21 + block[1][3].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+2].green = (block[0][3].green*35 + block[0][2].green*21 + block[1][3].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+2].blue = (block[0][3].blue*35 + block[0][2].blue*21 + block[1][3].blue*5 + block[1][2].blue*3 )/(64*256);
down[r+1][c].red = (block[1][0].red*35 + block[1][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+1][c].green = (block[1][0].green*35 + block[1][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+1][c].blue = (block[1][0].blue*35 + block[1][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+1][c+1].red = (block[1][1].red*25 + block[1][2].red*15 + block[2][1].red*15 + block[2][2].red*9 )/(64*256);
down[r+1][c+1].green = (block[1][1].green*25 + block[1][2].green*15 + block[2][1].green*15 + block[2][2].green*9 )/(64*256);
down[r+1][c+1].blue = (block[1][1].blue*25 + block[1][2].blue*15 + block[2][1].blue*15 + block[2][2].blue*9 )/(64*256);
down[r+1][c+2].red = (block[1][2].red*15 + block[1][3].red*25 + block[2][2].red*9 + block[2][3].red*15 )/(64*256);
down[r+1][c+2].green = (block[1][2].green*15 + block[1][3].green*25 + block[2][2].green*9 + block[2][3].green*15)/(64*256);
down[r+1][c+2].blue = (block[1][2].blue*15 + block[1][3].blue*25 + block[2][2].blue*9 + block[2][3].blue*15 )/(64*256);
down[r+2][c].red = (block[3][0].red*35 + block[3][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+2][c].green = (block[3][0].green*35 + block[3][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+2][c].blue = (block[3][0].blue*35 + block[3][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+2][c+1].red = (block[3][1].red*25 + block[3][2].red*15 + block[2][1].red*15 + block[2][2].red*9 )/(64*256);
down[r+2][c+1].green = (block[3][1].green*25 + block[3][2].green*15 + block[2][1].green*15 + block[2][2].green*9 )/(64*256);
down[r+2][c+1].blue = (block[3][1].blue*25 + block[3][2].blue*15 + block[2][1].blue*15 + block[2][2].blue*9 )/(64*256);
down[r+2][c+2].red = (block[3][2].red*15 + block[3][3].red*25 + block[2][2].red*9 + block[2][3].red*15 )/(64*256);
down[r+2][c+2].green = (block[3][2].green*15 + block[3][3].green*25 + block[2][2].green*9 + block[2][3].green*15)/(64*256);
down[r+2][c+2].blue = (block[3][2].blue*15 + block[3][3].blue*25 + block[2][2].blue*9 + block[2][3].blue*15 )/(64*256);
down[r+3][c].red = (block[4][0].red*49 + block[3][0].red*7 + block[4][1].red*7 + block[3][1].red )/(64*256);
down[r+3][c].green = (block[4][0].green*49 + block[3][0].green*7 + block[4][1].green*7 + block[3][1].green )/(64*256);
down[r+3][c].blue = (block[4][0].blue*49 + block[3][0].blue*7 + block[4][1].blue*7 + block[3][1].blue )/(64*256);
down[r+3][c+1].red = (block[4][1].red*35 + block[4][2].red*21 + block[3][1].red*5 + block[3][2].red*3 )/(64*256);
down[r+3][c+1].green = (block[4][1].green*35 + block[4][2].green*21 + block[3][1].green*5 + block[3][2].green*3 )/(64*256);
down[r+3][c+1].blue = (block[4][1].blue*35 + block[4][2].blue*21 + block[3][1].blue*5 + block[3][2].blue*3 )/(64*256);
down[r+3][c+2].red = (block[4][3].red*35 + block[4][2].red*21 + block[3][3].red*5 + block[3][2].red*3 )/(64*256);
down[r+3][c+2].green = (block[4][3].green*35 + block[4][2].green*21 + block[3][3].green*5 + block[3][2].green*3 )/(64*256);
down[r+3][c+2].blue = (block[4][3].blue*35 + block[4][2].blue*21 + block[3][3].blue*5 + block[3][2].blue*3 )/(64*256);
} }
else if (part_nc - full_nc == 2)
{
rgbptype block[size_in][3];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r][c+1].red = (block[0][1].red*35 + block[0][2].red*21 + block[1][1].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+1].green = (block[0][1].green*35 + block[0][2].green*21 + block[1][1].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+1].blue = (block[0][1].blue*35 + block[0][2].blue*21 + block[1][1].blue*5 + block[1][2].blue*3 )/(64*256);
down[r+1][c].red = (block[1][0].red*35 + block[1][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+1][c].green = (block[1][0].green*35 + block[1][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+1][c].blue = (block[1][0].blue*35 + block[1][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+1][c+1].red = (block[1][1].red*25 + block[1][2].red*15 + block[2][1].red*15 + block[2][2].red*9 )/(64*256);
down[r+1][c+1].green = (block[1][1].green*25 + block[1][2].green*15 + block[2][1].green*15 + block[2][2].green*9 )/(64*256);
down[r+1][c+1].blue = (block[1][1].blue*25 + block[1][2].blue*15 + block[2][1].blue*15 + block[2][2].blue*9 )/(64*256);
down[r+2][c].red = (block[3][0].red*35 + block[3][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+2][c].green = (block[3][0].green*35 + block[3][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+2][c].blue = (block[3][0].blue*35 + block[3][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+2][c+1].red = (block[3][1].red*25 + block[3][2].red*15 + block[2][1].red*15 + block[2][2].red*9 )/(64*256);
down[r+2][c+1].green = (block[3][1].green*25 + block[3][2].green*15 + block[2][1].green*15 + block[2][2].green*9 )/(64*256);
down[r+2][c+1].blue = (block[3][1].blue*25 + block[3][2].blue*15 + block[2][1].blue*15 + block[2][2].blue*9 )/(64*256);
down[r+3][c].red = (block[4][0].red*49 + block[3][0].red*7 + block[4][1].red*7 + block[3][1].red )/(64*256);
down[r+3][c].green = (block[4][0].green*49 + block[3][0].green*7 + block[4][1].green*7 + block[3][1].green )/(64*256);
down[r+3][c].blue = (block[4][0].blue*49 + block[3][0].blue*7 + block[4][1].blue*7 + block[3][1].blue )/(64*256);
down[r+3][c+1].red = (block[4][1].red*35 + block[4][2].red*21 + block[3][1].red*5 + block[3][2].red*3 )/(64*256);
down[r+3][c+1].green = (block[4][1].green*35 + block[4][2].green*21 + block[3][1].green*5 + block[3][2].green*3 )/(64*256);
down[r+3][c+1].blue = (block[4][1].blue*35 + block[4][2].blue*21 + block[3][1].blue*5 + block[3][2].blue*3 )/(64*256);
}
else if (part_nc - full_nc == 1)
{
rgbptype block[size_in][2];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r+1][c].red = (block[1][0].red*35 + block[1][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+1][c].green = (block[1][0].green*35 + block[1][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+1][c].blue = (block[1][0].blue*35 + block[1][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+2][c].red = (block[3][0].red*35 + block[3][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+2][c].green = (block[3][0].green*35 + block[3][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+2][c].blue = (block[3][0].blue*35 + block[3][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+3][c].red = (block[4][0].red*49 + block[3][0].red*7 + block[4][1].red*7 + block[3][1].red )/(64*256);
down[r+3][c].green = (block[4][0].green*49 + block[3][0].green*7 + block[4][1].green*7 + block[3][1].green )/(64*256);
down[r+3][c].blue = (block[4][0].blue*49 + block[3][0].blue*7 + block[4][1].blue*7 + block[3][1].blue )/(64*256);
}
rr += size_in;
}
if (part_nr - full_nr == 3)
{
long cc = 1;
long c;
for (c = 0; c < full_nc; c+=size_out)
{
rgbptype block[4][size_in];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r][c+1].red = (block[0][1].red*35 + block[0][2].red*21 + block[1][1].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+1].green = (block[0][1].green*35 + block[0][2].green*21 + block[1][1].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+1].blue = (block[0][1].blue*35 + block[0][2].blue*21 + block[1][1].blue*5 + block[1][2].blue*3 )/(64*256);
down[r][c+2].red = (block[0][3].red*35 + block[0][2].red*21 + block[1][3].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+2].green = (block[0][3].green*35 + block[0][2].green*21 + block[1][3].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+2].blue = (block[0][3].blue*35 + block[0][2].blue*21 + block[1][3].blue*5 + block[1][2].blue*3 )/(64*256);
down[r][c+3].red = (block[0][4].red*49 + block[0][3].red*7 + block[1][4].red*7 + block[1][3].red )/(64*256);
down[r][c+3].green = (block[0][4].green*49 + block[0][3].green*7 + block[1][4].green*7 + block[1][3].green )/(64*256);
down[r][c+3].blue = (block[0][4].blue*49 + block[0][3].blue*7 + block[1][4].blue*7 + block[1][3].blue )/(64*256);
down[r+1][c].red = (block[1][0].red*35 + block[1][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+1][c].green = (block[1][0].green*35 + block[1][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+1][c].blue = (block[1][0].blue*35 + block[1][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+1][c+1].red = (block[1][1].red*25 + block[1][2].red*15 + block[2][1].red*15 + block[2][2].red*9 )/(64*256);
down[r+1][c+1].green = (block[1][1].green*25 + block[1][2].green*15 + block[2][1].green*15 + block[2][2].green*9 )/(64*256);
down[r+1][c+1].blue = (block[1][1].blue*25 + block[1][2].blue*15 + block[2][1].blue*15 + block[2][2].blue*9 )/(64*256);
down[r+1][c+2].red = (block[1][2].red*15 + block[1][3].red*25 + block[2][2].red*9 + block[2][3].red*15 )/(64*256);
down[r+1][c+2].green = (block[1][2].green*15 + block[1][3].green*25 + block[2][2].green*9 + block[2][3].green*15)/(64*256);
down[r+1][c+2].blue = (block[1][2].blue*15 + block[1][3].blue*25 + block[2][2].blue*9 + block[2][3].blue*15 )/(64*256);
down[r+1][c+3].red = (block[1][3].red*5 + block[1][4].red*35 + block[2][3].red*3 + block[2][4].red*21 )/(64*256);
down[r+1][c+3].green = (block[1][3].green*5 + block[1][4].green*35 + block[2][3].green*3 + block[2][4].green*21)/(64*256);
down[r+1][c+3].blue = (block[1][3].blue*5 + block[1][4].blue*35 + block[2][3].blue*3 + block[2][4].blue*21 )/(64*256);
down[r+2][c].red = (block[3][0].red*35 + block[3][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+2][c].green = (block[3][0].green*35 + block[3][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+2][c].blue = (block[3][0].blue*35 + block[3][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+2][c+1].red = (block[3][1].red*25 + block[3][2].red*15 + block[2][1].red*15 + block[2][2].red*9 )/(64*256);
down[r+2][c+1].green = (block[3][1].green*25 + block[3][2].green*15 + block[2][1].green*15 + block[2][2].green*9 )/(64*256);
down[r+2][c+1].blue = (block[3][1].blue*25 + block[3][2].blue*15 + block[2][1].blue*15 + block[2][2].blue*9 )/(64*256);
down[r+2][c+2].red = (block[3][2].red*15 + block[3][3].red*25 + block[2][2].red*9 + block[2][3].red*15 )/(64*256);
down[r+2][c+2].green = (block[3][2].green*15 + block[3][3].green*25 + block[2][2].green*9 + block[2][3].green*15)/(64*256);
down[r+2][c+2].blue = (block[3][2].blue*15 + block[3][3].blue*25 + block[2][2].blue*9 + block[2][3].blue*15 )/(64*256);
down[r+2][c+3].red = (block[3][3].red*5 + block[3][4].red*35 + block[2][3].red*3 + block[2][4].red*21 )/(64*256);
down[r+2][c+3].green = (block[3][3].green*5 + block[3][4].green*35 + block[2][3].green*3 + block[2][4].green*21)/(64*256);
down[r+2][c+3].blue = (block[3][3].blue*5 + block[3][4].blue*35 + block[2][3].blue*3 + block[2][4].blue*21 )/(64*256);
cc += size_in;
}
if (part_nc - full_nc == 3)
{
rgbptype block[4][4];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r][c+1].red = (block[0][1].red*35 + block[0][2].red*21 + block[1][1].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+1].green = (block[0][1].green*35 + block[0][2].green*21 + block[1][1].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+1].blue = (block[0][1].blue*35 + block[0][2].blue*21 + block[1][1].blue*5 + block[1][2].blue*3 )/(64*256);
down[r][c+2].red = (block[0][3].red*35 + block[0][2].red*21 + block[1][3].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+2].green = (block[0][3].green*35 + block[0][2].green*21 + block[1][3].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+2].blue = (block[0][3].blue*35 + block[0][2].blue*21 + block[1][3].blue*5 + block[1][2].blue*3 )/(64*256);
down[r+1][c].red = (block[1][0].red*35 + block[1][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+1][c].green = (block[1][0].green*35 + block[1][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+1][c].blue = (block[1][0].blue*35 + block[1][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+1][c+1].red = (block[1][1].red*25 + block[1][2].red*15 + block[2][1].red*15 + block[2][2].red*9 )/(64*256);
down[r+1][c+1].green = (block[1][1].green*25 + block[1][2].green*15 + block[2][1].green*15 + block[2][2].green*9 )/(64*256);
down[r+1][c+1].blue = (block[1][1].blue*25 + block[1][2].blue*15 + block[2][1].blue*15 + block[2][2].blue*9 )/(64*256);
down[r+1][c+2].red = (block[1][2].red*15 + block[1][3].red*25 + block[2][2].red*9 + block[2][3].red*15 )/(64*256);
down[r+1][c+2].green = (block[1][2].green*15 + block[1][3].green*25 + block[2][2].green*9 + block[2][3].green*15)/(64*256);
down[r+1][c+2].blue = (block[1][2].blue*15 + block[1][3].blue*25 + block[2][2].blue*9 + block[2][3].blue*15 )/(64*256);
down[r+2][c].red = (block[3][0].red*35 + block[3][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+2][c].green = (block[3][0].green*35 + block[3][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+2][c].blue = (block[3][0].blue*35 + block[3][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+2][c+1].red = (block[3][1].red*25 + block[3][2].red*15 + block[2][1].red*15 + block[2][2].red*9 )/(64*256);
down[r+2][c+1].green = (block[3][1].green*25 + block[3][2].green*15 + block[2][1].green*15 + block[2][2].green*9 )/(64*256);
down[r+2][c+1].blue = (block[3][1].blue*25 + block[3][2].blue*15 + block[2][1].blue*15 + block[2][2].blue*9 )/(64*256);
down[r+2][c+2].red = (block[3][2].red*15 + block[3][3].red*25 + block[2][2].red*9 + block[2][3].red*15 )/(64*256);
down[r+2][c+2].green = (block[3][2].green*15 + block[3][3].green*25 + block[2][2].green*9 + block[2][3].green*15)/(64*256);
down[r+2][c+2].blue = (block[3][2].blue*15 + block[3][3].blue*25 + block[2][2].blue*9 + block[2][3].blue*15 )/(64*256);
}
else if (part_nc - full_nc == 2)
{
rgbptype block[4][3];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r][c+1].red = (block[0][1].red*35 + block[0][2].red*21 + block[1][1].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+1].green = (block[0][1].green*35 + block[0][2].green*21 + block[1][1].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+1].blue = (block[0][1].blue*35 + block[0][2].blue*21 + block[1][1].blue*5 + block[1][2].blue*3 )/(64*256);
down[r+1][c].red = (block[1][0].red*35 + block[1][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+1][c].green = (block[1][0].green*35 + block[1][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+1][c].blue = (block[1][0].blue*35 + block[1][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+1][c+1].red = (block[1][1].red*25 + block[1][2].red*15 + block[2][1].red*15 + block[2][2].red*9 )/(64*256);
down[r+1][c+1].green = (block[1][1].green*25 + block[1][2].green*15 + block[2][1].green*15 + block[2][2].green*9 )/(64*256);
down[r+1][c+1].blue = (block[1][1].blue*25 + block[1][2].blue*15 + block[2][1].blue*15 + block[2][2].blue*9 )/(64*256);
down[r+2][c].red = (block[3][0].red*35 + block[3][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+2][c].green = (block[3][0].green*35 + block[3][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+2][c].blue = (block[3][0].blue*35 + block[3][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+2][c+1].red = (block[3][1].red*25 + block[3][2].red*15 + block[2][1].red*15 + block[2][2].red*9 )/(64*256);
down[r+2][c+1].green = (block[3][1].green*25 + block[3][2].green*15 + block[2][1].green*15 + block[2][2].green*9 )/(64*256);
down[r+2][c+1].blue = (block[3][1].blue*25 + block[3][2].blue*15 + block[2][1].blue*15 + block[2][2].blue*9 )/(64*256);
}
else if (part_nc - full_nc == 1)
{
rgbptype block[4][2];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r+1][c].red = (block[1][0].red*35 + block[1][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+1][c].green = (block[1][0].green*35 + block[1][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+1][c].blue = (block[1][0].blue*35 + block[1][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+2][c].red = (block[3][0].red*35 + block[3][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+2][c].green = (block[3][0].green*35 + block[3][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+2][c].blue = (block[3][0].blue*35 + block[3][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
}
}
else if (part_nr - full_nr == 2)
{
long cc = 1;
long c;
for (c = 0; c < full_nc; c+=size_out)
{
rgbptype block[3][size_in];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r][c+1].red = (block[0][1].red*35 + block[0][2].red*21 + block[1][1].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+1].green = (block[0][1].green*35 + block[0][2].green*21 + block[1][1].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+1].blue = (block[0][1].blue*35 + block[0][2].blue*21 + block[1][1].blue*5 + block[1][2].blue*3 )/(64*256);
down[r][c+2].red = (block[0][3].red*35 + block[0][2].red*21 + block[1][3].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+2].green = (block[0][3].green*35 + block[0][2].green*21 + block[1][3].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+2].blue = (block[0][3].blue*35 + block[0][2].blue*21 + block[1][3].blue*5 + block[1][2].blue*3 )/(64*256);
down[r][c+3].red = (block[0][4].red*49 + block[0][3].red*7 + block[1][4].red*7 + block[1][3].red )/(64*256);
down[r][c+3].green = (block[0][4].green*49 + block[0][3].green*7 + block[1][4].green*7 + block[1][3].green )/(64*256);
down[r][c+3].blue = (block[0][4].blue*49 + block[0][3].blue*7 + block[1][4].blue*7 + block[1][3].blue )/(64*256);
down[r+1][c].red = (block[1][0].red*35 + block[1][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+1][c].green = (block[1][0].green*35 + block[1][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+1][c].blue = (block[1][0].blue*35 + block[1][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+1][c+1].red = (block[1][1].red*25 + block[1][2].red*15 + block[2][1].red*15 + block[2][2].red*9 )/(64*256);
down[r+1][c+1].green = (block[1][1].green*25 + block[1][2].green*15 + block[2][1].green*15 + block[2][2].green*9 )/(64*256);
down[r+1][c+1].blue = (block[1][1].blue*25 + block[1][2].blue*15 + block[2][1].blue*15 + block[2][2].blue*9 )/(64*256);
down[r+1][c+2].red = (block[1][2].red*15 + block[1][3].red*25 + block[2][2].red*9 + block[2][3].red*15 )/(64*256);
down[r+1][c+2].green = (block[1][2].green*15 + block[1][3].green*25 + block[2][2].green*9 + block[2][3].green*15)/(64*256);
down[r+1][c+2].blue = (block[1][2].blue*15 + block[1][3].blue*25 + block[2][2].blue*9 + block[2][3].blue*15 )/(64*256);
down[r+1][c+3].red = (block[1][3].red*5 + block[1][4].red*35 + block[2][3].red*3 + block[2][4].red*21 )/(64*256);
down[r+1][c+3].green = (block[1][3].green*5 + block[1][4].green*35 + block[2][3].green*3 + block[2][4].green*21)/(64*256);
down[r+1][c+3].blue = (block[1][3].blue*5 + block[1][4].blue*35 + block[2][3].blue*3 + block[2][4].blue*21 )/(64*256);
cc += size_in;
}
if (part_nc - full_nc == 3)
{
rgbptype block[3][4];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r][c+1].red = (block[0][1].red*35 + block[0][2].red*21 + block[1][1].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+1].green = (block[0][1].green*35 + block[0][2].green*21 + block[1][1].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+1].blue = (block[0][1].blue*35 + block[0][2].blue*21 + block[1][1].blue*5 + block[1][2].blue*3 )/(64*256);
down[r][c+2].red = (block[0][3].red*35 + block[0][2].red*21 + block[1][3].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+2].green = (block[0][3].green*35 + block[0][2].green*21 + block[1][3].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+2].blue = (block[0][3].blue*35 + block[0][2].blue*21 + block[1][3].blue*5 + block[1][2].blue*3 )/(64*256);
down[r+1][c].red = (block[1][0].red*35 + block[1][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+1][c].green = (block[1][0].green*35 + block[1][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+1][c].blue = (block[1][0].blue*35 + block[1][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+1][c+1].red = (block[1][1].red*25 + block[1][2].red*15 + block[2][1].red*15 + block[2][2].red*9 )/(64*256);
down[r+1][c+1].green = (block[1][1].green*25 + block[1][2].green*15 + block[2][1].green*15 + block[2][2].green*9 )/(64*256);
down[r+1][c+1].blue = (block[1][1].blue*25 + block[1][2].blue*15 + block[2][1].blue*15 + block[2][2].blue*9 )/(64*256);
down[r+1][c+2].red = (block[1][2].red*15 + block[1][3].red*25 + block[2][2].red*9 + block[2][3].red*15 )/(64*256);
down[r+1][c+2].green = (block[1][2].green*15 + block[1][3].green*25 + block[2][2].green*9 + block[2][3].green*15)/(64*256);
down[r+1][c+2].blue = (block[1][2].blue*15 + block[1][3].blue*25 + block[2][2].blue*9 + block[2][3].blue*15 )/(64*256);
}
else if (part_nc - full_nc == 2)
{
rgbptype block[3][3];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r][c+1].red = (block[0][1].red*35 + block[0][2].red*21 + block[1][1].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+1].green = (block[0][1].green*35 + block[0][2].green*21 + block[1][1].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+1].blue = (block[0][1].blue*35 + block[0][2].blue*21 + block[1][1].blue*5 + block[1][2].blue*3 )/(64*256);
down[r+1][c].red = (block[1][0].red*35 + block[1][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+1][c].green = (block[1][0].green*35 + block[1][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+1][c].blue = (block[1][0].blue*35 + block[1][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
down[r+1][c+1].red = (block[1][1].red*25 + block[1][2].red*15 + block[2][1].red*15 + block[2][2].red*9 )/(64*256);
down[r+1][c+1].green = (block[1][1].green*25 + block[1][2].green*15 + block[2][1].green*15 + block[2][2].green*9 )/(64*256);
down[r+1][c+1].blue = (block[1][1].blue*25 + block[1][2].blue*15 + block[2][1].blue*15 + block[2][2].blue*9 )/(64*256);
}
else if (part_nc - full_nc == 1)
{
rgbptype block[3][2];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r+1][c].red = (block[1][0].red*35 + block[1][1].red*5 + block[2][0].red*21 + block[1][1].red*3 )/(64*256);
down[r+1][c].green = (block[1][0].green*35 + block[1][1].green*5 + block[2][0].green*21 + block[1][1].green*3 )/(64*256);
down[r+1][c].blue = (block[1][0].blue*35 + block[1][1].blue*5 + block[2][0].blue*21 + block[1][1].blue*3 )/(64*256);
}
}
else if (part_nr - full_nr == 1)
{
long cc = 1;
long c;
for (c = 0; c < full_nc; c+=size_out)
{
rgbptype block[2][size_in];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r][c+1].red = (block[0][1].red*35 + block[0][2].red*21 + block[1][1].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+1].green = (block[0][1].green*35 + block[0][2].green*21 + block[1][1].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+1].blue = (block[0][1].blue*35 + block[0][2].blue*21 + block[1][1].blue*5 + block[1][2].blue*3 )/(64*256);
down[r][c+2].red = (block[0][3].red*35 + block[0][2].red*21 + block[1][3].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+2].green = (block[0][3].green*35 + block[0][2].green*21 + block[1][3].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+2].blue = (block[0][3].blue*35 + block[0][2].blue*21 + block[1][3].blue*5 + block[1][2].blue*3 )/(64*256);
down[r][c+3].red = (block[0][4].red*49 + block[0][3].red*7 + block[1][4].red*7 + block[1][3].red )/(64*256);
down[r][c+3].green = (block[0][4].green*49 + block[0][3].green*7 + block[1][4].green*7 + block[1][3].green )/(64*256);
down[r][c+3].blue = (block[0][4].blue*49 + block[0][3].blue*7 + block[1][4].blue*7 + block[1][3].blue )/(64*256);
cc += size_in;
}
if (part_nc - full_nc == 3)
{
rgbptype block[2][4];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r][c+1].red = (block[0][1].red*35 + block[0][2].red*21 + block[1][1].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+1].green = (block[0][1].green*35 + block[0][2].green*21 + block[1][1].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+1].blue = (block[0][1].blue*35 + block[0][2].blue*21 + block[1][1].blue*5 + block[1][2].blue*3 )/(64*256);
down[r][c+2].red = (block[0][3].red*35 + block[0][2].red*21 + block[1][3].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+2].green = (block[0][3].green*35 + block[0][2].green*21 + block[1][3].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+2].blue = (block[0][3].blue*35 + block[0][2].blue*21 + block[1][3].blue*5 + block[1][2].blue*3 )/(64*256);
}
else if (part_nc - full_nc == 2)
{
rgbptype block[2][3];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
down[r][c+1].red = (block[0][1].red*35 + block[0][2].red*21 + block[1][1].red*5 + block[1][2].red*3 )/(64*256);
down[r][c+1].green = (block[0][1].green*35 + block[0][2].green*21 + block[1][1].green*5 + block[1][2].green*3 )/(64*256);
down[r][c+1].blue = (block[0][1].blue*35 + block[0][2].blue*21 + block[1][1].blue*5 + block[1][2].blue*3 )/(64*256);
}
else if (part_nc - full_nc == 1)
{
rgbptype block[2][2];
separable_3x3_filter_block_rgb(block, original, rr, cc, 3, 10, 3);
// bi-linearly interpolate partial block
down[r][c].red = (block[0][0].red*49 + block[1][0].red*7 + block[0][1].red*7 + block[1][1].red )/(64*256);
down[r][c].green = (block[0][0].green*49 + block[1][0].green*7 + block[0][1].green*7 + block[1][1].green )/(64*256);
down[r][c].blue = (block[0][0].blue*49 + block[1][0].blue*7 + block[0][1].blue*7 + block[1][1].blue )/(64*256);
}
}
} }
private: private:
......
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