Boost GIL


filter.hpp
1 //
2 // Copyright 2019 Miral Shah <miralshah2211@gmail.com>
3 //
4 // Use, modification and distribution are subject to the Boost Software License,
5 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 
9 #ifndef BOOST_GIL_IMAGE_PROCESSING_FILTER_HPP
10 #define BOOST_GIL_IMAGE_PROCESSING_FILTER_HPP
11 
12 #include <boost/gil/extension/numeric/algorithm.hpp>
13 #include <boost/gil/extension/numeric/kernel.hpp>
14 #include <boost/gil/extension/numeric/convolve.hpp>
15 
16 #include <boost/gil/image.hpp>
17 #include <boost/gil/image_view.hpp>
18 
19 #include <cstddef>
20 #include <vector>
21 
22 
23 
24 
25 namespace boost { namespace gil {
26 
27 template <typename SrcView, typename DstView>
28 void box_filter(
29  SrcView const& src_view,
30  DstView const& dst_view,
31  std::size_t kernel_size,
32  long int anchor = -1,
33  bool normalize=true,
34  boundary_option option = boundary_option::extend_zero
35 )
36 {
37  gil_function_requires<ImageViewConcept<SrcView>>();
38  gil_function_requires<MutableImageViewConcept<DstView>>();
39  static_assert(color_spaces_are_compatible
40  <
41  typename color_space_type<SrcView>::type,
42  typename color_space_type<DstView>::type
43  >::value, "Source and destination views must have pixels with the same color space");
44 
45  std::vector<float> kernel_values;
46  if (normalize) { kernel_values.resize(kernel_size, 1.0f / float(kernel_size)); }
47  else { kernel_values.resize(kernel_size, 1.0f); }
48 
49  if (anchor == -1) anchor = static_cast<int>(kernel_size / 2);
50  kernel_1d<float> kernel(kernel_values.begin(), kernel_size, anchor);
51 
52  detail::convolve_1d
53  <
54  pixel<float, typename SrcView::value_type::layout_t>
55  >(src_view, kernel, dst_view, option);
56 }
57 
58 template <typename SrcView, typename DstView>
59 void blur(
60  SrcView const& src_view,
61  DstView const& dst_view,
62  std::size_t kernel_size,
63  long int anchor = -1,
64  boundary_option option = boundary_option::extend_zero
65 )
66 {
67  box_filter(src_view, dst_view, kernel_size, anchor, true, option);
68 }
69 
70 
71 namespace detail
72 {
73 template <typename SrcView, typename DstView>
74 void filter_median_impl(SrcView const& src_view, DstView const& dst_view, std::size_t kernel_size)
75 {
76  std::size_t half_kernel_size = kernel_size / 2;
77 
78  // deciding output channel type and creating functor
79  using src_channel_t = typename channel_type<SrcView>::type;
80 
81  std::vector<src_channel_t> values;
82  values.reserve(kernel_size * kernel_size);
83 
84  for (std::ptrdiff_t y = 0; y < src_view.height(); y++)
85  {
86  typename DstView::x_iterator dst_it = dst_view.row_begin(y);
87 
88  for (std::ptrdiff_t x = 0; x < src_view.width(); x++)
89  {
90  auto sub_view = subimage_view(
91  src_view,
92  x - half_kernel_size, y - half_kernel_size,
93  kernel_size,
94  kernel_size
95  );
96  values.assign(sub_view.begin(), sub_view.end());
97 
98  std::nth_element(values.begin(), values.begin() + (values.size() / 2), values.end());
99  dst_it[x] = values[values.size() / 2];
100  }
101  }
102 }
103 } // namespace detail
104 
105 template <typename SrcView, typename DstView>
106 void median_filter(SrcView const& src_view, DstView const& dst_view, std::size_t kernel_size)
107 {
108  static_assert(color_spaces_are_compatible
109  <
110  typename color_space_type<SrcView>::type,
111  typename color_space_type<DstView>::type
112  >::value, "Source and destination views must have pixels with the same color space");
113 
114  std::size_t half_kernel_size = kernel_size / 2;
115  auto extended_img = extend_boundary(
116  src_view,
117  half_kernel_size,
118  boundary_option::extend_constant
119  );
120  auto extended_view = subimage_view(
121  view(extended_img),
122  half_kernel_size,
123  half_kernel_size,
124  src_view.width(),
125  src_view.height()
126  );
127 
128  for (std::size_t channel = 0; channel < extended_view.num_channels(); channel++)
129  {
130  detail::filter_median_impl(
131  nth_channel_view(extended_view, channel),
132  nth_channel_view(dst_view, channel),
133  kernel_size
134  );
135  }
136 }
137 
138 }} //namespace boost::gil
139 
140 #endif // !BOOST_GIL_IMAGE_PROCESSING_FILTER_HPP
const image< Pixel, IsPlanar, Alloc >::view_t & view(image< Pixel, IsPlanar, Alloc > &img)
Returns the non-constant-pixel view of an image.
Definition: image.hpp:443