Commit a081d4de authored by Davis King's avatar Davis King

- Renamed spatially_filter_image() for the separable case to spatially_filter_image_separable()

 - Changed the behavior of spatially_filter_image().  Now it won't truncate signed pixel values
   to 0 if they go negative.
parent 4d8e96ef
...@@ -19,20 +19,21 @@ namespace dlib ...@@ -19,20 +19,21 @@ namespace dlib
template < template <
typename in_image_type, typename in_image_type,
typename out_image_type, typename out_image_type,
typename EXP typename EXP,
typename T
> >
void spatially_filter_image ( void spatially_filter_image (
const in_image_type& in_img, const in_image_type& in_img,
out_image_type& out_img, out_image_type& out_img,
const matrix_exp<EXP>& filter, const matrix_exp<EXP>& filter,
unsigned long scale = 1, T scale,
bool use_abs = false bool use_abs = false
) )
{ {
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::has_alpha == false ); COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::has_alpha == false ); COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::has_alpha == false );
DLIB_ASSERT(scale > 0 && DLIB_ASSERT(scale != 0 &&
filter.nr()%2 == 1 && filter.nr()%2 == 1 &&
filter.nc()%2 == 1, filter.nc()%2 == 1,
"\tvoid spatially_filter_image()" "\tvoid spatially_filter_image()"
...@@ -85,18 +86,10 @@ namespace dlib ...@@ -85,18 +86,10 @@ namespace dlib
temp /= scale; temp /= scale;
// Catch any underflow or apply abs as appropriate if (use_abs && temp < 0)
if (temp < 0)
{
if (use_abs)
{ {
temp = -temp; temp = -temp;
} }
else
{
temp = 0;
}
}
// save this pixel to the output image // save this pixel to the output image
assign_pixel(out_img[r][c], in_img[r][c]); assign_pixel(out_img[r][c], in_img[r][c]);
...@@ -105,32 +98,47 @@ namespace dlib ...@@ -105,32 +98,47 @@ namespace dlib
} }
} }
template <
typename in_image_type,
typename out_image_type,
typename EXP
>
void spatially_filter_image (
const in_image_type& in_img,
out_image_type& out_img,
const matrix_exp<EXP>& filter
)
{
spatially_filter_image(in_img,out_img,filter,1);
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < template <
typename in_image_type, typename in_image_type,
typename out_image_type, typename out_image_type,
typename EXP1, typename EXP1,
typename EXP2 typename EXP2,
typename T
> >
void spatially_filter_image ( void spatially_filter_image_separable (
const in_image_type& in_img, const in_image_type& in_img,
out_image_type& out_img, out_image_type& out_img,
const matrix_exp<EXP1>& row_filter, const matrix_exp<EXP1>& row_filter,
const matrix_exp<EXP2>& col_filter, const matrix_exp<EXP2>& col_filter,
unsigned long scale = 1, T scale,
bool use_abs = false bool use_abs = false
) )
{ {
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::has_alpha == false ); COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::has_alpha == false ); COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::has_alpha == false );
DLIB_ASSERT(scale > 0 && DLIB_ASSERT(scale != 0 &&
row_filter.size()%2 == 1 && row_filter.size()%2 == 1 &&
col_filter.size()%2 == 1 && col_filter.size()%2 == 1 &&
is_vector(row_filter) && is_vector(row_filter) &&
is_vector(col_filter), is_vector(col_filter),
"\tvoid spatially_filter_image()" "\tvoid spatially_filter_image_separable()"
<< "\n\t Invalid inputs were given to this function." << "\n\t Invalid inputs were given to this function."
<< "\n\t scale: "<< scale << "\n\t scale: "<< scale
<< "\n\t row_filter.size(): "<< row_filter.size() << "\n\t row_filter.size(): "<< row_filter.size()
...@@ -139,7 +147,7 @@ namespace dlib ...@@ -139,7 +147,7 @@ namespace dlib
<< "\n\t is_vector(col_filter): "<< is_vector(col_filter) << "\n\t is_vector(col_filter): "<< is_vector(col_filter)
); );
DLIB_ASSERT(is_same_object(in_img, out_img) == false, DLIB_ASSERT(is_same_object(in_img, out_img) == false,
"\tvoid spatially_filter_image()" "\tvoid spatially_filter_image_separable()"
<< "\n\tYou must give two different image objects" << "\n\tYou must give two different image objects"
); );
...@@ -199,18 +207,10 @@ namespace dlib ...@@ -199,18 +207,10 @@ namespace dlib
temp /= scale; temp /= scale;
// Catch any underflow or apply abs as appropriate if (use_abs && temp < 0)
if (temp < 0)
{
if (use_abs)
{ {
temp = -temp; temp = -temp;
} }
else
{
temp = 0;
}
}
// save this pixel to the output image // save this pixel to the output image
assign_pixel(out_img[r][c], in_img[r][c]); assign_pixel(out_img[r][c], in_img[r][c]);
...@@ -219,6 +219,22 @@ namespace dlib ...@@ -219,6 +219,22 @@ namespace dlib
} }
} }
template <
typename in_image_type,
typename out_image_type,
typename EXP1,
typename EXP2
>
void spatially_filter_image_separable (
const in_image_type& in_img,
out_image_type& out_img,
const matrix_exp<EXP1>& row_filter,
const matrix_exp<EXP2>& col_filter
)
{
spatially_filter_image_separable(in_img,out_img,row_filter,col_filter,1);
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < template <
......
...@@ -14,13 +14,14 @@ namespace dlib ...@@ -14,13 +14,14 @@ namespace dlib
template < template <
typename in_image_type, typename in_image_type,
typename out_image_type, typename out_image_type,
typename EXP typename EXP,
typename T
> >
void spatially_filter_image ( void spatially_filter_image (
const in_image_type& in_img, const in_image_type& in_img,
out_image_type& out_img, out_image_type& out_img,
const matrix_exp<EXP>& filter, const matrix_exp<EXP>& filter,
unsigned long scale = 1, T scale = 1,
bool use_abs = false bool use_abs = false
); );
/*! /*!
...@@ -30,21 +31,20 @@ namespace dlib ...@@ -30,21 +31,20 @@ namespace dlib
- pixel_traits<typename in_image_type::type>::has_alpha == false - pixel_traits<typename in_image_type::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false - pixel_traits<typename out_image_type::type>::has_alpha == false
- is_same_object(in_img, out_img) == false - is_same_object(in_img, out_img) == false
- scale > 0 - T must be some scalar type
- scale != 0
- filter.nr() % 2 == 1 (i.e. must be odd) - filter.nr() % 2 == 1 (i.e. must be odd)
- filter.nc() % 2 == 1 (i.e. must be odd) - filter.nc() % 2 == 1 (i.e. must be odd)
ensures ensures
- Applies the given spatial filter to in_img and stores the result in out_img. Also - Applies the given spatial filter to in_img and stores the result in out_img. Also
divides each resulting pixel by scale. divides each resulting pixel by scale.
- pixel values after filtering that are > pixel_traits<out_image_type>::max() are - Pixel values are stored into out_img using the assign_pixel() function and therefore
set to pixel_traits<out_image_type>::max() any applicable color space conversion or value saturation is performed.
- if (pixel_traits<typename in_image_type::type>::grayscale == false) then - if (pixel_traits<typename in_image_type::type>::grayscale == false) then
- the pixel values are converted to the HSI color space and the filtering - the pixel values are converted to the HSI color space and the filtering
is done on the intensity channel only. is done on the intensity channel only.
- if (use_abs == true) then - if (use_abs == true) then
- pixel values after filtering that are < 0 are converted to their absolute values - pixel values after filtering that are < 0 are converted to their absolute values.
- else
- pixel values after filtering that are < 0 are assigned the value of 0
- Pixels close enough to the edge of in_img to not have the filter still fit - Pixels close enough to the edge of in_img to not have the filter still fit
inside the image are set to zero. inside the image are set to zero.
- #out_img.nc() == in_img.nc() - #out_img.nc() == in_img.nc()
...@@ -57,14 +57,15 @@ namespace dlib ...@@ -57,14 +57,15 @@ namespace dlib
typename in_image_type, typename in_image_type,
typename out_image_type, typename out_image_type,
typename EXP1, typename EXP1,
typename EXP2 typename EXP2,
typename T
> >
void spatially_filter_image ( void spatially_filter_image_separable (
const in_image_type& in_img, const in_image_type& in_img,
out_image_type& out_img, out_image_type& out_img,
const matrix_exp<EXP1>& row_filter, const matrix_exp<EXP1>& row_filter,
const matrix_exp<EXP2>& col_filter, const matrix_exp<EXP2>& col_filter,
unsigned long scale = 1, T scale = 1,
bool use_abs = false bool use_abs = false
); );
/*! /*!
...@@ -74,7 +75,8 @@ namespace dlib ...@@ -74,7 +75,8 @@ namespace dlib
- pixel_traits<typename in_image_type::type>::has_alpha == false - pixel_traits<typename in_image_type::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false - pixel_traits<typename out_image_type::type>::has_alpha == false
- is_same_object(in_img, out_img) == false - is_same_object(in_img, out_img) == false
- scale > 0 - T must be some scalar type
- scale != 0
- is_vector(row_filter) == true - is_vector(row_filter) == true
- is_vector(col_filter) == true - is_vector(col_filter) == true
- row_filter.size() % 2 == 1 (i.e. must be odd) - row_filter.size() % 2 == 1 (i.e. must be odd)
...@@ -85,15 +87,13 @@ namespace dlib ...@@ -85,15 +87,13 @@ namespace dlib
effect as calling the regular spatially_filter_image() routine with a filter, effect as calling the regular spatially_filter_image() routine with a filter,
FILT, defined as follows: FILT, defined as follows:
- FILT(r,c) == col_filter(r)*row_filter(c) - FILT(r,c) == col_filter(r)*row_filter(c)
- pixel values after filtering that are > pixel_traits<out_image_type>::max() are - Pixel values are stored into out_img using the assign_pixel() function and therefore
set to pixel_traits<out_image_type>::max() any applicable color space conversion or value saturation is performed.
- if (pixel_traits<typename in_image_type::type>::grayscale == false) then - if (pixel_traits<typename in_image_type::type>::grayscale == false) then
- the pixel values are converted to the HSI color space and the filtering - the pixel values are converted to the HSI color space and the filtering
is done on the intensity channel only. is done on the intensity channel only.
- if (use_abs == true) then - if (use_abs == true) then
- pixel values after filtering that are < 0 are converted to their absolute values - pixel values after filtering that are < 0 are converted to their absolute values
- else
- pixel values after filtering that are < 0 are assigned the value of 0
- Pixels close enough to the edge of in_img to not have the filter still fit - Pixels close enough to the edge of in_img to not have the filter still fit
inside the image are set to zero. inside the image are set to zero.
- #out_img.nc() == in_img.nc() - #out_img.nc() == in_img.nc()
......
...@@ -808,7 +808,7 @@ namespace ...@@ -808,7 +808,7 @@ namespace
row_filter = 1,1,1,1,1; row_filter = 1,1,1,1,1;
col_filter = 1,1,1; col_filter = 1,1,1;
spatially_filter_image(img, img3, row_filter, col_filter); spatially_filter_image_separable(img, img3, row_filter, col_filter);
DLIB_TEST(array_to_matrix(img2) == array_to_matrix(img3)); DLIB_TEST(array_to_matrix(img2) == array_to_matrix(img3));
...@@ -840,9 +840,117 @@ namespace ...@@ -840,9 +840,117 @@ namespace
assign_all_pixels(img3,3); assign_all_pixels(img3,3);
// Just make sure both filtering methods give the same results. // Just make sure both filtering methods give the same results.
spatially_filter_image(img, img2, filter, scale, use_abs); spatially_filter_image(img, img2, filter, scale, use_abs);
spatially_filter_image(img, img3, row_filter, col_filter, scale, use_abs); spatially_filter_image_separable(img, img3, row_filter, col_filter, scale, use_abs);
DLIB_TEST(array_to_matrix(img2) == array_to_matrix(img3)); DLIB_TEST(array_to_matrix(img2) == array_to_matrix(img3));
} }
{
array2d<int> img, img2;
img.set_size(3,4);
matrix<int> filter(3,3);
filter = 1;
assign_all_pixels(img,-1);
spatially_filter_image(img,img2,filter);
DLIB_TEST(img2[0][0] == 0);
DLIB_TEST(img2[0][1] == 0);
DLIB_TEST(img2[0][2] == 0);
DLIB_TEST(img2[0][3] == 0);
DLIB_TEST(img2[1][0] == 0);
DLIB_TEST(img2[1][1] == -9);
DLIB_TEST(img2[1][2] == -9);
DLIB_TEST(img2[1][3] == 0);
DLIB_TEST(img2[2][0] == 0);
DLIB_TEST(img2[2][1] == 0);
DLIB_TEST(img2[2][2] == 0);
DLIB_TEST(img2[2][3] == 0);
assign_all_pixels(img,-1);
spatially_filter_image(img,img2,filter,2,true);
DLIB_TEST(img2[0][0] == 0);
DLIB_TEST(img2[0][1] == 0);
DLIB_TEST(img2[0][2] == 0);
DLIB_TEST(img2[0][3] == 0);
DLIB_TEST(img2[1][0] == 0);
DLIB_TEST(img2[1][1] == 4);
DLIB_TEST(img2[1][2] == 4);
DLIB_TEST(img2[1][3] == 0);
DLIB_TEST(img2[2][0] == 0);
DLIB_TEST(img2[2][1] == 0);
DLIB_TEST(img2[2][2] == 0);
DLIB_TEST(img2[2][3] == 0);
matrix<int> rowf(3,1), colf(3,1);
rowf = 1;
colf = 1;
assign_all_pixels(img,-1);
spatially_filter_image_separable(img,img2,rowf,colf);
DLIB_TEST(img2[0][0] == 0);
DLIB_TEST(img2[0][1] == 0);
DLIB_TEST(img2[0][2] == 0);
DLIB_TEST(img2[0][3] == 0);
DLIB_TEST(img2[1][0] == 0);
DLIB_TEST(img2[1][1] == -9);
DLIB_TEST(img2[1][2] == -9);
DLIB_TEST(img2[1][3] == 0);
DLIB_TEST(img2[2][0] == 0);
DLIB_TEST(img2[2][1] == 0);
DLIB_TEST(img2[2][2] == 0);
DLIB_TEST(img2[2][3] == 0);
spatially_filter_image_separable(img,img2,rowf,colf,1,true);
DLIB_TEST(img2[0][0] == 0);
DLIB_TEST(img2[0][1] == 0);
DLIB_TEST(img2[0][2] == 0);
DLIB_TEST(img2[0][3] == 0);
DLIB_TEST(img2[1][0] == 0);
DLIB_TEST(img2[1][1] == 9);
DLIB_TEST(img2[1][2] == 9);
DLIB_TEST(img2[1][3] == 0);
DLIB_TEST(img2[2][0] == 0);
DLIB_TEST(img2[2][1] == 0);
DLIB_TEST(img2[2][2] == 0);
DLIB_TEST(img2[2][3] == 0);
}
{
array2d<double> img, img2;
img.set_size(3,4);
matrix<double> filter(3,3);
filter = 1;
assign_all_pixels(img,-1);
spatially_filter_image(img,img2,filter,2);
DLIB_TEST(img2[0][0] == 0);
DLIB_TEST(img2[0][1] == 0);
DLIB_TEST(img2[0][2] == 0);
DLIB_TEST(img2[0][3] == 0);
DLIB_TEST(img2[1][0] == 0);
DLIB_TEST((img2[1][1] - -4.5) < 1e-14);
DLIB_TEST((img2[1][2] - -4.5) < 1e-14);
DLIB_TEST(img2[1][3] == 0);
DLIB_TEST(img2[2][0] == 0);
DLIB_TEST(img2[2][1] == 0);
DLIB_TEST(img2[2][2] == 0);
DLIB_TEST(img2[2][3] == 0);
}
} }
void test_zero_border_pixels( void test_zero_border_pixels(
......
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