Commit 93121255 authored by Davis King's avatar Davis King

Made the integral_image more general by making it templated on the

type of scalar used to store the sums.
parent 2d0d3c9e
...@@ -18,10 +18,13 @@ namespace dlib ...@@ -18,10 +18,13 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
class integral_image : noncopyable template <
typename T
>
class integral_image_generic : noncopyable
{ {
public: public:
typedef long value_type; typedef T value_type;
long nr() const { return int_img.nr(); } long nr() const { return int_img.nr(); }
long nc() const { return int_img.nc(); } long nc() const { return int_img.nc(); }
...@@ -31,11 +34,11 @@ namespace dlib ...@@ -31,11 +34,11 @@ namespace dlib
const image_type& img const image_type& img
) )
{ {
long pixel; T pixel;
int_img.set_size(img.nr(), img.nc()); int_img.set_size(img.nr(), img.nc());
// compute the first row of the integral image // compute the first row of the integral image
long temp = 0; T temp = 0;
for (long c = 0; c < img.nc(); ++c) for (long c = 0; c < img.nc(); ++c)
{ {
assign_pixel(pixel, img[0][c]); assign_pixel(pixel, img[0][c]);
...@@ -57,12 +60,12 @@ namespace dlib ...@@ -57,12 +60,12 @@ namespace dlib
} }
long get_sum_of_area ( value_type get_sum_of_area (
const rectangle& rect const rectangle& rect
) const ) const
{ {
DLIB_ASSERT(get_rect(*this).contains(rect) == true && rect.is_empty() == false, DLIB_ASSERT(get_rect(*this).contains(rect) == true && rect.is_empty() == false,
"\tlong get_sum_of_area(rect)" "\tvalue_type get_sum_of_area(rect)"
<< "\n\tYou have given a rectangle that goes outside the image" << "\n\tYou have given a rectangle that goes outside the image"
<< "\n\tthis: " << this << "\n\tthis: " << this
<< "\n\trect.is_empty(): " << rect.is_empty() << "\n\trect.is_empty(): " << rect.is_empty()
...@@ -70,7 +73,7 @@ namespace dlib ...@@ -70,7 +73,7 @@ namespace dlib
<< "\n\tget_rect(*this): " << get_rect(*this) << "\n\tget_rect(*this): " << get_rect(*this)
); );
long top_left = 0, top_right = 0, bottom_left = 0, bottom_right = 0; T top_left = 0, top_right = 0, bottom_left = 0, bottom_right = 0;
bottom_right = int_img[rect.bottom()][rect.right()]; bottom_right = int_img[rect.bottom()][rect.right()];
if (rect.left()-1 >= 0 && rect.top()-1 >= 0) if (rect.left()-1 >= 0 && rect.top()-1 >= 0)
...@@ -93,11 +96,15 @@ namespace dlib ...@@ -93,11 +96,15 @@ namespace dlib
private: private:
array2d<long> int_img; array2d<T> int_img;
}; };
// ----------------------------------------------------------------------------------------
typedef integral_image_generic<long> integral_image;
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename integral_image_type> template <typename integral_image_type>
......
...@@ -13,9 +13,17 @@ namespace dlib ...@@ -13,9 +13,17 @@ namespace dlib
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
class integral_image : noncopyable template <
typename T
>
class integral_image_generic : noncopyable
{ {
/*! /*!
REQUIREMENTS ON T
T should be a built in scalar type. Moreover, it should
be capable of storing sums of whatever kind of pixel
you will be dealing with.
INITIAL VALUE INITIAL VALUE
- nr() == 0 - nr() == 0
- nc() == 0 - nc() == 0
...@@ -29,7 +37,7 @@ namespace dlib ...@@ -29,7 +37,7 @@ namespace dlib
constant time. constant time.
!*/ !*/
public: public:
typedef long value_type; typedef T value_type;
const long nr( const long nr(
) const; ) const;
...@@ -52,7 +60,7 @@ namespace dlib ...@@ -52,7 +60,7 @@ namespace dlib
/*! /*!
requires requires
- image_type == a type that implements the array2d/array2d_kernel_abstract.h interface - image_type == a type that implements the array2d/array2d_kernel_abstract.h interface
- pixel_traits<typename image_type::type>::is_unsigned == true - pixel_traits<typename image_type::type>::has_alpha == false
ensures ensures
- #nr() == img.nr() - #nr() == img.nr()
- #nc() == img.nc() - #nc() == img.nc()
...@@ -77,6 +85,10 @@ namespace dlib ...@@ -77,6 +85,10 @@ namespace dlib
}; };
// ----------------------------------------------------------------------------------------
typedef integral_image_generic<long> integral_image;
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template <typename integral_image_type> template <typename integral_image_type>
...@@ -88,8 +100,8 @@ namespace dlib ...@@ -88,8 +100,8 @@ namespace dlib
/*! /*!
requires requires
- get_rect(img).contains(centered_rect(p,width,width)) == true - get_rect(img).contains(centered_rect(p,width,width)) == true
- integral_image_type == a type that implements the integral_image interface - integral_image_type == a type that implements the integral_image_generic
defined above interface defined above
ensures ensures
- returns the response of a Haar wavelet centered at the point p - returns the response of a Haar wavelet centered at the point p
with the given width. The wavelet is oriented along the X axis with the given width. The wavelet is oriented along the X axis
...@@ -113,8 +125,8 @@ namespace dlib ...@@ -113,8 +125,8 @@ namespace dlib
/*! /*!
requires requires
- get_rect(img).contains(centered_rect(p,width,width)) == true - get_rect(img).contains(centered_rect(p,width,width)) == true
- integral_image_type == a type that implements the integral_image interface - integral_image_type == a type that implements the integral_image_generic
defined above interface defined above
ensures ensures
- returns the response of a Haar wavelet centered at the point p - returns the response of a Haar wavelet centered at the point p
with the given width in the given image. The wavelet is oriented with the given width in the given image. The wavelet is oriented
......
...@@ -703,13 +703,14 @@ namespace ...@@ -703,13 +703,14 @@ namespace
} }
template <typename T, typename pixel_type>
void test_integral_image ( void test_integral_image (
) )
{ {
dlib::rand rnd; dlib::rand rnd;
array2d<unsigned char> img; array2d<pixel_type> img;
integral_image int_img; integral_image_generic<T> int_img;
int_img.load(img); int_img.load(img);
DLIB_TEST(int_img.nr() == 0); DLIB_TEST(int_img.nr() == 0);
...@@ -725,7 +726,7 @@ namespace ...@@ -725,7 +726,7 @@ namespace
{ {
for (long c = 0; c < img.nc(); ++c) for (long c = 0; c < img.nc(); ++c)
{ {
img[r][c] = rnd.get_random_8bit_number(); img[r][c] = (int)rnd.get_random_8bit_number() - 100;
} }
} }
...@@ -734,14 +735,14 @@ namespace ...@@ -734,14 +735,14 @@ namespace
DLIB_TEST(int_img.nc() == img.nc()); DLIB_TEST(int_img.nc() == img.nc());
// make 200 random rectangles // make 200 random rectangles
for (int j = 0; j < 200; ++j) for (int j = 0; j < 500; ++j)
{ {
point p1(rnd.get_random_32bit_number()%img.nc(), rnd.get_random_32bit_number()%img.nr()); point p1(rnd.get_random_32bit_number()%img.nc(), rnd.get_random_32bit_number()%img.nr());
point p2(rnd.get_random_32bit_number()%img.nc(), rnd.get_random_32bit_number()%img.nr()); point p2(rnd.get_random_32bit_number()%img.nc(), rnd.get_random_32bit_number()%img.nr());
rectangle rect(p1,p2); rectangle rect(p1,p2);
DLIB_TEST(int_img.get_sum_of_area(rect) == sum(subm(matrix_cast<long>(array_to_matrix(img)), rect))); DLIB_TEST(int_img.get_sum_of_area(rect) == sum(subm(matrix_cast<T>(array_to_matrix(img)), rect)));
rect = rectangle(p1,p1); rect = rectangle(p1,p1);
DLIB_TEST(int_img.get_sum_of_area(rect) == sum(subm(matrix_cast<long>(array_to_matrix(img)), rect))); DLIB_TEST(int_img.get_sum_of_area(rect) == sum(subm(matrix_cast<T>(array_to_matrix(img)), rect)));
} }
} }
...@@ -763,7 +764,10 @@ namespace ...@@ -763,7 +764,10 @@ namespace
) )
{ {
image_test(); image_test();
test_integral_image(); test_integral_image<long, unsigned char>();
test_integral_image<double, int>();
test_integral_image<long, unsigned char>();
test_integral_image<double, float>();
} }
} a; } a;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment