9 #ifndef BOOST_GIL_IMAGE_PROCESSING_NUMERIC_HPP
10 #define BOOST_GIL_IMAGE_PROCESSING_NUMERIC_HPP
12 #include <boost/gil/image_processing/kernel.hpp>
13 #include <boost/gil/image_processing/convolve.hpp>
14 #include <boost/gil/image_view.hpp>
15 #include <boost/gil/typedefs.hpp>
16 #include <boost/gil/detail/math.hpp>
21 namespace boost {
namespace gil {
34 inline double normalized_sinc(
double x)
36 return std::sin(x * boost::gil::detail::pi) / (x * boost::gil::detail::pi);
46 inline double lanczos(
double x, std::ptrdiff_t a)
52 if (
static_cast<double>(-a) < x && x <
static_cast<double>(a))
53 return normalized_sinc(x) / normalized_sinc(x /
static_cast<double>(a));
58 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
60 #pragma warning(disable:4244) // 'argument': conversion from 'const Channel' to 'BaseChannelValue', possible loss of data
63 inline void compute_tensor_entries(
64 boost::gil::gray16s_view_t dx,
65 boost::gil::gray16s_view_t dy,
66 boost::gil::gray32f_view_t m11,
67 boost::gil::gray32f_view_t m12_21,
68 boost::gil::gray32f_view_t m22)
70 for (std::ptrdiff_t y = 0; y < dx.height(); ++y) {
71 for (std::ptrdiff_t x = 0; x < dx.width(); ++x) {
72 auto dx_value = dx(x, y);
73 auto dy_value = dy(x, y);
74 m11(x, y) = dx_value * dx_value;
75 m12_21(x, y) = dx_value * dy_value;
76 m22(x, y) = dy_value * dy_value;
81 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
91 template <
typename T =
float,
typename Allocator = std::allocator<T>>
94 if (side_length % 2 != 1)
95 throw std::invalid_argument(
"kernel dimensions should be odd and equal");
96 const float entry = 1.0f /
static_cast<float>(side_length * side_length);
99 for (
auto& cell: result) {
110 template <
typename T =
float,
typename Allocator = std::allocator<T>>
113 if (side_length % 2 != 1)
114 throw std::invalid_argument(
"kernel dimensions should be odd and equal");
117 for (
auto& cell: result) {
129 template <
typename T =
float,
typename Allocator = std::allocator<T>>
132 if (side_length % 2 != 1)
133 throw std::invalid_argument(
"kernel dimensions should be odd and equal");
136 const double denominator = 2 * boost::gil::detail::pi * sigma * sigma;
137 auto middle = side_length / 2;
138 std::vector<T, Allocator> values(side_length * side_length);
139 for (std::size_t y = 0; y < side_length; ++y)
141 for (std::size_t x = 0; x < side_length; ++x)
143 const auto delta_x = middle > x ? middle - x : x - middle;
144 const auto delta_y = middle > y ? middle - y : y - middle;
145 const double power = (delta_x * delta_x + delta_y * delta_y) / (2 * sigma * sigma);
146 const double nominator = std::exp(-power);
147 const float value =
static_cast<float>(nominator / denominator);
148 values[y * side_length + x] = value;
162 template <
typename T =
float,
typename Allocator = std::allocator<T>>
169 return detail::get_identity_kernel<T, Allocator>();
174 std::copy(detail::dx_sobel.begin(), detail::dx_sobel.end(), result.begin());
178 throw std::logic_error(
"not supported yet");
182 throw std::runtime_error(
"unreachable statement");
192 template <
typename T =
float,
typename Allocator = std::allocator<T>>
199 return detail::get_identity_kernel<T, Allocator>();
204 std::copy(detail::dx_scharr.begin(), detail::dx_scharr.end(), result.begin());
208 throw std::logic_error(
"not supported yet");
212 throw std::runtime_error(
"unreachable statement");
222 template <
typename T =
float,
typename Allocator = std::allocator<T>>
229 return detail::get_identity_kernel<T, Allocator>();
234 std::copy(detail::dy_sobel.begin(), detail::dy_sobel.end(), result.begin());
238 throw std::logic_error(
"not supported yet");
242 throw std::runtime_error(
"unreachable statement");
252 template <
typename T =
float,
typename Allocator = std::allocator<T>>
259 return detail::get_identity_kernel<T, Allocator>();
264 std::copy(detail::dy_scharr.begin(), detail::dy_scharr.end(), result.begin());
268 throw std::logic_error(
"not supported yet");
272 throw std::runtime_error(
"unreachable statement");
284 template <
typename GradientView,
typename OutputView>
294 detail::convolve_2d(dx, sobel_x, ddxx);
295 detail::convolve_2d(dx, sobel_y, dxdy);
296 detail::convolve_2d(dy, sobel_y, ddyy);