convolve.hpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. Copyright 2005-2007 Adobe Systems Incorporated
  3. Use, modification and distribution are subject to the Boost Software License,
  4. Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. */
  7. /*************************************************************************************************/
  8. #ifndef BOOST_GIL_EXTENSION_NUMERIC_CONVOLVE_HPP
  9. #define BOOST_GIL_EXTENSION_NUMERIC_CONVOLVE_HPP
  10. /*!
  11. /// \file
  12. /// \brief 2D seperable convolutions and correlations
  13. ///
  14. /// \author Hailin Jin and Lubomir Bourdev \n
  15. /// Adobe Systems Incorporated
  16. /// \date 2005-2007 \n
  17. */
  18. #include <cstddef>
  19. #include <cassert>
  20. #include <algorithm>
  21. #include <vector>
  22. #include <functional>
  23. #include <boost/gil/gil_config.hpp>
  24. #include <boost/gil/image_view_factory.hpp>
  25. #include <boost/gil/algorithm.hpp>
  26. #include <boost/gil/metafunctions.hpp>
  27. #include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
  28. #include <boost/gil/extension/numeric/algorithm.hpp>
  29. namespace boost { namespace gil {
  30. /// \ingroup ImageAlgorithms
  31. /// Boundary options for 1D correlations/convolutions
  32. enum convolve_boundary_option {
  33. convolve_option_output_ignore, /// do nothing to the output
  34. convolve_option_output_zero, /// set the output to zero
  35. convolve_option_extend_padded, /// assume the source boundaries to be padded already
  36. convolve_option_extend_zero, /// assume the source boundaries to be zero
  37. convolve_option_extend_constant /// assume the source boundaries to be the boundary value
  38. };
  39. namespace detail {
  40. /// compute the correlation of 1D kernel with the rows of an image
  41. template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView,typename Correlator>
  42. void correlate_rows_imp(const SrcView& src, const Kernel& ker, const DstView& dst,
  43. convolve_boundary_option option,
  44. Correlator correlator) {
  45. assert(src.dimensions()==dst.dimensions());
  46. assert(ker.size()!=0);
  47. typedef typename pixel_proxy<typename SrcView::value_type>::type PIXEL_SRC_REF;
  48. typedef typename pixel_proxy<typename DstView::value_type>::type PIXEL_DST_REF;
  49. typedef typename Kernel::value_type kernel_type;
  50. if(ker.size()==1) {//reduces to a multiplication
  51. view_multiplies_scalar<PixelAccum>(src,*ker.begin(),dst);
  52. return;
  53. }
  54. int width=src.width(),height=src.height();
  55. PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
  56. if (width==0) return;
  57. if (option==convolve_option_output_ignore || option==convolve_option_output_zero) {
  58. typename DstView::value_type dst_zero; pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(acc_zero,dst_zero);
  59. if (width<(int)ker.size()) {
  60. if (option==convolve_option_output_zero)
  61. fill_pixels(dst,dst_zero);
  62. } else {
  63. std::vector<PixelAccum> buffer(width);
  64. for(int rr=0;rr<height;++rr) {
  65. assign_pixels(src.row_begin(rr),src.row_end(rr),&buffer.front());
  66. typename DstView::x_iterator it_dst=dst.row_begin(rr);
  67. if (option==convolve_option_output_zero)
  68. std::fill_n(it_dst,ker.left_size(),dst_zero);
  69. it_dst+=ker.left_size();
  70. correlator(&buffer.front(),&buffer.front()+width+1-ker.size(),
  71. ker.begin(),it_dst);
  72. it_dst+=width+1-ker.size();
  73. if (option==convolve_option_output_zero)
  74. std::fill_n(it_dst,ker.right_size(),dst_zero);
  75. }
  76. }
  77. } else {
  78. std::vector<PixelAccum> buffer(width+ker.size()-1);
  79. for(int rr=0;rr<height;++rr) {
  80. PixelAccum* it_buffer=&buffer.front();
  81. if (option==convolve_option_extend_padded) {
  82. assign_pixels(src.row_begin(rr)-ker.left_size(),
  83. src.row_end(rr)+ker.right_size(),
  84. it_buffer);
  85. } else if (option==convolve_option_extend_zero) {
  86. std::fill_n(it_buffer,ker.left_size(),acc_zero);
  87. it_buffer+=ker.left_size();
  88. assign_pixels(src.row_begin(rr),src.row_end(rr),it_buffer);
  89. it_buffer+=width;
  90. std::fill_n(it_buffer,ker.right_size(),acc_zero);
  91. } else if (option==convolve_option_extend_constant) {
  92. PixelAccum filler;
  93. pixel_assigns_t<PIXEL_SRC_REF,PixelAccum>()(*src.row_begin(rr),filler);
  94. std::fill_n(it_buffer,ker.left_size(),filler);
  95. it_buffer+=ker.left_size();
  96. assign_pixels(src.row_begin(rr),src.row_end(rr),it_buffer);
  97. it_buffer+=width;
  98. pixel_assigns_t<PIXEL_SRC_REF,PixelAccum>()(src.row_end(rr)[-1],filler);
  99. std::fill_n(it_buffer,ker.right_size(),filler);
  100. }
  101. correlator(&buffer.front(),&buffer.front()+width,
  102. ker.begin(),
  103. dst.row_begin(rr));
  104. }
  105. }
  106. }
  107. template <typename PixelAccum>
  108. class correlator_n {
  109. private:
  110. std::size_t _size;
  111. public:
  112. correlator_n(std::size_t size_in) : _size(size_in) {}
  113. template <typename SrcIterator,typename KernelIterator,typename DstIterator>
  114. void operator()(SrcIterator src_begin,SrcIterator src_end,
  115. KernelIterator ker_begin,
  116. DstIterator dst_begin) {
  117. correlate_pixels_n<PixelAccum>(src_begin,src_end,ker_begin,_size,dst_begin);
  118. }
  119. };
  120. template <std::size_t Size,typename PixelAccum>
  121. struct correlator_k {
  122. public:
  123. template <typename SrcIterator,typename KernelIterator,typename DstIterator>
  124. void operator()(SrcIterator src_begin,SrcIterator src_end,
  125. KernelIterator ker_begin,
  126. DstIterator dst_begin){
  127. correlate_pixels_k<Size,PixelAccum>(src_begin,src_end,ker_begin,dst_begin);
  128. }
  129. };
  130. } // namespace detail
  131. /// \ingroup ImageAlgorithms
  132. ///correlate a 1D variable-size kernel along the rows of an image
  133. template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
  134. BOOST_FORCEINLINE
  135. void correlate_rows(const SrcView& src, const Kernel& ker, const DstView& dst,
  136. convolve_boundary_option option=convolve_option_extend_zero) {
  137. detail::correlate_rows_imp<PixelAccum>(src,ker,dst,option,detail::correlator_n<PixelAccum>(ker.size()));
  138. }
  139. /// \ingroup ImageAlgorithms
  140. ///correlate a 1D variable-size kernel along the columns of an image
  141. template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
  142. BOOST_FORCEINLINE
  143. void correlate_cols(const SrcView& src, const Kernel& ker, const DstView& dst,
  144. convolve_boundary_option option=convolve_option_extend_zero) {
  145. correlate_rows<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
  146. }
  147. /// \ingroup ImageAlgorithms
  148. ///convolve a 1D variable-size kernel along the rows of an image
  149. template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
  150. BOOST_FORCEINLINE
  151. void convolve_rows(const SrcView& src, const Kernel& ker, const DstView& dst,
  152. convolve_boundary_option option=convolve_option_extend_zero) {
  153. correlate_rows<PixelAccum>(src,reverse_kernel(ker),dst,option);
  154. }
  155. /// \ingroup ImageAlgorithms
  156. ///convolve a 1D variable-size kernel along the columns of an image
  157. template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
  158. BOOST_FORCEINLINE
  159. void convolve_cols(const SrcView& src, const Kernel& ker, const DstView& dst,
  160. convolve_boundary_option option=convolve_option_extend_zero) {
  161. convolve_rows<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
  162. }
  163. /// \ingroup ImageAlgorithms
  164. ///correlate a 1D fixed-size kernel along the rows of an image
  165. template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
  166. BOOST_FORCEINLINE
  167. void correlate_rows_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
  168. convolve_boundary_option option=convolve_option_extend_zero) {
  169. detail::correlate_rows_imp<PixelAccum>(src,ker,dst,option,detail::correlator_k<Kernel::static_size,PixelAccum>());
  170. }
  171. /// \ingroup ImageAlgorithms
  172. ///correlate a 1D fixed-size kernel along the columns of an image
  173. template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
  174. BOOST_FORCEINLINE
  175. void correlate_cols_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
  176. convolve_boundary_option option=convolve_option_extend_zero) {
  177. correlate_rows_fixed<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
  178. }
  179. /// \ingroup ImageAlgorithms
  180. ///convolve a 1D fixed-size kernel along the rows of an image
  181. template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
  182. BOOST_FORCEINLINE
  183. void convolve_rows_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
  184. convolve_boundary_option option=convolve_option_extend_zero) {
  185. correlate_rows_fixed<PixelAccum>(src,reverse_kernel(ker),dst,option);
  186. }
  187. /// \ingroup ImageAlgorithms
  188. ///convolve a 1D fixed-size kernel along the columns of an image
  189. template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
  190. BOOST_FORCEINLINE
  191. void convolve_cols_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
  192. convolve_boundary_option option=convolve_option_extend_zero) {
  193. convolve_rows_fixed<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
  194. }
  195. } } // namespace boost::gil
  196. #endif // BOOST_GIL_EXTENSION_NUMERIC_CONVOLVE_HPP