#ifndef BOOST_GIL_IMAGE_PROCESSING_HESSIAN_HPP #define BOOST_GIL_IMAGE_PROCESSING_HESSIAN_HPP #include #include #include #include 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 inline void compute_hessian_responses( GradientView ddxx, GradientView dxdy, GradientView ddyy, const detail::kernel_2d& 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()(0, 0))>::type; using channel_t = typename std::remove_reference < decltype(std::declval().at(std::integral_constant{})) >::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{}) * weights.at(w_x, w_y); ddyy_i += ddyy(x + w_x - center, y + w_y - center) .at(std::integral_constant{}) * weights.at(w_x, w_y); dxdy_i += dxdy(x + w_x - center, y + w_y - center) .at(std::integral_constant{}) * weights.at(w_x, w_y); } } auto determinant = ddxx_i * ddyy_i - dxdy_i * dxdy_i; dst(x, y).at(std::integral_constant{}) = determinant; } } } }} // namespace boost::gil #endif