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)
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>>
95 if (side_length % 2 != 1)
96 throw std::invalid_argument(
"kernel dimensions should be odd and equal");
97 const float entry = 1.0f /
static_cast<float>(side_length * side_length);
100 for (
auto& cell: result) {
111 template <
typename T =
float,
typename Allocator = std::allocator<T>>
115 if (side_length % 2 != 1)
116 throw std::invalid_argument(
"kernel dimensions should be odd and equal");
119 for (
auto& cell: result) {
131 template <
typename T =
float,
typename Allocator = std::allocator<T>>
135 if (side_length % 2 != 1)
136 throw std::invalid_argument(
"kernel dimensions should be odd and equal");
138 const double denominator = 2 * boost::gil::detail::pi * sigma * sigma;
139 auto const middle = side_length / 2;
140 std::vector<T, Allocator> values(side_length * side_length);
142 for (std::size_t y = 0; y < side_length; ++y)
144 for (std::size_t x = 0; x < side_length; ++x)
146 const auto delta_x = x - middle;
147 const auto delta_y = y - middle;
148 const auto power =
static_cast<double>(delta_x * delta_x + delta_y * delta_y) / (2 * sigma * sigma);
149 const double nominator = std::exp(-power);
150 const auto value =
static_cast<T
>(nominator / denominator);
151 values[y * side_length + x] = value;
157 std::transform(values.begin(), values.end(), values.begin(), [&sum](
const auto & v) { return v/sum; });
169 template <
typename T =
float,
typename Allocator = std::allocator<T>>
177 return detail::get_identity_kernel<T, Allocator>();
182 std::copy(detail::dx_sobel.begin(), detail::dx_sobel.end(), result.begin());
186 throw std::logic_error(
"not supported yet");
190 throw std::runtime_error(
"unreachable statement");
200 template <
typename T =
float,
typename Allocator = std::allocator<T>>
208 return detail::get_identity_kernel<T, Allocator>();
213 std::copy(detail::dx_scharr.begin(), detail::dx_scharr.end(), result.begin());
217 throw std::logic_error(
"not supported yet");
221 throw std::runtime_error(
"unreachable statement");
231 template <
typename T =
float,
typename Allocator = std::allocator<T>>
239 return detail::get_identity_kernel<T, Allocator>();
244 std::copy(detail::dy_sobel.begin(), detail::dy_sobel.end(), result.begin());
248 throw std::logic_error(
"not supported yet");
252 throw std::runtime_error(
"unreachable statement");
262 template <
typename T =
float,
typename Allocator = std::allocator<T>>
270 return detail::get_identity_kernel<T, Allocator>();
275 std::copy(detail::dy_scharr.begin(), detail::dy_scharr.end(), result.begin());
279 throw std::logic_error(
"not supported yet");
283 throw std::runtime_error(
"unreachable statement");
295 template <
typename GradientView,
typename OutputView>
305 detail::convolve_2d(dx, sobel_x, ddxx);
306 detail::convolve_2d(dx, sobel_y, dxdy);
307 detail::convolve_2d(dy, sobel_y, ddyy);
variable-size kernel
Definition: kernel.hpp:273
auto generate_gaussian_kernel(std::size_t side_length, double sigma) -> detail::kernel_2d< T, Allocator >
Generate Gaussian kernel.
Definition: numeric.hpp:132
auto generate_unnormalized_mean(std::size_t side_length) -> detail::kernel_2d< T, Allocator >
Generate kernel with all 1s.
Definition: numeric.hpp:112
void compute_hessian_entries(GradientView dx, GradientView dy, OutputView ddxx, OutputView dxdy, OutputView ddyy)
Compute xy gradient, and second order x and y gradients.
Definition: numeric.hpp:296
auto generate_dy_scharr(unsigned int degree=1) -> detail::kernel_2d< T, Allocator >
Generate Scharr operator in vertical direction.
Definition: numeric.hpp:263
double lanczos(double x, std::ptrdiff_t a)
Lanczos response at point x.
Definition: numeric.hpp:46
auto generate_dx_sobel(unsigned int degree=1) -> detail::kernel_2d< T, Allocator >
Generates Sobel operator in horizontal direction.
Definition: numeric.hpp:170
auto generate_normalized_mean(std::size_t side_length) -> detail::kernel_2d< T, Allocator >
Generate mean kernel.
Definition: numeric.hpp:92
auto generate_dy_sobel(unsigned int degree=1) -> detail::kernel_2d< T, Allocator >
Generates Sobel operator in vertical direction.
Definition: numeric.hpp:232
auto generate_dx_scharr(unsigned int degree=1) -> detail::kernel_2d< T, Allocator >
Generate Scharr operator in horizontal direction.
Definition: numeric.hpp:201
BOOST_FORCEINLINE auto copy(boost::gil::pixel< T, CS > *first, boost::gil::pixel< T, CS > *last, boost::gil::pixel< T, CS > *dst) -> boost::gil::pixel< T, CS > *
Copy when both src and dst are interleaved and of the same type can be just memmove.
Definition: algorithm.hpp:145
defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
Definition: algorithm.hpp:36