Commit 67ce66c1 authored by Davis King's avatar Davis King

Upgraded spatial filtering routines to work with even sized filters.

parent 9ab1f7cc
...@@ -36,11 +36,9 @@ namespace dlib ...@@ -36,11 +36,9 @@ namespace dlib
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.size() != 0,
filter.nr()%2 == 1 &&
filter.nc()%2 == 1,
"\tvoid spatially_filter_image()" "\tvoid spatially_filter_image()"
<< "\n\t You can't give a scale of zero or a filter with even dimensions" << "\n\t You can't give a scale of zero or an empty filter."
<< "\n\t scale: "<< scale << "\n\t scale: "<< scale
<< "\n\t filter.nr(): "<< filter.nr() << "\n\t filter.nr(): "<< filter.nr()
<< "\n\t filter.nc(): "<< filter.nc() << "\n\t filter.nc(): "<< filter.nc()
...@@ -61,15 +59,16 @@ namespace dlib ...@@ -61,15 +59,16 @@ namespace dlib
out_img.set_size(in_img.nr(),in_img.nc()); out_img.set_size(in_img.nr(),in_img.nc());
zero_border_pixels(out_img, filter.nc()/2, filter.nr()/2);
// figure out the range that we should apply the filter to // figure out the range that we should apply the filter to
const long first_row = filter.nr()/2; const long first_row = (filter.nr()-1)/2;
const long first_col = filter.nc()/2; const long first_col = (filter.nc()-1)/2;
const long last_row = in_img.nr() - filter.nr()/2; const long last_row = in_img.nr() - (filter.nr()-first_row);
const long last_col = in_img.nc() - filter.nc()/2; const long last_col = in_img.nc() - (filter.nc()-first_col);
const rectangle non_border = rectangle(first_col, first_row, last_col-1, last_row-1); const rectangle non_border = rectangle(first_col, first_row, last_col-1, last_row-1);
if (!add_to)
zero_border_pixels(out_img, non_border);
// apply the filter to the image // apply the filter to the image
for (long r = first_row; r < last_row; ++r) for (long r = first_row; r < last_row; ++r)
...@@ -84,7 +83,7 @@ namespace dlib ...@@ -84,7 +83,7 @@ namespace dlib
for (long n = 0; n < filter.nc(); ++n) for (long n = 0; n < filter.nc(); ++n)
{ {
// pull out the current pixel and put it into p // pull out the current pixel and put it into p
p = get_pixel_intensity(in_img[r-filter.nr()/2+m][c-filter.nc()/2+n]); p = get_pixel_intensity(in_img[r-first_row+m][c-first_col+n]);
temp += p*filter(m,n); temp += p*filter(m,n);
} }
} }
...@@ -130,11 +129,9 @@ namespace dlib ...@@ -130,11 +129,9 @@ namespace dlib
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.size() != 0,
filter.nr()%2 == 1 &&
filter.nc()%2 == 1,
"\tvoid spatially_filter_image()" "\tvoid spatially_filter_image()"
<< "\n\t You can't give a scale of zero or a filter with even dimensions" << "\n\t You can't give a scale of zero or an empty filter."
<< "\n\t scale: "<< scale << "\n\t scale: "<< scale
<< "\n\t filter.nr(): "<< filter.nr() << "\n\t filter.nr(): "<< filter.nr()
<< "\n\t filter.nc(): "<< filter.nc() << "\n\t filter.nc(): "<< filter.nc()
...@@ -155,15 +152,15 @@ namespace dlib ...@@ -155,15 +152,15 @@ namespace dlib
out_img.set_size(in_img.nr(),in_img.nc()); out_img.set_size(in_img.nr(),in_img.nc());
zero_border_pixels(out_img, filter.nc()/2, filter.nr()/2);
// figure out the range that we should apply the filter to // figure out the range that we should apply the filter to
const long first_row = filter.nr()/2; const long first_row = (filter.nr()-1)/2;
const long first_col = filter.nc()/2; const long first_col = (filter.nc()-1)/2;
const long last_row = in_img.nr() - filter.nr()/2; const long last_row = in_img.nr() - (filter.nr()-first_row);
const long last_col = in_img.nc() - filter.nc()/2; const long last_col = in_img.nc() - (filter.nc()-first_col);
const rectangle non_border = rectangle(first_col, first_row, last_col-1, last_row-1); const rectangle non_border = rectangle(first_col, first_row, last_col-1, last_row-1);
zero_border_pixels(out_img, non_border);
// apply the filter to the image // apply the filter to the image
for (long r = first_row; r < last_row; ++r) for (long r = first_row; r < last_row; ++r)
...@@ -179,7 +176,7 @@ namespace dlib ...@@ -179,7 +176,7 @@ namespace dlib
for (long n = 0; n < filter.nc(); ++n) for (long n = 0; n < filter.nc(); ++n)
{ {
// pull out the current pixel and put it into p // pull out the current pixel and put it into p
p = pixel_to_vector<typename EXP::type>(in_img[r-filter.nr()/2+m][c-filter.nc()/2+n]); p = pixel_to_vector<typename EXP::type>(in_img[r-first_row+m][c-first_col+n]);
temp += p*filter(m,n); temp += p*filter(m,n);
} }
} }
...@@ -232,9 +229,7 @@ namespace dlib ...@@ -232,9 +229,7 @@ namespace dlib
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() != 0 && col_filter.size() != 0 &&
row_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_separable()" "\tvoid spatially_filter_image_separable()"
...@@ -261,15 +256,16 @@ namespace dlib ...@@ -261,15 +256,16 @@ namespace dlib
out_img.set_size(in_img.nr(),in_img.nc()); out_img.set_size(in_img.nr(),in_img.nc());
zero_border_pixels(out_img, row_filter.size()/2, col_filter.size()/2);
// figure out the range that we should apply the filter to // figure out the range that we should apply the filter to
const long first_row = col_filter.size()/2; const long first_row = (col_filter.size()-1)/2;
const long first_col = row_filter.size()/2; const long first_col = (row_filter.size()-1)/2;
const long last_row = in_img.nr() - col_filter.size()/2; const long last_row = in_img.nr() - (col_filter.size()-first_row);
const long last_col = in_img.nc() - row_filter.size()/2; const long last_col = in_img.nc() - (row_filter.size()-first_col);
const rectangle non_border = rectangle(first_col, first_row, last_col-1, last_row-1); const rectangle non_border = rectangle(first_col, first_row, last_col-1, last_row-1);
if (!add_to)
zero_border_pixels(out_img, non_border);
typedef typename out_image_type::mem_manager_type mem_manager_type; typedef typename out_image_type::mem_manager_type mem_manager_type;
typedef typename EXP1::type ptype; typedef typename EXP1::type ptype;
...@@ -287,7 +283,7 @@ namespace dlib ...@@ -287,7 +283,7 @@ namespace dlib
for (long n = 0; n < row_filter.size(); ++n) for (long n = 0; n < row_filter.size(); ++n)
{ {
// pull out the current pixel and put it into p // pull out the current pixel and put it into p
p = get_pixel_intensity(in_img[r][c-row_filter.size()/2+n]); p = get_pixel_intensity(in_img[r][c-first_col+n]);
temp += p*row_filter(n); temp += p*row_filter(n);
} }
temp_img[r][c] = temp; temp_img[r][c] = temp;
...@@ -302,7 +298,7 @@ namespace dlib ...@@ -302,7 +298,7 @@ namespace dlib
ptype temp = 0; ptype temp = 0;
for (long m = 0; m < col_filter.size(); ++m) for (long m = 0; m < col_filter.size(); ++m)
{ {
temp += temp_img[r-col_filter.size()/2+m][c]*col_filter(m); temp += temp_img[r-first_row+m][c]*col_filter(m);
} }
temp /= scale; temp /= scale;
...@@ -347,9 +343,7 @@ namespace dlib ...@@ -347,9 +343,7 @@ namespace dlib
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() != 0 && col_filter.size() != 0 &&
row_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_separable()" "\tvoid spatially_filter_image_separable()"
...@@ -376,15 +370,15 @@ namespace dlib ...@@ -376,15 +370,15 @@ namespace dlib
out_img.set_size(in_img.nr(),in_img.nc()); out_img.set_size(in_img.nr(),in_img.nc());
zero_border_pixels(out_img, row_filter.size()/2, col_filter.size()/2);
// figure out the range that we should apply the filter to // figure out the range that we should apply the filter to
const long first_row = col_filter.size()/2; const long first_row = (col_filter.size()-1)/2;
const long first_col = row_filter.size()/2; const long first_col = (row_filter.size()-1)/2;
const long last_row = in_img.nr() - col_filter.size()/2; const long last_row = in_img.nr() - (col_filter.size()-first_row);
const long last_col = in_img.nc() - row_filter.size()/2; const long last_col = in_img.nc() - (row_filter.size()-first_col);
const rectangle non_border = rectangle(first_col, first_row, last_col-1, last_row-1); const rectangle non_border = rectangle(first_col, first_row, last_col-1, last_row-1);
zero_border_pixels(out_img, non_border);
typedef typename out_image_type::mem_manager_type mem_manager_type; typedef typename out_image_type::mem_manager_type mem_manager_type;
typedef matrix<typename EXP1::type,pixel_traits<typename in_image_type::type>::num,1> ptype; typedef matrix<typename EXP1::type,pixel_traits<typename in_image_type::type>::num,1> ptype;
...@@ -403,7 +397,7 @@ namespace dlib ...@@ -403,7 +397,7 @@ namespace dlib
for (long n = 0; n < row_filter.size(); ++n) for (long n = 0; n < row_filter.size(); ++n)
{ {
// pull out the current pixel and put it into p // pull out the current pixel and put it into p
p = pixel_to_vector<typename EXP1::type>(in_img[r][c-row_filter.size()/2+n]); p = pixel_to_vector<typename EXP1::type>(in_img[r][c-first_col+n]);
temp += p*row_filter(n); temp += p*row_filter(n);
} }
temp_img[r][c] = temp; temp_img[r][c] = temp;
...@@ -419,7 +413,7 @@ namespace dlib ...@@ -419,7 +413,7 @@ namespace dlib
temp = 0; temp = 0;
for (long m = 0; m < col_filter.size(); ++m) for (long m = 0; m < col_filter.size(); ++m)
{ {
temp += temp_img[r-col_filter.size()/2+m][c]*col_filter(m); temp += temp_img[r-first_row+m][c]*col_filter(m);
} }
temp /= scale; temp /= scale;
...@@ -517,11 +511,7 @@ namespace dlib ...@@ -517,11 +511,7 @@ namespace dlib
// zero border pixels // zero border pixels
const rectangle non_border = rectangle(first_col, first_row, last_col, last_row); const rectangle non_border = rectangle(first_col, first_row, last_col, last_row);
border_enumerator be(get_rect(out_img), non_border ); zero_border_pixels(out_img,non_border);
while (be.move_next())
{
out_img[be.element().y()][be.element().x()] = 0;
}
typedef typename EXP1::type ptype; typedef typename EXP1::type ptype;
......
...@@ -33,9 +33,8 @@ namespace dlib ...@@ -33,9 +33,8 @@ namespace dlib
- 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
- T must be some scalar type - T must be some scalar type
- filter.size() != 0
- scale != 0 - scale != 0
- filter.nr() % 2 == 1 (i.e. must be odd)
- filter.nc() % 2 == 1 (i.e. must be odd)
- if (pixel_traits<typename in_image_type::type>::grayscale == false) then - if (pixel_traits<typename in_image_type::type>::grayscale == false) then
- use_abs == false && add_to == false - use_abs == false && add_to == false
(i.e. You can only use the use_abs and add_to options with grayscale images) (i.e. You can only use the use_abs and add_to options with grayscale images)
...@@ -52,6 +51,9 @@ namespace dlib ...@@ -52,6 +51,9 @@ namespace dlib
- The filter is applied to each color channel independently. - The filter is applied to each color channel independently.
- 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.
- The filter is applied such that it is centered over the pixel it writes its
output into. For centering purposes, we consider the center element of the
filter to be filter((filter.nr()-1)/2,(filter.nc-1)/2).
- 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 always set to zero. inside the image are always set to zero.
- #out_img.nc() == in_img.nc() - #out_img.nc() == in_img.nc()
...@@ -87,10 +89,10 @@ namespace dlib ...@@ -87,10 +89,10 @@ namespace dlib
- is_same_object(in_img, out_img) == false - is_same_object(in_img, out_img) == false
- T must be some scalar type - T must be some scalar type
- scale != 0 - scale != 0
- row_filter.size() != 0
- col_filter.size() != 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)
- col_filter.size() % 2 == 1 (i.e. must be odd)
- if (pixel_traits<typename in_image_type::type>::grayscale == false) then - if (pixel_traits<typename in_image_type::type>::grayscale == false) then
- use_abs == false && add_to == false - use_abs == false && add_to == false
(i.e. You can only use the use_abs and add_to options with grayscale images) (i.e. You can only use the use_abs and add_to options with grayscale images)
...@@ -110,6 +112,9 @@ namespace dlib ...@@ -110,6 +112,9 @@ namespace dlib
- The filter is applied to each color channel independently. - The filter is applied to each color channel independently.
- 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
- The filter is applied such that it is centered over the pixel it writes its
output into. For centering purposes, we consider the center element of the
filter to be FILT((col_filter.size()-1)/2,(row_filter.size()-1)/2).
- 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 always set to zero. inside the image are always set to zero.
- #out_img.nc() == in_img.nc() - #out_img.nc() == in_img.nc()
......
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