Boost GIL


numeric.hpp
1 //
2 // Copyright 2019 Olzhas Zhumabek <anonymous.from.applecity@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 #ifndef BOOST_GIL_IMAGE_PROCESSING_NUMERIC_HPP
9 #define BOOST_GIL_IMAGE_PROCESSING_NUMERIC_HPP
10 
11 #include <boost/gil/detail/math.hpp>
12 #include <cmath>
13 #include <boost/gil/image_view.hpp>
14 #include <boost/gil/typedefs.hpp>
15 
16 namespace boost { namespace gil {
17 
29 inline double normalized_sinc(double x)
30 {
31  return std::sin(x * boost::gil::pi) / (x * boost::gil::pi);
32 }
33 
41 inline double lanczos(double x, std::ptrdiff_t a)
42 {
43  // means == but <= avoids compiler warning
44  if (0 <= x && x <= 0)
45  return 1;
46 
47  if (-a < x && x < a)
48  return normalized_sinc(x) / normalized_sinc(x / static_cast<double>(a));
49 
50  return 0;
51 }
52 
53 inline void compute_tensor_entries(
54  boost::gil::gray16_view_t dx,
55  boost::gil::gray16_view_t dy,
56  boost::gil::gray32f_view_t m11,
57  boost::gil::gray32f_view_t m12_21,
58  boost::gil::gray32f_view_t m22)
59 {
60  for (std::ptrdiff_t y = 0; y < dx.height(); ++y) {
61  for (std::ptrdiff_t x = 0; x < dx.width(); ++x) {
62  auto dx_value = dx(x, y);
63  auto dy_value = dy(x, y);
64  m11(x, y) = dx_value * dx_value;
65  m12_21(x, y) = dx_value * dy_value;
66  m22(x, y) = dy_value * dy_value;
67  }
68  }
69 }
70 
80 template <typename GradientView, typename OutputView>
82  GradientView dx,
83  GradientView dy,
84  OutputView ddxx,
85  OutputView dxdy,
86  OutputView ddyy)
87 {
88  using x_coord_t = typename OutputView::x_coord_t;
89  using y_coord_t = typename OutputView::y_coord_t;
90  using pixel_t = typename std::remove_reference<decltype(ddxx(0, 0))>::type;
91  using channel_t = typename std::remove_reference<
92  decltype(
93  std::declval<pixel_t>().at(
94  std::integral_constant<int, 0>{}
95  )
96  )
97  >::type;
98 
99  constexpr double x_kernel[3][3] =
100  {
101  {1, 0, -1},
102  {2, 0, -2},
103  {1, 0, -1}
104  };
105  constexpr double y_kernel[3][3] =
106  {
107  {1, 2, 1},
108  {0, 0, 0},
109  {-1, -2, -1}
110  };
111  constexpr auto chosen_channel = std::integral_constant<int, 0>{};
112  for (y_coord_t y = 1; y < ddxx.height() - 1; ++y)
113  {
114  for (x_coord_t x = 1; x < ddxx.width() - 1; ++x)
115  {
116  pixel_t ddxx_i;
117  static_transform(ddxx_i, ddxx_i,
118  [](channel_t) { return static_cast<channel_t>(0); });
119  pixel_t dxdy_i;
120  static_transform(dxdy_i, dxdy_i,
121  [](channel_t) { return static_cast<channel_t>(0); });
122  pixel_t ddyy_i;
123  static_transform(ddyy_i, ddyy_i,
124  [](channel_t) { return static_cast<channel_t>(0); });
125  for (y_coord_t y_filter = 0; y_filter < 2; ++y_filter)
126  {
127  for (x_coord_t x_filter = 0; x_filter < 2; ++x_filter)
128  {
129  auto adjusted_y = y + y_filter - 1;
130  auto adjusted_x = x + x_filter - 1;
131  ddxx_i.at(std::integral_constant<int, 0>{}) +=
132  dx(adjusted_x, adjusted_y).at(chosen_channel)
133  * x_kernel[y_filter][x_filter];
134  dxdy_i.at(std::integral_constant<int, 0>{}) +=
135  dx(adjusted_x, adjusted_y).at(chosen_channel)
136  * y_kernel[y_filter][x_filter];
137  ddyy_i.at(std::integral_constant<int, 0>{}) +=
138  dy(adjusted_x, adjusted_y).at(chosen_channel)
139  * y_kernel[y_filter][x_filter];
140  }
141  }
142  ddxx(x, y) = ddxx_i;
143  dxdy(x, y) = dxdy_i;
144  ddyy(x, y) = ddyy_i;
145  }
146  }
147 }
148 
155 inline void generate_normalized_mean(boost::gil::gray32f_view_t dst)
156 {
157  if (dst.width() != dst.height() || dst.width() % 2 != 1)
158  throw std::invalid_argument("kernel dimensions should be odd and equal");
159  const float entry = 1.0f / static_cast<float>(dst.size());
160 
161  for (auto& pixel: dst) {
162  pixel.at(std::integral_constant<int, 0>{}) = entry;
163  }
164 }
165 
170 inline void generate_unnormalized_mean(boost::gil::gray32f_view_t dst)
171 {
172  if (dst.width() != dst.height() || dst.width() % 2 != 1)
173  throw std::invalid_argument("kernel dimensions should be odd and equal");
174 
175  for (auto& pixel: dst) {
176  pixel.at(std::integral_constant<int, 0>{}) = 1.0f;
177  }
178 }
179 
185 inline void generate_gaussian_kernel(boost::gil::gray32f_view_t dst, double sigma)
186 {
187  if (dst.width() != dst.height() || dst.width() % 2 != 1)
188  throw std::invalid_argument("kernel dimensions should be odd and equal");
189 
190  const double denominator = 2 * boost::gil::pi * sigma * sigma;
191  const auto middle = boost::gil::point_t(dst.width() / 2, dst.height() / 2);
192  for (boost::gil::gray32f_view_t::coord_t y = 0; y < dst.height(); ++y)
193  {
194  for (boost::gil::gray32f_view_t::coord_t x = 0; x < dst.width(); ++x)
195  {
196  const auto delta_x = std::abs(middle.x - x);
197  const auto delta_y = std::abs(middle.y - y);
198  const double power = (delta_x * delta_x + delta_y * delta_y) / (2 * sigma * sigma);
199  const double nominator = std::exp(-power);
200  const float value = nominator / denominator;
201  dst(x, y).at(std::integral_constant<int, 0>{}) = value;
202  }
203  }
204 }
205 
206 }} // namespace boost::gil
207 
208 #endif
Definition: algorithm.hpp:30
Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept, PixelValueConcept, HomogeneousPixelBasedConcept.
Definition: metafunctions.hpp:23
void compute_hessian_entries(GradientView dx, GradientView dy, OutputView ddxx, OutputView dxdy, OutputView ddyy)
Compute xy gradient, and second order x and y gradientsHessian matrix is defined as a matrix of parti...
Definition: numeric.hpp:81
double lanczos(double x, std::ptrdiff_t a)
Lanczos response at point xLanczos response is defined as: x == 0: 1 -a < x && x < a: 0 otherwise: no...
Definition: numeric.hpp:41
void generate_normalized_mean(boost::gil::gray32f_view_t dst)
Generate mean kernelFills supplied view with normalized mean in which all entries will be equal to...
Definition: numeric.hpp:155
void generate_unnormalized_mean(boost::gil::gray32f_view_t dst)
Generate kernel with all 1sFills supplied view with 1s (ones)
Definition: numeric.hpp:170
void generate_gaussian_kernel(boost::gil::gray32f_view_t dst, double sigma)
Generate Gaussian kernelFills supplied view with values taken from Gaussian distribution. See https://en.wikipedia.org/wiki/Gaussian_blur.
Definition: numeric.hpp:185