/* Copyright 2005-2007 Adobe Systems Incorporated Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt or a copy at http://opensource.adobe.com/licenses.html) */ /*************************************************************************************************/ #ifndef GIL_CONVOLVE_HPP #define GIL_CONVOLVE_HPP /*! /// \file /// \brief 2D seperable convolutions and correlations /// /// \author Hailin Jin and Lubomir Bourdev \n /// Adobe Systems Incorporated /// \date 2005-2007 \n Last updated on February 6, 2007 */ #include #include #include #include #include #include #include #include #include #include "pixel_numeric_operations.hpp" #include "algorithm.hpp" namespace boost { namespace gil { /// \ingroup ImageAlgorithms /// Boundary options for 1D correlations/convolutions enum convolve_boundary_option { convolve_option_output_ignore, /// do nothing to the output convolve_option_output_zero, /// set the output to zero convolve_option_extend_padded, /// assume the source boundaries to be padded already convolve_option_extend_zero, /// assume the source boundaries to be zero convolve_option_extend_constant /// assume the source boundaries to be the boundary value }; namespace detail { /// compute the correlation of 1D kernel with the rows of an image template void correlate_rows_imp(const SrcView& src, const Kernel& ker, const DstView& dst, convolve_boundary_option option, Correlator correlator) { assert(src.dimensions()==dst.dimensions()); assert(ker.size()!=0); typedef typename pixel_proxy::type PIXEL_SRC_REF; typedef typename pixel_proxy::type PIXEL_DST_REF; typedef typename Kernel::value_type kernel_type; if(ker.size()==1) {//reduces to a multiplication view_multiplies_scalar(src,*ker.begin(),dst); return; } int width=src.width(),height=src.height(); PixelAccum acc_zero; pixel_zeros_t()(acc_zero); if (width==0) return; if (option==convolve_option_output_ignore || option==convolve_option_output_zero) { typename DstView::value_type dst_zero; pixel_assigns_t()(acc_zero,dst_zero); if (width<(int)ker.size()) { if (option==convolve_option_output_zero) fill_pixels(dst,dst_zero); } else { std::vector buffer(width); for(int rr=0;rr buffer(width+ker.size()-1); for(int rr=0;rr()(*src.row_begin(rr),filler); std::fill_n(it_buffer,ker.left_size(),filler); it_buffer+=ker.left_size(); assign_pixels(src.row_begin(rr),src.row_end(rr),it_buffer); it_buffer+=width; pixel_assigns_t()(src.row_end(rr)[-1],filler); std::fill_n(it_buffer,ker.right_size(),filler); } correlator(&buffer.front(),&buffer.front()+width, ker.begin(), dst.row_begin(rr)); } } } template class correlator_n { private: std::size_t _size; public: correlator_n(std::size_t size_in) : _size(size_in) {} template void operator()(SrcIterator src_begin,SrcIterator src_end, KernelIterator ker_begin, DstIterator dst_begin) { correlate_pixels_n(src_begin,src_end,ker_begin,_size,dst_begin); } }; template struct correlator_k { public: template void operator()(SrcIterator src_begin,SrcIterator src_end, KernelIterator ker_begin, DstIterator dst_begin){ correlate_pixels_k(src_begin,src_end,ker_begin,dst_begin); } }; } // namespace detail /// \ingroup ImageAlgorithms ///correlate a 1D variable-size kernel along the rows of an image template GIL_FORCEINLINE void correlate_rows(const SrcView& src, const Kernel& ker, const DstView& dst, convolve_boundary_option option=convolve_option_extend_zero) { detail::correlate_rows_imp(src,ker,dst,option,detail::correlator_n(ker.size())); } /// \ingroup ImageAlgorithms ///correlate a 1D variable-size kernel along the columns of an image template GIL_FORCEINLINE void correlate_cols(const SrcView& src, const Kernel& ker, const DstView& dst, convolve_boundary_option option=convolve_option_extend_zero) { correlate_rows(transposed_view(src),ker,transposed_view(dst),option); } /// \ingroup ImageAlgorithms ///convolve a 1D variable-size kernel along the rows of an image template GIL_FORCEINLINE void convolve_rows(const SrcView& src, const Kernel& ker, const DstView& dst, convolve_boundary_option option=convolve_option_extend_zero) { correlate_rows(src,reverse_kernel(ker),dst,option); } /// \ingroup ImageAlgorithms ///convolve a 1D variable-size kernel along the columns of an image template GIL_FORCEINLINE void convolve_cols(const SrcView& src, const Kernel& ker, const DstView& dst, convolve_boundary_option option=convolve_option_extend_zero) { convolve_rows(transposed_view(src),ker,transposed_view(dst),option); } /// \ingroup ImageAlgorithms ///correlate a 1D fixed-size kernel along the rows of an image template GIL_FORCEINLINE void correlate_rows_fixed(const SrcView& src, const Kernel& ker, const DstView& dst, convolve_boundary_option option=convolve_option_extend_zero) { detail::correlate_rows_imp(src,ker,dst,option,detail::correlator_k()); } /// \ingroup ImageAlgorithms ///correlate a 1D fixed-size kernel along the columns of an image template GIL_FORCEINLINE void correlate_cols_fixed(const SrcView& src, const Kernel& ker, const DstView& dst, convolve_boundary_option option=convolve_option_extend_zero) { correlate_rows_fixed(transposed_view(src),ker,transposed_view(dst),option); } /// \ingroup ImageAlgorithms ///convolve a 1D fixed-size kernel along the rows of an image template GIL_FORCEINLINE void convolve_rows_fixed(const SrcView& src, const Kernel& ker, const DstView& dst, convolve_boundary_option option=convolve_option_extend_zero) { correlate_rows_fixed(src,reverse_kernel(ker),dst,option); } /// \ingroup ImageAlgorithms ///convolve a 1D fixed-size kernel along the columns of an image template GIL_FORCEINLINE void convolve_cols_fixed(const SrcView& src, const Kernel& ker, const DstView& dst, convolve_boundary_option option=convolve_option_extend_zero) { convolve_rows_fixed(transposed_view(src),ker,transposed_view(dst),option); } } } // namespace boost::gil #endif