hessian.hpp 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. //
  2. // Copyright 2019 Olzhas Zhumabek <anonymous.from.applecity@gmail.com>
  3. // Copyright 2021 Scramjet911 <36035352+Scramjet911@users.noreply.github.com>
  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. #ifndef BOOST_GIL_IMAGE_PROCESSING_HESSIAN_HPP
  8. #define BOOST_GIL_IMAGE_PROCESSING_HESSIAN_HPP
  9. #include <boost/gil/image_view.hpp>
  10. #include <boost/gil/typedefs.hpp>
  11. #include <boost/gil/image_processing/kernel.hpp>
  12. #include <stdexcept>
  13. namespace boost { namespace gil {
  14. /// \brief Computes Hessian response
  15. ///
  16. /// Computes Hessian response based on computed entries of Hessian matrix, e.g. second order
  17. /// derivates in x and y, and derivatives in both x, y.
  18. /// d stands for derivative, and x or y stand for derivative direction. For example,
  19. /// ddxx means taking two derivatives (gradients) in horizontal direction.
  20. /// Weights change perception of surroinding pixels.
  21. /// Additional filtering is strongly advised.
  22. template <typename GradientView, typename T, typename Allocator, typename OutputView>
  23. inline void compute_hessian_responses(
  24. GradientView ddxx,
  25. GradientView dxdy,
  26. GradientView ddyy,
  27. const detail::kernel_2d<T, Allocator>& weights,
  28. OutputView dst)
  29. {
  30. if (ddxx.dimensions() != ddyy.dimensions()
  31. || ddyy.dimensions() != dxdy.dimensions()
  32. || dxdy.dimensions() != dst.dimensions()
  33. || weights.center_x() != weights.center_y())
  34. {
  35. throw std::invalid_argument("dimensions of views are not the same"
  36. " or weights don't have equal width and height"
  37. " or weights' dimensions are not odd");
  38. }
  39. // Use pixel type of output, as values will be written to output
  40. using pixel_t = typename std::remove_reference<decltype(std::declval<OutputView>()(0, 0))>::type;
  41. using channel_t = typename std::remove_reference
  42. <
  43. decltype(std::declval<pixel_t>().at(std::integral_constant<int, 0>{}))
  44. >::type;
  45. auto center = weights.center_y();
  46. for (auto y = center; y < dst.height() - center; ++y)
  47. {
  48. for (auto x = center; x < dst.width() - center; ++x)
  49. {
  50. auto ddxx_i = channel_t();
  51. auto ddyy_i = channel_t();
  52. auto dxdy_i = channel_t();
  53. for (typename OutputView::coord_t w_y = 0; w_y < static_cast<std::ptrdiff_t>(weights.size()); ++w_y)
  54. {
  55. for (typename OutputView::coord_t w_x = 0; w_x < static_cast<std::ptrdiff_t>(weights.size()); ++w_x)
  56. {
  57. ddxx_i += ddxx(x + w_x - center, y + w_y - center)
  58. .at(std::integral_constant<int, 0>{}) * weights.at(w_x, w_y);
  59. ddyy_i += ddyy(x + w_x - center, y + w_y - center)
  60. .at(std::integral_constant<int, 0>{}) * weights.at(w_x, w_y);
  61. dxdy_i += dxdy(x + w_x - center, y + w_y - center)
  62. .at(std::integral_constant<int, 0>{}) * weights.at(w_x, w_y);
  63. }
  64. }
  65. auto determinant = ddxx_i * ddyy_i - dxdy_i * dxdy_i;
  66. dst(x, y).at(std::integral_constant<int, 0>{}) = determinant;
  67. }
  68. }
  69. }
  70. }} // namespace boost::gil
  71. #endif