Commit 30963435 authored by Davis King's avatar Davis King

Made the spatial filtering functions always center their filters over the

output pixel exactly the same way as defined by centered_rect().
parent 4dd693e4
...@@ -658,8 +658,6 @@ namespace dlib ...@@ -658,8 +658,6 @@ namespace dlib
unsigned long width, height; unsigned long width, height;
compute_fhog_window_size(width,height); compute_fhog_window_size(width,height);
const point anchor((width+1)%2,
(height+1)%2);
array2d<float> saliency_image; array2d<float> saliency_image;
pyramid_type pyr; pyramid_type pyr;
...@@ -677,7 +675,7 @@ namespace dlib ...@@ -677,7 +675,7 @@ namespace dlib
// if we found a detection // if we found a detection
if (saliency_image[r][c] >= thresh) if (saliency_image[r][c] >= thresh)
{ {
rectangle rect = fhog_to_image(centered_rect(point(c,r)+anchor,width-2*padding,height-2*padding), cell_size, height,width); rectangle rect = fhog_to_image(centered_rect(point(c,r),width-2*padding,height-2*padding), cell_size, height,width);
rect = pyr.rect_up(rect, l); rect = pyr.rect_up(rect, l);
dets.push_back(std::make_pair(saliency_image[r][c], rect)); dets.push_back(std::make_pair(saliency_image[r][c], rect));
} }
......
...@@ -64,10 +64,10 @@ namespace dlib ...@@ -64,10 +64,10 @@ namespace dlib
// 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()-1)/2; const long first_row = filter.nr()/2;
const long first_col = (filter.nc()-1)/2; const long first_col = filter.nc()/2;
const long last_row = in_img.nr() - (filter.nr()/2); const long last_row = in_img.nr() - ((filter.nr()-1)/2);
const long last_col = in_img.nc() - (filter.nc()/2); const long last_col = in_img.nc() - ((filter.nc()-1)/2);
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) if (!add_to)
...@@ -153,10 +153,10 @@ namespace dlib ...@@ -153,10 +153,10 @@ namespace dlib
// 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()-1)/2; const long first_row = filter.nr()/2;
const long first_col = (filter.nc()-1)/2; const long first_col = filter.nc()/2;
const long last_row = in_img.nr() - (filter.nr()/2); const long last_row = in_img.nr() - ((filter.nr()-1)/2);
const long last_col = in_img.nc() - (filter.nc()/2); const long last_col = in_img.nc() - ((filter.nc()-1)/2);
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) if (!add_to)
...@@ -347,10 +347,10 @@ namespace dlib ...@@ -347,10 +347,10 @@ namespace dlib
// 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()-1)/2; const long first_row = filter.nr()/2;
const long first_col = (filter.nc()-1)/2; const long first_col = filter.nc()/2;
const long last_row = in_img.nr() - (filter.nr()/2); const long last_row = in_img.nr() - ((filter.nr()-1)/2);
const long last_col = in_img.nc() - (filter.nc()/2); const long last_col = in_img.nc() - ((filter.nc()-1)/2);
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); zero_border_pixels(out_img, non_border);
...@@ -458,10 +458,10 @@ namespace dlib ...@@ -458,10 +458,10 @@ namespace dlib
// 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()-1)/2; const long first_row = col_filter.size()/2;
const long first_col = (row_filter.size()-1)/2; const long first_col = row_filter.size()/2;
const long last_row = in_img.nr() - (col_filter.size()/2); const long last_row = in_img.nr() - ((col_filter.size()-1)/2);
const long last_col = in_img.nc() - (row_filter.size()/2); const long last_col = in_img.nc() - ((row_filter.size()-1)/2);
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) if (!add_to)
...@@ -593,10 +593,10 @@ namespace dlib ...@@ -593,10 +593,10 @@ namespace dlib
out_img.set_size(in_img.nr(),in_img.nc()); out_img.set_size(in_img.nr(),in_img.nc());
// 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()-1)/2; const long first_row = col_filter.size()/2;
const long first_col = (row_filter.size()-1)/2; const long first_col = row_filter.size()/2;
const long last_row = in_img.nr() - (col_filter.size()/2); const long last_row = in_img.nr() - ((col_filter.size()-1)/2);
const long last_col = in_img.nc() - (row_filter.size()/2); const long last_col = in_img.nc() - ((row_filter.size()-1)/2);
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) if (!add_to)
...@@ -814,10 +814,10 @@ namespace dlib ...@@ -814,10 +814,10 @@ namespace dlib
// 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()-1)/2; const long first_row = col_filter.size()/2;
const long first_col = (row_filter.size()-1)/2; const long first_col = row_filter.size()/2;
const long last_row = in_img.nr() - (col_filter.size()/2); const long last_row = in_img.nr() - ((col_filter.size()-1)/2);
const long last_col = in_img.nc() - (row_filter.size()/2); const long last_col = in_img.nc() - ((row_filter.size()-1)/2);
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); zero_border_pixels(out_img, non_border);
......
...@@ -53,7 +53,10 @@ namespace dlib ...@@ -53,7 +53,10 @@ namespace dlib
- 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's centered over the pixel it writes its - The filter is applied such that it's centered over the pixel it writes its
output into. For centering purposes, we consider the center element of the output into. For centering purposes, we consider the center element of the
filter to be filter((filter.nr()-1)/2,(filter.nc()-1)/2). filter to be filter(filter.nr()/2,filter.nc()/2). This means that the filter
that writes its output to a pixel at location point(c,r) and is W by H (width
by height) pixels in size operates on exactly the pixels in the rectangle
centered_rect(point(c,r),W,H) within in_img.
- 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()
...@@ -117,7 +120,10 @@ namespace dlib ...@@ -117,7 +120,10 @@ namespace dlib
- 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's centered over the pixel it writes its - The filter is applied such that it's centered over the pixel it writes its
output into. For centering purposes, we consider the center element of the 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). filter to be FILT(col_filter.size()/2,row_filter.size()/2). This means that
the filter that writes its output to a pixel at location point(c,r) and is W
by H (width by height) pixels in size operates on exactly the pixels in the
rectangle centered_rect(point(c,r),W,H) within in_img.
- 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()
......
...@@ -1091,47 +1091,6 @@ namespace ...@@ -1091,47 +1091,6 @@ namespace
} }
} }
void test_small_filter()
{
array2d<int> img(3,3), out;
assign_all_pixels(img, 1);
matrix<int> filt(2,2);
filt = 1;
spatially_filter_image(img, out, filt);
DLIB_TEST(out[0][0] == 4);
DLIB_TEST(out[0][1] == 4);
DLIB_TEST(out[0][2] == 0);
DLIB_TEST(out[1][0] == 4);
DLIB_TEST(out[1][1] == 4);
DLIB_TEST(out[1][2] == 0);
DLIB_TEST(out[2][0] == 0);
DLIB_TEST(out[2][1] == 0);
DLIB_TEST(out[2][2] == 0);
matrix<int> rfilt(2,1), cfilt(2,1);
rfilt = 1;
cfilt = 1;
assign_all_pixels(out, 9);
spatially_filter_image_separable(img, out, rfilt, cfilt);
DLIB_TEST(out[0][0] == 4);
DLIB_TEST(out[0][1] == 4);
DLIB_TEST(out[0][2] == 0);
DLIB_TEST(out[1][0] == 4);
DLIB_TEST(out[1][1] == 4);
DLIB_TEST(out[1][2] == 0);
DLIB_TEST(out[2][0] == 0);
DLIB_TEST(out[2][1] == 0);
DLIB_TEST(out[2][2] == 0);
}
void test_zero_border_pixels( void test_zero_border_pixels(
) )
...@@ -1614,6 +1573,104 @@ namespace ...@@ -1614,6 +1573,104 @@ namespace
DLIB_TEST(mat(img) == mat(img3)); DLIB_TEST(mat(img) == mat(img3));
} }
// ----------------------------------------------------------------------------------------
template <typename T>
void test_filtering_center (
dlib::rand& rnd
)
{
array2d<T> img(rnd.get_random_32bit_number()%100+1,
rnd.get_random_32bit_number()%100+1);
matrix<T> filt(rnd.get_random_32bit_number()%10+1,
rnd.get_random_32bit_number()%10+1);
for (long r = 0; r < img.nr(); ++r)
{
for (long c = 0; c < img.nc(); ++c)
{
img[r][c] = rnd.get_random_32bit_number()%100;
}
}
for (long r = 0; r < filt.nr(); ++r)
{
for (long c = 0; c < filt.nc(); ++c)
{
filt(r,c) = rnd.get_random_32bit_number()%100;
}
}
array2d<T> out;
const rectangle area = spatially_filter_image(img, out, filt);
for (long r = 0; r < out.nr(); ++r)
{
for (long c = 0; c < out.nc(); ++c)
{
const rectangle rect = centered_rect(point(c,r), filt.nc(), filt.nr());
if (get_rect(out).contains(rect))
{
T val = sum(pointwise_multiply(filt, subm(mat(img),rect)));
DLIB_CASSERT(val == out[r][c],"err: " << val-out[r][c]);
DLIB_CASSERT(area.contains(point(c,r)),"");
}
else
{
DLIB_CASSERT(!area.contains(point(c,r)),"");
}
}
}
}
template <typename T>
void test_separable_filtering_center (
dlib::rand& rnd
)
{
array2d<T> img(rnd.get_random_32bit_number()%100+1,
rnd.get_random_32bit_number()%100+1);
matrix<T,1,0> row_filt(rnd.get_random_32bit_number()%10+1);
matrix<T,0,1> col_filt(rnd.get_random_32bit_number()%10+1);
for (long r = 0; r < img.nr(); ++r)
{
for (long c = 0; c < img.nc(); ++c)
{
img[r][c] = rnd.get_random_32bit_number()%10;
}
}
for (long r = 0; r < row_filt.size(); ++r)
{
row_filt(r) = rnd.get_random_32bit_number()%10;
}
for (long r = 0; r < col_filt.size(); ++r)
{
col_filt(r) = rnd.get_random_32bit_number()%10;
}
array2d<T> out;
const rectangle area = spatially_filter_image_separable(img, out, row_filt, col_filt);
for (long r = 0; r < out.nr(); ++r)
{
for (long c = 0; c < out.nc(); ++c)
{
const rectangle rect = centered_rect(point(c,r), row_filt.size(), col_filt.size());
if (get_rect(out).contains(rect))
{
T val = sum(pointwise_multiply(col_filt*row_filt, subm(mat(img),rect)));
DLIB_CASSERT(val == out[r][c],"err: " << val-out[r][c]);
DLIB_CASSERT(area.contains(point(c,r)),"");
}
else
{
DLIB_CASSERT(!area.contains(point(c,r)),"");
}
}
}
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
class image_tester : public tester class image_tester : public tester
...@@ -1628,7 +1685,6 @@ namespace ...@@ -1628,7 +1685,6 @@ namespace
void perform_test ( void perform_test (
) )
{ {
test_small_filter();
image_test(); image_test();
test_integral_image<long, unsigned char>(); test_integral_image<long, unsigned char>();
test_integral_image<double, int>(); test_integral_image<double, int>();
...@@ -1669,15 +1725,22 @@ namespace ...@@ -1669,15 +1725,22 @@ namespace
dlib::rand rnd; dlib::rand rnd;
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
{ {
// the spatial filtering stuff is the same as xcorr_same when the filter
// sizes are odd.
test_filtering2(3,3,rnd); test_filtering2(3,3,rnd);
test_filtering2(3,4,rnd); test_filtering2(5,5,rnd);
test_filtering2(4,3,rnd);
test_filtering2(4,4,rnd);
test_filtering2(4,7,rnd);
test_filtering2(7,7,rnd); test_filtering2(7,7,rnd);
test_filtering2(7,5,rnd);
} }
for (int i = 0; i < 100; ++i)
test_filtering_center<float>(rnd);
for (int i = 0; i < 100; ++i)
test_filtering_center<int>(rnd);
for (int i = 0; i < 100; ++i)
test_separable_filtering_center<int>(rnd);
for (int i = 0; i < 100; ++i)
test_separable_filtering_center<float>(rnd);
} }
} 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