diff --git a/dlib/image_transforms/image_pyramid.h b/dlib/image_transforms/image_pyramid.h index 090f11dd1..1bfbdf5cd 100644 --- a/dlib/image_transforms/image_pyramid.h +++ b/dlib/image_transforms/image_pyramid.h @@ -130,2207 +130,646 @@ namespace dlib // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- - class pyramid_down : noncopyable + namespace impl { - public: - template - vector point_down ( - const vector& p - ) const + class pyramid_down_2_1 : noncopyable { - //do return (p - vector(2,2))/2.0; - return p/2.0 - vector(1,1); - } + public: - template - vector point_up ( - const vector& p - ) const - { - return p*2 + vector(2,2); - } - - // ----------------------------- - - template - vector point_down ( - const vector& p, - unsigned int levels - ) const - { - vector temp = p; - for (unsigned int i = 0; i < levels; ++i) - temp = point_down(temp); - return temp; - } - - template - vector point_up ( - const vector& p, - unsigned int levels - ) const - { - vector 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 - struct both_images_rgb - { - const static bool value = pixel_traits::rgb && - pixel_traits::rgb; - }; - public: - - template < - typename in_image_type, - typename out_image_type - > - typename disable_if >::type operator() ( - const in_image_type& original, - out_image_type& down - ) const - { - // make sure requires clause is not broken - DLIB_ASSERT( is_same_object(original, down) == false, - "\t void pyramid_down::operator()" - << "\n\t is_same_object(original, down): " << is_same_object(original, down) - << "\n\t this: " << this - ); - - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - - if (original.nr() <= 8 || original.nc() <= 8) + template + vector point_down ( + const vector& p + ) const { - down.clear(); - return; + //do return (p - vector(2,2))/2.0; + return p/2.0 - vector(1,1); } - typedef typename pixel_traits::basic_pixel_type bp_type; - typedef typename promote::type ptype; - array2d temp_img; - temp_img.set_size(original.nr(), (original.nc()-3)/2); - down.set_size((original.nr()-3)/2, (original.nc()-3)/2); - - - // This function applies a 5x5 Gaussian filter to the image. It - // does this by separating the filter into its horizontal and vertical - // components and then downsamples the image by dropping every other - // row and column. Note that we can do these things all together in - // one step. - - // apply row filter - for (long r = 0; r < temp_img.nr(); ++r) + template + vector point_up ( + const vector& p + ) const { - long oc = 0; - for (long c = 0; c < temp_img.nc(); ++c) + return p*2 + vector(2,2); + } + + // ----------------------------- + + template + vector point_down ( + const vector& p, + unsigned int levels + ) const + { + vector temp = p; + for (unsigned int i = 0; i < levels; ++i) + temp = point_down(temp); + return temp; + } + + template + vector point_up ( + const vector& p, + unsigned int levels + ) const + { + vector 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 + struct both_images_rgb + { + const static bool value = pixel_traits::rgb && + pixel_traits::rgb; + }; + public: + + template < + typename in_image_type, + typename out_image_type + > + typename disable_if >::type operator() ( + const in_image_type& original, + out_image_type& down + ) const + { + // make sure requires clause is not broken + DLIB_ASSERT( is_same_object(original, down) == false, + "\t void pyramid_down_2_1::operator()" + << "\n\t is_same_object(original, down): " << is_same_object(original, down) + << "\n\t this: " << this + ); + + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + + if (original.nr() <= 8 || original.nc() <= 8) { - ptype pix1; - ptype pix2; - ptype pix3; - ptype pix4; - ptype pix5; - - assign_pixel(pix1, original[r][oc]); - assign_pixel(pix2, original[r][oc+1]); - assign_pixel(pix3, original[r][oc+2]); - assign_pixel(pix4, original[r][oc+3]); - assign_pixel(pix5, original[r][oc+4]); - - pix2 *= 4; - pix3 *= 6; - pix4 *= 4; - - assign_pixel(temp_img[r][c], pix1 + pix2 + pix3 + pix4 + pix5); - oc += 2; + down.clear(); + return; } - } + + typedef typename pixel_traits::basic_pixel_type bp_type; + typedef typename promote::type ptype; + array2d temp_img; + temp_img.set_size(original.nr(), (original.nc()-3)/2); + down.set_size((original.nr()-3)/2, (original.nc()-3)/2); - // apply column filter - long dr = 0; - for (long r = 2; r < temp_img.nr()-2; r += 2) - { - for (long c = 0; c < temp_img.nc(); ++c) + // This function applies a 5x5 Gaussian filter to the image. It + // does this by separating the filter into its horizontal and vertical + // components and then downsamples the image by dropping every other + // row and column. Note that we can do these things all together in + // one step. + + // apply row filter + for (long r = 0; r < temp_img.nr(); ++r) { - ptype temp = temp_img[r-2][c] + - temp_img[r-1][c]*4 + - temp_img[r ][c]*6 + - temp_img[r-1][c]*4 + - temp_img[r-2][c]; + long oc = 0; + for (long c = 0; c < temp_img.nc(); ++c) + { + ptype pix1; + ptype pix2; + ptype pix3; + ptype pix4; + ptype pix5; - assign_pixel(down[dr][c],temp/256); + assign_pixel(pix1, original[r][oc]); + assign_pixel(pix2, original[r][oc+1]); + assign_pixel(pix3, original[r][oc+2]); + assign_pixel(pix4, original[r][oc+3]); + assign_pixel(pix5, original[r][oc+4]); + + pix2 *= 4; + pix3 *= 6; + pix4 *= 4; + + assign_pixel(temp_img[r][c], pix1 + pix2 + pix3 + pix4 + pix5); + oc += 2; + } } - ++dr; - } - - } - - private: - struct rgbptype - { - uint16 red; - uint16 green; - uint16 blue; - }; - public: - // ------------------------------------------ - // OVERLOAD FOR RGB TO RGB IMAGES - // ------------------------------------------ - template < - typename in_image_type, - typename out_image_type - > - typename enable_if >::type operator() ( - const in_image_type& original, - out_image_type& down - ) const - { - // make sure requires clause is not broken - DLIB_ASSERT( is_same_object(original, down) == false, - "\t void pyramid_down::operator()" - << "\n\t is_same_object(original, down): " << is_same_object(original, down) - << "\n\t this: " << this - ); - - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - - if (original.nr() <= 8 || original.nc() <= 8) - { - down.clear(); - return; - } - - array2d temp_img; - temp_img.set_size(original.nr(), (original.nc()-3)/2); - down.set_size((original.nr()-3)/2, (original.nc()-3)/2); - // This function applies a 5x5 Gaussian filter to the image. It - // does this by separating the filter into its horizontal and vertical - // components and then downsamples the image by dropping every other - // row and column. Note that we can do these things all together in - // one step. - - // apply row filter - for (long r = 0; r < temp_img.nr(); ++r) - { - long oc = 0; - for (long c = 0; c < temp_img.nc(); ++c) + // apply column filter + long dr = 0; + for (long r = 2; r < temp_img.nr()-2; r += 2) { - rgbptype pix1; - rgbptype pix2; - rgbptype pix3; - rgbptype pix4; - rgbptype pix5; + for (long c = 0; c < temp_img.nc(); ++c) + { + ptype temp = temp_img[r-2][c] + + temp_img[r-1][c]*4 + + temp_img[r ][c]*6 + + temp_img[r-1][c]*4 + + temp_img[r-2][c]; - pix1.red = original[r][oc].red; - pix2.red = original[r][oc+1].red; - pix3.red = original[r][oc+2].red; - pix4.red = original[r][oc+3].red; - pix5.red = original[r][oc+4].red; - pix1.green = original[r][oc].green; - pix2.green = original[r][oc+1].green; - pix3.green = original[r][oc+2].green; - pix4.green = original[r][oc+3].green; - pix5.green = original[r][oc+4].green; - pix1.blue = original[r][oc].blue; - pix2.blue = original[r][oc+1].blue; - pix3.blue = original[r][oc+2].blue; - pix4.blue = original[r][oc+3].blue; - pix5.blue = original[r][oc+4].blue; - - pix2.red *= 4; - pix3.red *= 6; - pix4.red *= 4; - - pix2.green *= 4; - pix3.green *= 6; - pix4.green *= 4; - - pix2.blue *= 4; - pix3.blue *= 6; - pix4.blue *= 4; - - rgbptype temp; - temp.red = pix1.red + pix2.red + pix3.red + pix4.red + pix5.red; - temp.green = pix1.green + pix2.green + pix3.green + pix4.green + pix5.green; - temp.blue = pix1.blue + pix2.blue + pix3.blue + pix4.blue + pix5.blue; - - temp_img[r][c] = temp; - - oc += 2; + assign_pixel(down[dr][c],temp/256); + } + ++dr; } + } - - // apply column filter - long dr = 0; - for (long r = 2; r < temp_img.nr()-2; r += 2) + private: + struct rgbptype { - for (long c = 0; c < temp_img.nc(); ++c) - { - rgbptype temp; - temp.red = temp_img[r-2][c].red + - temp_img[r-1][c].red*4 + - temp_img[r ][c].red*6 + - temp_img[r-1][c].red*4 + - temp_img[r-2][c].red; - temp.green = temp_img[r-2][c].green + - temp_img[r-1][c].green*4 + - temp_img[r ][c].green*6 + - temp_img[r-1][c].green*4 + - temp_img[r-2][c].green; - temp.blue = temp_img[r-2][c].blue + - temp_img[r-1][c].blue*4 + - temp_img[r ][c].blue*6 + - temp_img[r-1][c].blue*4 + - temp_img[r-2][c].blue; - - down[dr][c].red = temp.red/256; - down[dr][c].green = temp.green/256; - down[dr][c].blue = temp.blue/256; - } - ++dr; - } - - } - - private: - - - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class pyramid_down_3_2 : noncopyable - { - public: - - template - vector point_down ( - const vector& p - ) const - { - const double ratio = 2.0/3.0; - //do return (p - vector(1,1))*ratio; - return p*ratio - vector(ratio,ratio); - } - - template - vector point_up ( - const vector& p - ) const - { - const double ratio = 3.0/2.0; - return p*ratio + vector(1,1); - } - - // ----------------------------- - - template - vector point_down ( - const vector& p, - unsigned int levels - ) const - { - vector temp = p; - for (unsigned int i = 0; i < levels; ++i) - temp = point_down(temp); - return temp; - } - - template - vector point_up ( - const vector& p, - unsigned int levels - ) const - { - vector 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 - struct both_images_rgb - { - const static bool value = pixel_traits::rgb && - pixel_traits::rgb; - }; - public: - - template < - typename in_image_type, - typename out_image_type - > - typename disable_if >::type operator() ( - const in_image_type& original, - out_image_type& down - ) const - { - // make sure requires clause is not broken - DLIB_ASSERT(is_same_object(original, down) == false, - "\t void pyramid_down_3_2::operator()" - << "\n\t is_same_object(original, down): " << is_same_object(original, down) - << "\n\t this: " << this - ); - - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - - if (original.nr() <= 8 || original.nc() <= 8) + uint16 red; + uint16 green; + uint16 blue; + }; + public: + // ------------------------------------------ + // OVERLOAD FOR RGB TO RGB IMAGES + // ------------------------------------------ + template < + typename in_image_type, + typename out_image_type + > + typename enable_if >::type operator() ( + const in_image_type& original, + out_image_type& down + ) const { - down.clear(); - return; + // make sure requires clause is not broken + DLIB_ASSERT( is_same_object(original, down) == false, + "\t void pyramid_down_2_1::operator()" + << "\n\t is_same_object(original, down): " << is_same_object(original, down) + << "\n\t this: " << this + ); + + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + + if (original.nr() <= 8 || original.nc() <= 8) + { + down.clear(); + return; + } + + array2d temp_img; + temp_img.set_size(original.nr(), (original.nc()-3)/2); + down.set_size((original.nr()-3)/2, (original.nc()-3)/2); + + + // This function applies a 5x5 Gaussian filter to the image. It + // does this by separating the filter into its horizontal and vertical + // components and then downsamples the image by dropping every other + // row and column. Note that we can do these things all together in + // one step. + + // apply row filter + for (long r = 0; r < temp_img.nr(); ++r) + { + long oc = 0; + for (long c = 0; c < temp_img.nc(); ++c) + { + rgbptype pix1; + rgbptype pix2; + rgbptype pix3; + rgbptype pix4; + rgbptype pix5; + + pix1.red = original[r][oc].red; + pix2.red = original[r][oc+1].red; + pix3.red = original[r][oc+2].red; + pix4.red = original[r][oc+3].red; + pix5.red = original[r][oc+4].red; + pix1.green = original[r][oc].green; + pix2.green = original[r][oc+1].green; + pix3.green = original[r][oc+2].green; + pix4.green = original[r][oc+3].green; + pix5.green = original[r][oc+4].green; + pix1.blue = original[r][oc].blue; + pix2.blue = original[r][oc+1].blue; + pix3.blue = original[r][oc+2].blue; + pix4.blue = original[r][oc+3].blue; + pix5.blue = original[r][oc+4].blue; + + pix2.red *= 4; + pix3.red *= 6; + pix4.red *= 4; + + pix2.green *= 4; + pix3.green *= 6; + pix4.green *= 4; + + pix2.blue *= 4; + pix3.blue *= 6; + pix4.blue *= 4; + + rgbptype temp; + temp.red = pix1.red + pix2.red + pix3.red + pix4.red + pix5.red; + temp.green = pix1.green + pix2.green + pix3.green + pix4.green + pix5.green; + temp.blue = pix1.blue + pix2.blue + pix3.blue + pix4.blue + pix5.blue; + + temp_img[r][c] = temp; + + oc += 2; + } + } + + + // apply column filter + long dr = 0; + for (long r = 2; r < temp_img.nr()-2; r += 2) + { + for (long c = 0; c < temp_img.nc(); ++c) + { + rgbptype temp; + temp.red = temp_img[r-2][c].red + + temp_img[r-1][c].red*4 + + temp_img[r ][c].red*6 + + temp_img[r-1][c].red*4 + + temp_img[r-2][c].red; + temp.green = temp_img[r-2][c].green + + temp_img[r-1][c].green*4 + + temp_img[r ][c].green*6 + + temp_img[r-1][c].green*4 + + temp_img[r-2][c].green; + temp.blue = temp_img[r-2][c].blue + + temp_img[r-1][c].blue*4 + + temp_img[r ][c].blue*6 + + temp_img[r-1][c].blue*4 + + temp_img[r-2][c].blue; + + down[dr][c].red = temp.red/256; + down[dr][c].green = temp.green/256; + down[dr][c].blue = temp.blue/256; + } + ++dr; + } + } - const long size_in = 3; - const long size_out = 2; - - typedef typename pixel_traits::basic_pixel_type bp_type; - typedef typename promote::type ptype; - 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); + private: - 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) - { - 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]*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)); - assign_pixel(down[r+1][c] , (block[2][0]*9 + block[1][0]*3 + block[2][1]*3 + block[1][1])/(16*256)); - assign_pixel(down[r+1][c+1] , (block[2][2]*9 + block[1][2]*3 + block[2][1]*3 + block[1][1])/(16*256)); - - 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; - } - 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)); - } - } - - } - - 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 >::type operator() ( - const in_image_type& original, - out_image_type& down - ) const + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + + class pyramid_down_3_2 : noncopyable { - // make sure requires clause is not broken - DLIB_ASSERT( is_same_object(original, down) == false, - "\t void pyramid_down_3_2::operator()" - << "\n\t is_same_object(original, down): " << is_same_object(original, down) - << "\n\t this: " << this - ); + public: - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - - if (original.nr() <= 8 || original.nc() <= 8) + template + vector point_down ( + const vector& p + ) const { - down.clear(); - return; + const double ratio = 2.0/3.0; + //do return (p - vector(1,1))*ratio; + return p*ratio - vector(ratio,ratio); } - const long size_in = 3; - const long size_out = 2; - - 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) + template + vector point_up ( + const vector& p + ) const { - 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); - - // bi-linearly interpolate 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); - - 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); - - down[r+1][c+1].red = (block[2][2].red*9 + block[1][2].red*3 + block[2][1].red*3 + block[1][1].red)/(16*256); - down[r+1][c+1].green = (block[2][2].green*9 + block[1][2].green*3 + block[2][1].green*3 + block[1][1].green)/(16*256); - down[r+1][c+1].blue = (block[2][2].blue*9 + block[1][2].blue*3 + block[2][1].blue*3 + block[1][1].blue)/(16*256); - - 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; - } - 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: - - - }; - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - class pyramid_down_4_3 : noncopyable - { - public: - - template - vector point_down ( - const vector& p - ) const - { - const double ratio = 3.0/4.0; - //do return (p - vector(1,1))*ratio; - return p*ratio - vector(ratio,ratio); - } - - template - vector point_up ( - const vector& p - ) const - { - const double ratio = 4.0/3.0; - return p*ratio + vector(1,1); - } - - // ----------------------------- - - template - vector point_down ( - const vector& p, - unsigned int levels - ) const - { - vector temp = p; - for (unsigned int i = 0; i < levels; ++i) - temp = point_down(temp); - return temp; - } - - template - vector point_up ( - const vector& p, - unsigned int levels - ) const - { - vector 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 - struct both_images_rgb - { - const static bool value = pixel_traits::rgb && - pixel_traits::rgb; - }; - public: - - template < - typename in_image_type, - typename out_image_type - > - typename disable_if >::type operator() ( - const in_image_type& original, - out_image_type& down - ) const - { - // make sure requires clause is not broken - DLIB_ASSERT( is_same_object(original, down) == false, - "\t void pyramid_down_4_3::operator()" - << "\n\t is_same_object(original, down): " << is_same_object(original, down) - << "\n\t this: " << this - ); - - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - - if (original.nr() <= 8 || original.nc() <= 8) - { - down.clear(); - return; + const double ratio = 3.0/2.0; + return p*ratio + vector(1,1); } - const long size_in = 4; - const long size_out = 3; + // ----------------------------- - typedef typename pixel_traits::basic_pixel_type bp_type; - typedef typename promote::type ptype; - 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) + template + vector point_down ( + const vector& p, + unsigned int levels + ) const { - long cc = 1; - long c; - for (c = 0; c < full_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; - } - 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; + vector temp = p; + for (unsigned int i = 0; i < levels; ++i) + temp = point_down(temp); + return temp; } - if (part_nr - full_nr == 2) + template + vector point_up ( + const vector& p, + unsigned int levels + ) const { - 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)); - } + vector temp = p; + for (unsigned int i = 0; i < levels; ++i) + temp = point_up(temp); + return temp; } - else if (part_nr - full_nr == 1) + + // ----------------------------- + + rectangle rect_up ( + const rectangle& rect + ) const { - long cc = 1; - long c; - for (c = 0; c < full_nc; c+=size_out) + 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 + struct both_images_rgb + { + const static bool value = pixel_traits::rgb && + pixel_traits::rgb; + }; + public: + + template < + typename in_image_type, + typename out_image_type + > + typename disable_if >::type operator() ( + const in_image_type& original, + out_image_type& down + ) const + { + // make sure requires clause is not broken + DLIB_ASSERT(is_same_object(original, down) == false, + "\t void pyramid_down_3_2::operator()" + << "\n\t is_same_object(original, down): " << is_same_object(original, down) + << "\n\t this: " << this + ); + + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + + if (original.nr() <= 8 || original.nc() <= 8) { - 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; + down.clear(); + return; } - 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)); + const long size_in = 3; + const long size_out = 2; + + typedef typename pixel_traits::basic_pixel_type bp_type; + typedef typename promote::type ptype; + 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) + { + ptype block[size_in][size_in]; + separable_3x3_filter_block_grayscale(block, original, rr, cc, 2, 12, 2); + + // bi-linearly interpolate 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)); + assign_pixel(down[r+1][c] , (block[2][0]*9 + block[1][0]*3 + block[2][1]*3 + block[1][1])/(16*256)); + assign_pixel(down[r+1][c+1] , (block[2][2]*9 + block[1][2]*3 + block[2][1]*3 + block[1][1])/(16*256)); + + cc += size_in; + } + if (part_nc - full_nc == 1) + { + ptype block[size_in][2]; + separable_3x3_filter_block_grayscale(block, original, rr, cc, 2, 12, 2); + + // 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; } - else if (part_nc - full_nc == 1) + if (part_nr - full_nr == 1) { - ptype block[2][2]; - separable_3x3_filter_block_grayscale(block, original, rr, cc, 3, 10, 3); + 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, 2, 12, 2); - // 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)); + // 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, 2, 12, 2); + + // 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)); + } + } + + } + + 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 >::type operator() ( + const in_image_type& original, + out_image_type& down + ) const + { + // make sure requires clause is not broken + DLIB_ASSERT( is_same_object(original, down) == false, + "\t void pyramid_down_3_2::operator()" + << "\n\t is_same_object(original, down): " << is_same_object(original, down) + << "\n\t this: " << this + ); + + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + + if (original.nr() <= 8 || original.nc() <= 8) + { + down.clear(); + return; + } + + const long size_in = 3; + const long size_out = 2; + + 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, 2, 12, 2); + + // bi-linearly interpolate 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); + + 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); + + down[r+1][c+1].red = (block[2][2].red*9 + block[1][2].red*3 + block[2][1].red*3 + block[1][1].red)/(16*256); + down[r+1][c+1].green = (block[2][2].green*9 + block[1][2].green*3 + block[2][1].green*3 + block[1][1].green)/(16*256); + down[r+1][c+1].blue = (block[2][2].blue*9 + block[1][2].blue*3 + block[2][1].blue*3 + block[1][1].blue)/(16*256); + + cc += size_in; + } + if (part_nc - full_nc == 1) + { + rgbptype block[size_in][2]; + separable_3x3_filter_block_rgb(block, original, rr, cc, 2, 12, 2); + + // 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; + } + 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, 2, 12, 2); + + // 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, 2, 12, 2); + + // 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: - 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 >::type operator() ( - const in_image_type& original, - out_image_type& down - ) const - { - // make sure requires clause is not broken - DLIB_ASSERT(is_same_object(original, down) == false, - "\t void pyramid_down_4_3::operator()" - << "\n\t is_same_object(original, down): " << is_same_object(original, down) - << "\n\t this: " << this - ); - - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - - if (original.nr() <= 8 || original.nc() <= 8) - { - down.clear(); - return; - } - - const long size_in = 4; - const long size_out = 3; - - 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); - - // 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; - } - 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*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); - - 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); - } - 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*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); - - 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); - } - - rr += size_in; - } - - - 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 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); - - 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 - vector point_down ( - const vector& p - ) const - { - const double ratio = 4.0/5.0; - //do return (p - vector(1,1))*ratio; - return p*ratio - vector(ratio,ratio); - } - - template - vector point_up ( - const vector& p - ) const - { - const double ratio = 5.0/4.0; - return p*ratio + vector(1,1); - } - - // ----------------------------- - - template - vector point_down ( - const vector& p, - unsigned int levels - ) const - { - vector temp = p; - for (unsigned int i = 0; i < levels; ++i) - temp = point_down(temp); - return temp; - } - - template - vector point_up ( - const vector& p, - unsigned int levels - ) const - { - vector 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 - struct both_images_rgb - { - const static bool value = pixel_traits::rgb && - pixel_traits::rgb; - }; - public: - - template < - typename in_image_type, - typename out_image_type - > - typename disable_if >::type operator() ( - const in_image_type& original, - out_image_type& down - ) const - { - // make sure requires clause is not broken - DLIB_ASSERT(is_same_object(original, down) == false, - "\t void pyramid_down_5_4::operator()" - << "\n\t is_same_object(original, down): " << is_same_object(original, down) - << "\n\t this: " << this - ); - - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - - if (original.nr() <= 8 || original.nc() <= 8) - { - down.clear(); - return; - } - - const long size_in = 5; - const long size_out = 4; - - typedef typename pixel_traits::basic_pixel_type bp_type; - typedef typename promote::type ptype; - 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) - { - ptype block[size_in][size_in]; - separable_3x3_filter_block_grayscale(block, original, rr, cc, 2, 12, 2); - - // bi-linearly interpolate 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)); - - 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)); - assign_pixel(down[r+3][c+3] , (block[4][4]*49 + block[4][3]*7 + block[3][4]*7 + block[3][3] )/(64*256)); - - cc += size_in; - } - - if (part_nc - full_nc == 3) - { - ptype block[size_in][4]; - separable_3x3_filter_block_grayscale(block, original, rr, cc, 2, 12, 2); - - // 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)); - - 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) - { - ptype block[size_in][3]; - separable_3x3_filter_block_grayscale(block, original, rr, cc, 2, 12, 2); - - // 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)); - - 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)); - } - else if (part_nc - full_nc == 1) - { - ptype block[size_in][2]; - separable_3x3_filter_block_grayscale(block, original, rr, cc, 2, 12, 2); - - // 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)); - - 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; - } - - if (part_nr - full_nr == 3) - { - long cc = 1; - long c; - for (c = 0; c < full_nc; c+=size_out) - { - ptype block[4][size_in]; - separable_3x3_filter_block_grayscale(block, original, rr, cc, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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 >::type operator() ( - const in_image_type& original, - out_image_type& down - ) const - { - // make sure requires clause is not broken - DLIB_ASSERT(is_same_object(original, down) == false, - "\t void pyramid_down_5_4::operator()" - << "\n\t is_same_object(original, down): " << is_same_object(original, down) - << "\n\t this: " << this - ); - - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - - if (original.nr() <= 8 || original.nc() <= 8) - { - down.clear(); - return; - } - - 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, 2, 12, 2); - - // bi-linearly interpolate 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); - - 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); - - down[r+3][c+3].red = (block[4][4].red*49 + block[4][3].red*7 + block[3][4].red*7 + block[3][3].red )/(64*256); - down[r+3][c+3].green = (block[4][4].green*49 + block[4][3].green*7 + block[3][4].green*7 + block[3][3].green )/(64*256); - down[r+3][c+3].blue = (block[4][4].blue*49 + block[4][3].blue*7 + block[3][4].blue*7 + block[3][3].blue )/(64*256); - - - cc += size_in; - } - - if (part_nc - full_nc == 3) - { - rgbptype block[size_in][4]; - separable_3x3_filter_block_rgb(block, original, rr, cc, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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, 2, 12, 2); - - // 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: - - - }; + } // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- @@ -2339,7 +778,7 @@ namespace dlib template < unsigned int N > - class pyramid_down_generic : noncopyable + class pyramid_down : noncopyable { public: @@ -2434,7 +873,7 @@ namespace dlib { // make sure requires clause is not broken DLIB_ASSERT(is_same_object(original, down) == false, - "\t void pyramid_down_generic::operator()" + "\t void pyramid_down::operator()" << "\n\t is_same_object(original, down): " << is_same_object(original, down) << "\n\t this: " << this ); @@ -2450,7 +889,10 @@ namespace dlib }; template <> - class pyramid_down_generic<2> : public pyramid_down {}; + class pyramid_down<2> : public dlib::impl::pyramid_down_2_1 {}; + + template <> + class pyramid_down<3> : public dlib::impl::pyramid_down_3_2 {}; // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- diff --git a/dlib/image_transforms/image_pyramid_abstract.h b/dlib/image_transforms/image_pyramid_abstract.h index 0be6b4255..e43c17878 100644 --- a/dlib/image_transforms/image_pyramid_abstract.h +++ b/dlib/image_transforms/image_pyramid_abstract.h @@ -10,11 +10,18 @@ namespace dlib { + template < + unsigned int N + > class pyramid_down : noncopyable { /*! + REQUIREMENTS ON N + N > 1 + WHAT THIS OBJECT REPRESENTS - This is a simple functor to help create image pyramids. + This is a simple functor to help create image pyramids. In particular, it + downsamples images at a ratio of N to N-1. WARNING, when mapping rectangles from one layer of a pyramid @@ -43,18 +50,14 @@ namespace dlib - pixel_traits::has_alpha == false - pixel_traits::has_alpha == false ensures - - #down will contain an image that is roughly half the size of the original - image. To be specific, this function performs the following steps: - - 1. Applies a 5x5 Gaussian filter to the original image to smooth it a little. - - 2. Every other row and column is discarded to create an image half the size - of the original. This smaller image is stored in #down. - - if both input and output images contain RGB pixels then the downsampled image will + - #down will contain an image that is roughly (N-1)/N times the size of the + original image. + - If both input and output images contain RGB pixels then the downsampled image will be in color. Otherwise, the downsampling will be performed in a grayscale mode. - The location of a point P in original image will show up at point point_down(P) in the #down image. - - Note that some points on the border of the original image will correspond to - points outside the #down image. This is because the 5x5 filter is not applied - at the borders. + - Note that some points on the border of the original image might correspond to + points outside the #down image. !*/ // ------------------------------- @@ -151,61 +154,6 @@ namespace dlib }; -// ---------------------------------------------------------------------------------------- - - class pyramid_down_3_2 : noncopyable - { - /*! - WHAT THIS OBJECT REPRESENTS - This is a function object with an interface identical to pyramid_down (defined - at the top of this file) except that it downsamples images at a ratio of 3 to 2 - instead of 2 to 1. - !*/ - }; - - -// ---------------------------------------------------------------------------------------- - - class pyramid_down_4_3 : noncopyable - { - /*! - WHAT THIS OBJECT REPRESENTS - This is a function object with an interface identical to pyramid_down (defined - at the top of this file) except that it downsamples images at a ratio of 4 to 3 - instead of 2 to 1. - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - class pyramid_down_5_4 : noncopyable - { - /*! - WHAT THIS OBJECT REPRESENTS - This is a function object with an interface identical to pyramid_down (defined - at the top of this file) except that it downsamples images at a ratio of 5 to 4 - instead of 2 to 1. - !*/ - }; - -// ---------------------------------------------------------------------------------------- - - template < - unsigned int N - > - class pyramid_down_generic : noncopyable - { - /*! - REQUIREMENTS ON N - N > 1 - - WHAT THIS OBJECT REPRESENTS - This is a function object with an interface identical to pyramid_down - (defined at the top of this file) except that it downsamples images at a - ratio of N to N-1 instead of 2 to 1. - !*/ - }; - // ---------------------------------------------------------------------------------------- class pyramid_disable : noncopyable diff --git a/dlib/test/object_detector.cpp b/dlib/test/object_detector.cpp index 45a6e460c..3255e4b61 100644 --- a/dlib/test/object_detector.cpp +++ b/dlib/test/object_detector.cpp @@ -379,7 +379,7 @@ namespace make_simple_test_data(images, object_locations); typedef hashed_feature_image > feature_extractor_type; - typedef scan_image_pyramid image_scanner_type; + typedef scan_image_pyramid, feature_extractor_type> image_scanner_type; image_scanner_type scanner; const rectangle object_box = compute_box_dimensions(1,35*35); scanner.add_detection_template(object_box, create_grid_detection_template(object_box,2,2)); @@ -463,7 +463,7 @@ namespace make_simple_test_data(images, object_locations); typedef hashed_feature_image > feature_extractor_type; - typedef scan_image_pyramid image_scanner_type; + typedef scan_image_pyramid, feature_extractor_type> image_scanner_type; image_scanner_type scanner; const rectangle object_box = compute_box_dimensions(1,35*35); std::vector mboxes; @@ -512,7 +512,7 @@ namespace make_simple_test_data(images, object_locations); typedef hashed_feature_image > feature_extractor_type; - typedef scan_image_pyramid image_scanner_type; + typedef scan_image_pyramid, feature_extractor_type> image_scanner_type; image_scanner_type scanner; const rectangle object_box = compute_box_dimensions(1,35*35); scanner.add_detection_template(object_box, create_grid_detection_template(object_box,2,2)); @@ -555,7 +555,7 @@ namespace make_simple_test_data(images, object_locations); typedef hashed_feature_image > feature_extractor_type; - typedef scan_image_pyramid image_scanner_type; + typedef scan_image_pyramid, feature_extractor_type> image_scanner_type; image_scanner_type scanner; const rectangle object_box = compute_box_dimensions(1,35*35); scanner.add_detection_template(object_box, create_grid_detection_template(object_box,2,2)); @@ -598,7 +598,7 @@ namespace make_simple_test_data(images, object_locations); typedef hashed_feature_image > feature_extractor_type; - typedef scan_image_pyramid image_scanner_type; + typedef scan_image_pyramid, feature_extractor_type> image_scanner_type; image_scanner_type scanner; const rectangle object_box = compute_box_dimensions(1,35*35); std::vector mboxes; @@ -647,12 +647,12 @@ namespace make_simple_test_data(images, object_locations); typedef nearest_neighbor_feature_image > feature_extractor_type; - typedef scan_image_pyramid image_scanner_type; + typedef scan_image_pyramid, feature_extractor_type> image_scanner_type; image_scanner_type scanner; setup_grid_detection_templates(scanner, object_locations, 2, 2); feature_extractor_type nnfe; - pyramid_down pyr_down; + pyramid_down<2> pyr_down; poly_image<5> polyi; nnfe.set_basis(randomly_sample_image_features(images, pyr_down, polyi, 80)); scanner.copy_configuration(nnfe); @@ -697,7 +697,7 @@ namespace image_scanner_type scanner; feature_extractor_type nnfe; - pyramid_down pyr_down; + pyramid_down<2> pyr_down; poly_image<5> polyi; nnfe.set_basis(randomly_sample_image_features(images, pyr_down, polyi, 80)); scanner.copy_configuration(nnfe); @@ -737,7 +737,7 @@ namespace std::vector > object_locations; make_simple_test_data(images, object_locations); - typedef scan_image_pyramid image_scanner_type; + typedef scan_image_pyramid, very_simple_feature_extractor> image_scanner_type; image_scanner_type scanner; const rectangle object_box = compute_box_dimensions(1,70*70); scanner.add_detection_template(object_box, create_grid_detection_template(object_box,2,2)); @@ -771,7 +771,7 @@ namespace class pyramid_down_funny : noncopyable { - pyramid_down pyr; + pyramid_down<2> pyr; public: template diff --git a/dlib/test/pyramid_down.cpp b/dlib/test/pyramid_down.cpp index c2f549dab..4c9a9516d 100644 --- a/dlib/test/pyramid_down.cpp +++ b/dlib/test/pyramid_down.cpp @@ -23,7 +23,7 @@ namespace void test_pyramid_down_grayscale() { array2d img, down; - pyramid_down pyr; + pyramid_down<2> pyr; img.set_size(300,264); @@ -52,7 +52,7 @@ void test_pyramid_down_rgb() { array2d img; array2d down; - pyramid_down pyr; + pyramid_down<2> pyr; img.set_size(231, 351); @@ -325,59 +325,59 @@ void test_pyramid_down_small_sizes() test_pyramid_down_rgb(); print_spinner(); - dlog << LINFO << "call test_pyramid_down_small_sizes();"; - test_pyramid_down_small_sizes(); - dlog << LINFO << "call test_pyramid_down_small_sizes();"; - test_pyramid_down_small_sizes(); - dlog << LINFO << "call test_pyramid_down_small_sizes();"; - test_pyramid_down_small_sizes(); - dlog << LINFO << "call test_pyramid_down_small_sizes();"; - test_pyramid_down_small_sizes(); + dlog << LINFO << "call test_pyramid_down_small_sizes >();"; + test_pyramid_down_small_sizes >(); + dlog << LINFO << "call test_pyramid_down_small_sizes >();"; + test_pyramid_down_small_sizes >(); + dlog << LINFO << "call test_pyramid_down_small_sizes >();"; + test_pyramid_down_small_sizes >(); + dlog << LINFO << "call test_pyramid_down_small_sizes >();"; + test_pyramid_down_small_sizes >(); dlog << LINFO << "call test_pyramid_down_small_sizes();"; test_pyramid_down_small_sizes(); - dlog << LINFO << "call test_pyramid_down_small_sizes >();"; - test_pyramid_down_small_sizes >(); + dlog << LINFO << "call test_pyramid_down_small_sizes >();"; + test_pyramid_down_small_sizes >(); print_spinner(); - dlog << LINFO << "call test_pyramid_down_rgb2();"; - test_pyramid_down_rgb2(); + dlog << LINFO << "call test_pyramid_down_rgb2 >();"; + test_pyramid_down_rgb2 >(); print_spinner(); - dlog << LINFO << "call test_pyramid_down_rgb2();"; - test_pyramid_down_rgb2(); + dlog << LINFO << "call test_pyramid_down_rgb2 >();"; + test_pyramid_down_rgb2 >(); print_spinner(); - dlog << LINFO << "call test_pyramid_down_rgb2();"; - test_pyramid_down_rgb2(); + dlog << LINFO << "call test_pyramid_down_rgb2 >();"; + test_pyramid_down_rgb2 >(); print_spinner(); - dlog << LINFO << "call test_pyramid_down_rgb2();"; - test_pyramid_down_rgb2(); + dlog << LINFO << "call test_pyramid_down_rgb2 >();"; + test_pyramid_down_rgb2 >(); print_spinner(); - dlog << LINFO << "call test_pyramid_down_rgb2 >();"; - test_pyramid_down_rgb2 >(); + dlog << LINFO << "call test_pyramid_down_rgb2 >();"; + test_pyramid_down_rgb2 >(); print_spinner(); - dlog << LINFO << "call test_pyramid_down_grayscale2();"; - test_pyramid_down_grayscale2(); + dlog << LINFO << "call test_pyramid_down_grayscale2 >();"; + test_pyramid_down_grayscale2 >(); print_spinner(); - dlog << LINFO << "call test_pyramid_down_grayscale2();"; - test_pyramid_down_grayscale2(); + dlog << LINFO << "call test_pyramid_down_grayscale2 >();"; + test_pyramid_down_grayscale2 >(); print_spinner(); - dlog << LINFO << "call test_pyramid_down_grayscale2();"; - test_pyramid_down_grayscale2(); + dlog << LINFO << "call test_pyramid_down_grayscale2 >();"; + test_pyramid_down_grayscale2 >(); print_spinner(); - dlog << LINFO << "call test_pyramid_down_grayscale2();"; - test_pyramid_down_grayscale2(); + dlog << LINFO << "call test_pyramid_down_grayscale2 >();"; + test_pyramid_down_grayscale2 >(); print_spinner(); - dlog << LINFO << "call test_pyramid_down_grayscale2 >();"; - test_pyramid_down_grayscale2 >(); + dlog << LINFO << "call test_pyramid_down_grayscale2 >();"; + test_pyramid_down_grayscale2 >(); } } a; diff --git a/examples/object_detector_advanced_ex.cpp b/examples/object_detector_advanced_ex.cpp index 787d48b8c..cd70636cf 100644 --- a/examples/object_detector_advanced_ex.cpp +++ b/examples/object_detector_advanced_ex.cpp @@ -196,7 +196,7 @@ int main() make_simple_test_data(images, object_locations); - typedef scan_image_pyramid image_scanner_type; + typedef scan_image_pyramid, very_simple_feature_extractor> image_scanner_type; image_scanner_type scanner; // Instead of using setup_grid_detection_templates() like in object_detector_ex.cpp, lets manually // setup the sliding window box. We use a window with the same shape as the white boxes we diff --git a/examples/object_detector_ex.cpp b/examples/object_detector_ex.cpp index 5e3ffc49d..dc94c9789 100644 --- a/examples/object_detector_ex.cpp +++ b/examples/object_detector_ex.cpp @@ -145,11 +145,12 @@ int main() parameters yourself. They are automatically populated by the structural_object_detection_trainer. - The sliding window classifiers described above are applied to every level of an image - pyramid. So you need to tell scan_image_pyramid what kind of pyramid you want to - use. In this case we are using pyramid_down which downsamples each pyramid layer by - half (dlib also contains other version of pyramid_down which result in finer grained - pyramids). + The sliding window classifiers described above are applied to every level of an + image pyramid. So you need to tell scan_image_pyramid what kind of pyramid you want + to use. In this case we are using pyramid_down<2> which downsamples each pyramid + layer by half (if you want to use a finer image pyramid then just change the + template argument to a larger value. For example, using pyramid_down<5> would + downsample each layer by a ratio of 5 to 4). Finally, some of the feature extraction zones are allowed to move freely within the object box. This means that when we are sliding the classifier over an image, some @@ -168,7 +169,7 @@ int main() feature extraction regions. */ typedef hashed_feature_image > feature_extractor_type; - typedef scan_image_pyramid image_scanner_type; + typedef scan_image_pyramid, feature_extractor_type> image_scanner_type; image_scanner_type scanner; // The hashed_feature_image in the scanner needs to be supplied with a hash function capable diff --git a/examples/train_object_detector.cpp b/examples/train_object_detector.cpp index f1cff2ea2..4f983c896 100644 --- a/examples/train_object_detector.cpp +++ b/examples/train_object_detector.cpp @@ -133,7 +133,7 @@ int main(int argc, char** argv) typedef hashed_feature_image > feature_extractor_type; - typedef scan_image_pyramid image_scanner_type; + typedef scan_image_pyramid, feature_extractor_type> image_scanner_type; if (parser.option("t") || parser.option("cross-validate")) {