// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_SPATIAL_FILTERINg_ABSTRACT_
#ifdef DLIB_SPATIAL_FILTERINg_ABSTRACT_
#include "../pixel.h"
#include "../matrix.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename in_image_type,
typename out_image_type,
typename EXP,
typename T
>
rectangle spatially_filter_image (
const in_image_type& in_img,
out_image_type& out_img,
const matrix_exp<EXP>& filter,
T scale = 1,
bool use_abs = false,
bool add_to = false
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- 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
- is_same_object(in_img, out_img) == false
- T must be some scalar type
- scale != 0
- filter.nr() % 2 == 1 (i.e. must be odd)
- filter.nc() % 2 == 1 (i.e. must be odd)
ensures
- Applies the given spatial filter to in_img and stores the result in out_img (i.e.
cross-correlates in_img with filter). Also divides each resulting pixel by scale.
- The intermediate filter computations will be carried out using variables of type EXP::type.
This is whatever scalar type is used inside the filter matrix.
- Pixel values are stored into out_img using the assign_pixel() function and therefore
any applicable color space conversion or value saturation is performed. Note that if
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.
- 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
inside the image are always set to zero.
- #out_img.nc() == in_img.nc()
- #out_img.nr() == in_img.nr()
- returns a rectangle which indicates what pixels in #out_img are considered
non-border pixels and therefore contain output from the filter.
!*/
// ----------------------------------------------------------------------------------------
template <
typename in_image_type,
typename out_image_type,
typename EXP1,
typename EXP2,
typename T
>
rectangle 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 = 1,
bool use_abs = false,
bool add_to = false
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- 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
- is_same_object(in_img, out_img) == false
- T must be some scalar type
- scale != 0
- is_vector(row_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)
ensures
- Applies the given separable spatial filter to in_img and stores the result in out_img.
Also divides each resulting pixel by scale. Calling this function has the same
effect as calling the regular spatially_filter_image() routine with a filter,
FILT, defined as follows:
- FILT(r,c) == col_filter(r)*row_filter(c)
- The intermediate filter computations will be carried out using variables of type EXP1::type.
This is whatever scalar type is used inside the row_filter matrix.
- Pixel values are stored into out_img using the assign_pixel() function and therefore
any applicable color space conversion or value saturation is performed. Note that if
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.
- 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
inside the image are always set to zero.
- #out_img.nc() == in_img.nc()
- #out_img.nr() == in_img.nr()
- returns a rectangle which indicates what pixels in #out_img are considered
non-border pixels and therefore contain output from the filter.
!*/
// ----------------------------------------------------------------------------------------
template <
typename in_image_type,
typename out_image_type,
typename EXP1,
typename EXP2,
typename T
>
rectangle spatially_filter_image_separable_down (
const unsigned long downsample,
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 = 1,
bool use_abs = false,
bool add_to = false
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- 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
- is_same_object(in_img, out_img) == false
- T must be some scalar type
- scale != 0
- is_vector(row_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)
- downsample > 0
ensures
- This function is equivalent to calling
spatially_filter_image_separable(in_img,out_img,row_filter,col_filter,scale,use_abs,add_to)
and then downsampling the output image by a factor of downsample. Therefore,
we will have that:
- #out_img.nr() == ceil((double)in_img.nr()/downsample)
- #out_img.nc() == ceil((double)in_img.nc()/downsample)
- #out_img[r][c] == filtered pixel corresponding to in_img[r*downsample][c*downsample]
- returns a rectangle which indicates what pixels in #out_img are considered
non-border pixels and therefore contain output from the filter.
- Note that the first row and column of non-zero padded data are the following
- first_row == ceil(floor(col_filter.size()/2.0)/downsample)
- first_col == ceil(floor(row_filter.size()/2.0)/downsample)
!*/
// ----------------------------------------------------------------------------------------
template <
long NR,
long NC,
typename T,
typename U,
typename in_image_type
>
inline void separable_3x3_filter_block_grayscale (
T (&block)[NR][NC],
const in_image_type& img,
const long& r,
const long& c,
const U& fe1,
const U& fm,
const U& fe2
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type> must be defined
- T and U should be scalar types
- shrink_rect(get_rect(img),1).contains(c,r)
- shrink_rect(get_rect(img),1).contains(c+NC-1,r+NR-1)
ensures
- Filters the image in the sub-window of img defined by a rectangle
with its upper left corner at (c,r) and lower right at (c+NC-1,r+NR-1).
- The output of the filter is stored in #block. Note that img will be
interpreted as a grayscale image.
- The filter used is defined by the separable filter [fe1 fm fe2]. So the
spatial filter is thus:
fe1*fe1 fe1*fm fe2*fe1
fe1*fm fm*fm fe2*fm
fe1*fe2 fe2*fm fe2*fe2
!*/
// ----------------------------------------------------------------------------------------
template <
long NR,
long NC,
typename T,
typename U,
typename in_image_type
>
inline void separable_3x3_filter_block_rgb (
T (&block)[NR][NC],
const in_image_type& img,
const long& r,
const long& c,
const U& fe1,
const U& fm,
const U& fe2
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type>::rgb == true
- T should be a struct with .red .green and .blue members.
- U should be a scalar type
- shrink_rect(get_rect(img),1).contains(c,r)
- shrink_rect(get_rect(img),1).contains(c+NC-1,r+NR-1)
ensures
- Filters the image in the sub-window of img defined by a rectangle
with its upper left corner at (c,r) and lower right at (c+NC-1,r+NR-1).
- The output of the filter is stored in #block. Note that the filter is applied
to each color component independently.
- The filter used is defined by the separable filter [fe1 fm fe2]. So the
spatial filter is thus:
fe1*fe1 fe1*fm fe2*fe1
fe1*fm fm*fm fe2*fm
fe1*fe2 fe2*fm fe2*fe2
!*/
// ----------------------------------------------------------------------------------------
inline double gaussian (
double x,
double sigma
);
/*!
requires
- sigma > 0
ensures
- computes and returns the value of a 1D Gaussian function with mean 0
and standard deviation sigma at the given x value.
!*/
// ----------------------------------------------------------------------------------------
template <
typename T
>
matrix<T,0,1> create_gaussian_filter (
double sigma,
int size
);
/*!
requires
- sigma > 0
- size > 0
- size is an odd number
ensures
- returns a separable Gaussian filter F such that:
- is_vector(F) == true
- F.size() == size
- F is suitable for use with the spatially_filter_image_separable() routine
and its use with this function corresponds to running a Gaussian filter
of sigma width over an image.
!*/
// ----------------------------------------------------------------------------------------
template <
typename in_image_type,
typename out_image_type
>
void gaussian_blur (
const in_image_type& in_img,
out_image_type& out_img,
double sigma = 1,
int max_size = 1001
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- 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
- is_same_object(in_img, out_img) == false
- sigma > 0
- max_size > 0
- max_size is an odd number
ensures
- Filters in_img with a Gaussian filter of sigma width. The actual spatial filter will
be applied to pixel blocks that are at most max_size wide and max_size tall (note that
this function will automatically select a smaller block size as appropriate). The
results are stored into #out_img.
- 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.
- 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()
- #out_img.nr() == in_img.nr()
!*/
// ----------------------------------------------------------------------------------------
template <
typename image_type1,
typename image_type2
>
void sum_filter (
const image_type1& img,
image_type2& out,
const rectangle& rect
);
/*!
requires
- out.nr() == img.nr()
- out.nc() == img.nc()
- image_type1 == an implementation of array2d/array2d_kernel_abstract.h
and it must contain a scalar type
- image_type2 == an implementation of array2d/array2d_kernel_abstract.h
and it must contain a scalar type
- is_same_object(img,out) == false
ensures
- for all valid r and c:
- let SUM(r,c) == sum of pixels from img which are inside the rectangle
translate_rect(rect, point(c,r)).
- #out[r][c] == out[r][c] + SUM(r,c)
!*/
// ----------------------------------------------------------------------------------------
template <
typename image_type1,
typename image_type2
>
void sum_filter_assign (
const image_type1& img,
image_type2& out,
const rectangle& rect
);
/*!
requires
- out.nr() == img.nr()
- out.nc() == img.nc()
- image_type1 == an implementation of array2d/array2d_kernel_abstract.h
and it must contain a scalar type
- image_type2 == an implementation of array2d/array2d_kernel_abstract.h
and it must contain a scalar type
- is_same_object(img,out) == false
ensures
- for all valid r and c:
- let SUM(r,c) == sum of pixels from img which are inside the rectangle
translate_rect(rect, point(c,r)).
- #out[r][c] == SUM(r,c)
!*/
// ----------------------------------------------------------------------------------------
template <
typename image_type1,
typename image_type2
>
void max_filter (
image_type1& img,
image_type2& out,
const long width,
const long height,
const typename image_type1::type& thresh
);
/*!
requires
- out.nr() == img.nr()
- out.nc() == img.nc()
- image_type1 == an implementation of array2d/array2d_kernel_abstract.h
and it must contain a scalar type
- image_type2 == an implementation of array2d/array2d_kernel_abstract.h
and it must contain a scalar type
- is_same_object(img,out) == false
- width > 0 && height > 0
ensures
- for all valid r and c:
- let MAX(r,c) == maximum of pixels from img which are inside the rectangle
centered_rect(point(c,r), width, height)
- if (MAX(r,c) >= thresh)
- #out[r][c] == out[r][c] + MAX(r,c)
- else
- #out[r][c] == out[r][c] + thresh
- Does not change the size of img.
- Uses img as scratch space. Therefore, the pixel values in img will have
been modified by this function. That is, max_filter() destroys the contents
of img.
!*/
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_SPATIAL_FILTERINg_ABSTRACT_