// Copyright (C) 2009 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_INTEGRAL_IMAGE #define DLIB_INTEGRAL_IMAGE #include "integral_image_abstract.h" #include "../algs.h" #include "../assert.h" #include "../geometry.h" #include "../array2d.h" #include "../matrix.h" #include "../pixel.h" #include "../noncopyable.h" namespace dlib { // ---------------------------------------------------------------------------------------- template < typename T > class integral_image_generic : noncopyable { public: typedef T value_type; long nr() const { return int_img.nr(); } long nc() const { return int_img.nc(); } template <typename image_type> void load ( const image_type& img_ ) { const_image_view<image_type> img(img_); T pixel; int_img.set_size(img.nr(), img.nc()); // compute the first row of the integral image T temp = 0; for (long c = 0; c < img.nc(); ++c) { assign_pixel(pixel, img[0][c]); temp += pixel; int_img[0][c] = temp; } // now compute the rest of the integral image for (long r = 1; r < img.nr(); ++r) { temp = 0; for (long c = 0; c < img.nc(); ++c) { assign_pixel(pixel, img[r][c]); temp += pixel; int_img[r][c] = temp + int_img[r-1][c]; } } } value_type get_sum_of_area ( const rectangle& rect ) const { DLIB_ASSERT(get_rect(*this).contains(rect) == true && rect.is_empty() == false, "\tvalue_type get_sum_of_area(rect)" << "\n\tYou have given a rectangle that goes outside the image" << "\n\tthis: " << this << "\n\trect.is_empty(): " << rect.is_empty() << "\n\trect: " << rect << "\n\tget_rect(*this): " << get_rect(*this) ); T top_left = 0, top_right = 0, bottom_left = 0, bottom_right = 0; bottom_right = int_img[rect.bottom()][rect.right()]; if (rect.left()-1 >= 0 && rect.top()-1 >= 0) { top_left = int_img[rect.top()-1][rect.left()-1]; bottom_left = int_img[rect.bottom()][rect.left()-1]; top_right = int_img[rect.top()-1][rect.right()]; } else if (rect.left()-1 >= 0) { bottom_left = int_img[rect.bottom()][rect.left()-1]; } else if (rect.top()-1 >= 0) { top_right = int_img[rect.top()-1][rect.right()]; } return bottom_right - bottom_left - top_right + top_left; } void swap(integral_image_generic& item) { int_img.swap(item.int_img); } private: array2d<T> int_img; }; template < typename T > void swap ( integral_image_generic<T>& a, integral_image_generic<T>& b ) { a.swap(b); } // ---------------------------------------------------------------------------------------- typedef integral_image_generic<long> integral_image; // ---------------------------------------------------------------------------------------- template <typename integral_image_type> typename integral_image_type::value_type haar_x ( const integral_image_type& img, const point& p, long width ) { DLIB_ASSERT(get_rect(img).contains(centered_rect(p,width,width)) == true, "\tlong haar_x(img,p,width)" << "\n\tYou have given a point and with that goes outside the image" << "\n\tget_rect(img): " << get_rect(img) << "\n\tp: " << p << "\n\twidth: " << width ); rectangle left_rect; left_rect.set_left ( p.x() - width / 2 ); left_rect.set_top ( p.y() - width / 2 ); left_rect.set_right ( p.x()-1 ); left_rect.set_bottom ( left_rect.top() + width - 1 ); rectangle right_rect; right_rect.set_left ( p.x() ); right_rect.set_top ( left_rect.top() ); right_rect.set_right ( left_rect.left() + width -1 ); right_rect.set_bottom ( left_rect.bottom() ); return img.get_sum_of_area(right_rect) - img.get_sum_of_area(left_rect); } // ---------------------------------------------------------------------------- template <typename integral_image_type> typename integral_image_type::value_type haar_y ( const integral_image_type& img, const point& p, long width ) { DLIB_ASSERT(get_rect(img).contains(centered_rect(p,width,width)) == true, "\tlong haar_y(img,p,width)" << "\n\tYou have given a point and with that goes outside the image" << "\n\tget_rect(img): " << get_rect(img) << "\n\tp: " << p << "\n\twidth: " << width ); rectangle top_rect; top_rect.set_left ( p.x() - width / 2 ); top_rect.set_top ( p.y() - width / 2 ); top_rect.set_right ( top_rect.left() + width - 1 ); top_rect.set_bottom ( p.y()-1 ); rectangle bottom_rect; bottom_rect.set_left ( top_rect.left() ); bottom_rect.set_top ( p.y() ); bottom_rect.set_right ( top_rect.right() ); bottom_rect.set_bottom ( top_rect.top() + width - 1 ); return img.get_sum_of_area(bottom_rect) - img.get_sum_of_area(top_rect); } // ---------------------------------------------------------------------------------------- } #endif // DLIB_INTEGRAL_IMAGE