mirror of
https://github.com/davisking/dlib.git
synced 2024-11-01 10:14:53 +08:00
Made the spatial filtering functions filter each color channel independently
rather than converting to HSI and filtering just the I channel. Also, the spatially_filter_image_separable_down() routine now only allows grayscale output images.
This commit is contained in:
parent
088ab2e1a0
commit
af34478be3
@ -23,7 +23,8 @@ namespace dlib
|
||||
typename EXP,
|
||||
typename T
|
||||
>
|
||||
rectangle spatially_filter_image (
|
||||
typename enable_if_c<pixel_traits<typename out_image_type::type>::grayscale,rectangle>::type
|
||||
spatially_filter_image (
|
||||
const in_image_type& in_img,
|
||||
out_image_type& out_img,
|
||||
const matrix_exp<EXP>& filter,
|
||||
@ -98,12 +99,11 @@ namespace dlib
|
||||
// save this pixel to the output image
|
||||
if (add_to == false)
|
||||
{
|
||||
assign_pixel(out_img[r][c], in_img[r][c]);
|
||||
assign_pixel_intensity(out_img[r][c], temp);
|
||||
assign_pixel(out_img[r][c], temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
assign_pixel(out_img[r][c], temp + get_pixel_intensity(out_img[r][c]));
|
||||
assign_pixel(out_img[r][c], temp + out_img[r][c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -111,6 +111,92 @@ namespace dlib
|
||||
return non_border;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename in_image_type,
|
||||
typename out_image_type,
|
||||
typename EXP,
|
||||
typename T
|
||||
>
|
||||
typename disable_if_c<pixel_traits<typename out_image_type::type>::grayscale,rectangle>::type
|
||||
spatially_filter_image (
|
||||
const in_image_type& in_img,
|
||||
out_image_type& out_img,
|
||||
const matrix_exp<EXP>& filter,
|
||||
T scale,
|
||||
bool use_abs = false,
|
||||
bool add_to = 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 );
|
||||
|
||||
DLIB_ASSERT(scale != 0 &&
|
||||
filter.nr()%2 == 1 &&
|
||||
filter.nc()%2 == 1,
|
||||
"\tvoid spatially_filter_image()"
|
||||
<< "\n\t You can't give a scale of zero or a filter with even dimensions"
|
||||
<< "\n\t scale: "<< scale
|
||||
<< "\n\t filter.nr(): "<< filter.nr()
|
||||
<< "\n\t filter.nc(): "<< filter.nc()
|
||||
);
|
||||
DLIB_ASSERT(is_same_object(in_img, out_img) == false,
|
||||
"\tvoid spatially_filter_image()"
|
||||
<< "\n\tYou must give two different image objects"
|
||||
);
|
||||
|
||||
|
||||
|
||||
// if there isn't any input image then don't do anything
|
||||
if (in_img.size() == 0)
|
||||
{
|
||||
out_img.clear();
|
||||
return rectangle();
|
||||
}
|
||||
|
||||
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
|
||||
const long first_row = filter.nr()/2;
|
||||
const long first_col = filter.nc()/2;
|
||||
const long last_row = in_img.nr() - filter.nr()/2;
|
||||
const long last_col = in_img.nc() - filter.nc()/2;
|
||||
|
||||
const rectangle non_border = rectangle(first_col, first_row, last_col-1, last_row-1);
|
||||
|
||||
// apply the filter to the image
|
||||
for (long r = first_row; r < last_row; ++r)
|
||||
{
|
||||
for (long c = first_col; c < last_col; ++c)
|
||||
{
|
||||
typedef matrix<typename EXP::type,pixel_traits<typename in_image_type::type>::num,1> ptype;
|
||||
ptype p;
|
||||
ptype temp;
|
||||
temp = 0;
|
||||
for (long m = 0; m < filter.nr(); ++m)
|
||||
{
|
||||
for (long n = 0; n < filter.nc(); ++n)
|
||||
{
|
||||
// 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]);
|
||||
temp += p*filter(m,n);
|
||||
}
|
||||
}
|
||||
|
||||
temp /= scale;
|
||||
|
||||
typename in_image_type::type pp;
|
||||
vector_to_pixel(pp, temp);
|
||||
assign_pixel(out_img[r][c], pp);
|
||||
}
|
||||
}
|
||||
|
||||
return non_border;
|
||||
}
|
||||
|
||||
template <
|
||||
typename in_image_type,
|
||||
typename out_image_type,
|
||||
@ -134,7 +220,8 @@ namespace dlib
|
||||
typename EXP2,
|
||||
typename T
|
||||
>
|
||||
rectangle spatially_filter_image_separable (
|
||||
typename enable_if_c<pixel_traits<typename out_image_type::type>::grayscale,rectangle>::type
|
||||
spatially_filter_image_separable (
|
||||
const in_image_type& in_img,
|
||||
out_image_type& out_img,
|
||||
const matrix_exp<EXP1>& row_filter,
|
||||
@ -230,18 +317,125 @@ namespace dlib
|
||||
// save this pixel to the output image
|
||||
if (add_to == false)
|
||||
{
|
||||
assign_pixel(out_img[r][c], in_img[r][c]);
|
||||
assign_pixel_intensity(out_img[r][c], temp);
|
||||
assign_pixel(out_img[r][c], temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
assign_pixel(out_img[r][c], temp + get_pixel_intensity(out_img[r][c]));
|
||||
assign_pixel(out_img[r][c], temp + out_img[r][c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return non_border;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename in_image_type,
|
||||
typename out_image_type,
|
||||
typename EXP1,
|
||||
typename EXP2,
|
||||
typename T
|
||||
>
|
||||
typename disable_if_c<pixel_traits<typename out_image_type::type>::grayscale,rectangle>::type
|
||||
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,
|
||||
T scale
|
||||
)
|
||||
{
|
||||
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 );
|
||||
|
||||
DLIB_ASSERT(scale != 0 &&
|
||||
row_filter.size()%2 == 1 &&
|
||||
col_filter.size()%2 == 1 &&
|
||||
is_vector(row_filter) &&
|
||||
is_vector(col_filter),
|
||||
"\tvoid spatially_filter_image_separable()"
|
||||
<< "\n\t Invalid inputs were given to this function."
|
||||
<< "\n\t scale: "<< scale
|
||||
<< "\n\t row_filter.size(): "<< row_filter.size()
|
||||
<< "\n\t col_filter.size(): "<< col_filter.size()
|
||||
<< "\n\t is_vector(row_filter): "<< is_vector(row_filter)
|
||||
<< "\n\t is_vector(col_filter): "<< is_vector(col_filter)
|
||||
);
|
||||
DLIB_ASSERT(is_same_object(in_img, out_img) == false,
|
||||
"\tvoid spatially_filter_image_separable()"
|
||||
<< "\n\tYou must give two different image objects"
|
||||
);
|
||||
|
||||
|
||||
|
||||
// if there isn't any input image then don't do anything
|
||||
if (in_img.size() == 0)
|
||||
{
|
||||
out_img.clear();
|
||||
return rectangle();
|
||||
}
|
||||
|
||||
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
|
||||
const long first_row = col_filter.size()/2;
|
||||
const long first_col = row_filter.size()/2;
|
||||
const long last_row = in_img.nr() - col_filter.size()/2;
|
||||
const long last_col = in_img.nc() - row_filter.size()/2;
|
||||
|
||||
const rectangle non_border = rectangle(first_col, first_row, last_col-1, last_row-1);
|
||||
|
||||
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;
|
||||
|
||||
array2d<ptype,mem_manager_type> temp_img;
|
||||
temp_img.set_size(in_img.nr(), in_img.nc());
|
||||
|
||||
// apply the row filter
|
||||
for (long r = 0; r < in_img.nr(); ++r)
|
||||
{
|
||||
for (long c = first_col; c < last_col; ++c)
|
||||
{
|
||||
ptype p;
|
||||
ptype temp;
|
||||
temp = 0;
|
||||
for (long n = 0; n < row_filter.size(); ++n)
|
||||
{
|
||||
// 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]);
|
||||
temp += p*row_filter(n);
|
||||
}
|
||||
temp_img[r][c] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
// apply the column filter
|
||||
for (long r = first_row; r < last_row; ++r)
|
||||
{
|
||||
for (long c = first_col; c < last_col; ++c)
|
||||
{
|
||||
ptype temp;
|
||||
temp = 0;
|
||||
for (long m = 0; m < col_filter.size(); ++m)
|
||||
{
|
||||
temp += temp_img[r-col_filter.size()/2+m][c]*col_filter(m);
|
||||
}
|
||||
|
||||
temp /= scale;
|
||||
|
||||
|
||||
// save this pixel to the output image
|
||||
typename in_image_type::type p;
|
||||
vector_to_pixel(p, temp);
|
||||
assign_pixel(out_img[r][c], p);
|
||||
}
|
||||
}
|
||||
return non_border;
|
||||
}
|
||||
|
||||
template <
|
||||
typename in_image_type,
|
||||
typename out_image_type,
|
||||
@ -280,6 +474,7 @@ namespace dlib
|
||||
{
|
||||
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>::grayscale == true );
|
||||
|
||||
DLIB_ASSERT(downsample > 0 &&
|
||||
scale != 0 &&
|
||||
@ -374,12 +569,11 @@ namespace dlib
|
||||
// save this pixel to the output image
|
||||
if (add_to == false)
|
||||
{
|
||||
assign_pixel(out_img[r][c], in_img[r*downsample][c*downsample]);
|
||||
assign_pixel_intensity(out_img[r][c], temp);
|
||||
assign_pixel(out_img[r][c], temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
assign_pixel(out_img[r][c], temp + get_pixel_intensity(out_img[r][c]));
|
||||
assign_pixel(out_img[r][c], temp + out_img[r][c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,8 +46,7 @@ namespace dlib
|
||||
add_to is true then the filtered output value will be added to out_img rather than
|
||||
overwriting the original value.
|
||||
- if (pixel_traits<typename in_image_type::type>::grayscale == false) then
|
||||
- the pixel values are converted to the HSI color space and the filtering
|
||||
is done on the intensity channel only.
|
||||
- The filter is applied to each color channel independently.
|
||||
- if (use_abs == true) then
|
||||
- pixel values after filtering that are < 0 are converted to their absolute values.
|
||||
- Pixels close enough to the edge of in_img to not have the filter still fit
|
||||
@ -102,8 +101,7 @@ namespace dlib
|
||||
add_to is true then the filtered output value will be added to out_img rather than
|
||||
overwriting the original value.
|
||||
- if (pixel_traits<typename in_image_type::type>::grayscale == false) then
|
||||
- the pixel values are converted to the HSI color space and the filtering
|
||||
is done on the intensity channel only.
|
||||
- The filter is applied to each color channel independently.
|
||||
- if (use_abs == true) then
|
||||
- pixel values after filtering that are < 0 are converted to their absolute values
|
||||
- Pixels close enough to the edge of in_img to not have the filter still fit
|
||||
@ -139,6 +137,7 @@ namespace dlib
|
||||
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
|
||||
- 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>::grayscale == true
|
||||
- is_same_object(in_img, out_img) == false
|
||||
- T must be some scalar type
|
||||
- scale != 0
|
||||
@ -304,8 +303,7 @@ namespace dlib
|
||||
- Pixel values are stored into out_img using the assign_pixel() function and therefore
|
||||
any applicable color space conversion or value saturation is performed.
|
||||
- if (pixel_traits<typename in_image_type::type>::grayscale == false) then
|
||||
- the pixel values are converted to the HSI color space and the filtering
|
||||
is done on the intensity channel only.
|
||||
- The filter is applied to each color channel independently.
|
||||
- Pixels close enough to the edge of in_img to not have the filter still fit
|
||||
inside the image are set to zero.
|
||||
- #out_img.nc() == in_img.nc()
|
||||
|
Loading…
Reference in New Issue
Block a user