12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- #ifndef BOOST_GIL_IMAGE_PROCESSING_HESSIAN_HPP
- #define BOOST_GIL_IMAGE_PROCESSING_HESSIAN_HPP
- #include <boost/gil/image_view.hpp>
- #include <boost/gil/typedefs.hpp>
- #include <boost/gil/extension/numeric/kernel.hpp>
- #include <stdexcept>
- namespace boost { namespace gil {
- /// \brief Computes Hessian response
- ///
- /// Computes Hessian response based on computed entries of Hessian matrix, e.g. second order
- /// derivates in x and y, and derivatives in both x, y.
- /// d stands for derivative, and x or y stand for derivative direction. For example,
- /// ddxx means taking two derivatives (gradients) in horizontal direction.
- /// Weights change perception of surroinding pixels.
- /// Additional filtering is strongly advised.
- template <typename GradientView, typename T, typename Allocator, typename OutputView>
- inline void compute_hessian_responses(
- GradientView ddxx,
- GradientView dxdy,
- GradientView ddyy,
- const detail::kernel_2d<T, Allocator>& weights,
- OutputView dst)
- {
- if (ddxx.dimensions() != ddyy.dimensions()
- || ddyy.dimensions() != dxdy.dimensions()
- || dxdy.dimensions() != dst.dimensions()
- || weights.center_x() != weights.center_y())
- {
- throw std::invalid_argument("dimensions of views are not the same"
- " or weights don't have equal width and height"
- " or weights' dimensions are not odd");
- }
- // Use pixel type of output, as values will be written to output
- using pixel_t = typename std::remove_reference<decltype(std::declval<OutputView>()(0, 0))>::type;
- using channel_t = typename std::remove_reference
- <
- decltype(std::declval<pixel_t>().at(std::integral_constant<int, 0>{}))
- >::type;
- auto center = weights.center_y();
- for (auto y = center; y < dst.height() - center; ++y)
- {
- for (auto x = center; x < dst.width() - center; ++x)
- {
- auto ddxx_i = channel_t();
- auto ddyy_i = channel_t();
- auto dxdy_i = channel_t();
- for (typename OutputView::coord_t w_y = 0; w_y < weights.size(); ++w_y)
- {
- for (typename OutputView::coord_t w_x = 0; w_x < weights.size(); ++w_x)
- {
- ddxx_i += ddxx(x + w_x - center, y + w_y - center)
- .at(std::integral_constant<int, 0>{}) * weights.at(w_x, w_y);
- ddyy_i += ddyy(x + w_x - center, y + w_y - center)
- .at(std::integral_constant<int, 0>{}) * weights.at(w_x, w_y);
- dxdy_i += dxdy(x + w_x - center, y + w_y - center)
- .at(std::integral_constant<int, 0>{}) * weights.at(w_x, w_y);
- }
- }
- auto determinant = ddxx_i * ddyy_i - dxdy_i * dxdy_i;
- dst(x, y).at(std::integral_constant<int, 0>{}) = determinant;
- }
- }
- }
- }} // namespace boost::gil
- #endif
|