hough_parameter.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Boost.GIL (Generic Image Library) - tests
  2. //
  3. // Copyright 2020 Olzhas Zhumabek <anonymous.from.applecity@gmail.com>
  4. //
  5. // Use, modification and distribution are subject to the Boost Software License,
  6. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. #ifndef BOOST_GIL_EXTENSION_IMAGE_PROCESSING_HOUGH_PARAMETER_HPP
  10. #define BOOST_GIL_EXTENSION_IMAGE_PROCESSING_HOUGH_PARAMETER_HPP
  11. #include "boost/gil/point.hpp"
  12. #include <cmath>
  13. #include <cstddef>
  14. namespace boost
  15. {
  16. namespace gil
  17. {
  18. /// \ingroup HoughTransform
  19. /// \brief A type to encapsulate Hough transform parameter range
  20. ///
  21. /// This type provides a way to express value range for a parameter
  22. /// as well as some factory functions to simplify initialization
  23. template <typename T>
  24. struct hough_parameter
  25. {
  26. T start_point;
  27. T step_size;
  28. std::size_t step_count;
  29. /// \ingroup HoughTransform
  30. /// \brief Create Hough parameter from value neighborhood and step count
  31. ///
  32. /// This function will take start_point as middle point, and in both
  33. /// directions will try to walk half_step_count times until distance of
  34. /// neighborhood is reached
  35. static hough_parameter<T> from_step_count(T start_point, T neighborhood,
  36. std::size_t half_step_count)
  37. {
  38. T step_size = neighborhood / half_step_count;
  39. std::size_t step_count = half_step_count * 2 + 1;
  40. // explicitly fill out members, as aggregate init will error out with narrowing
  41. hough_parameter<T> parameter;
  42. parameter.start_point = start_point - neighborhood;
  43. parameter.step_size = step_size;
  44. parameter.step_count = step_count;
  45. return parameter;
  46. }
  47. /// \ingroup HoughTransform
  48. /// \brief Create Hough parameter from value neighborhood and step size
  49. ///
  50. /// This function will take start_point as middle point, and in both
  51. /// directions will try to walk step_size at a time until distance of
  52. /// neighborhood is reached
  53. static hough_parameter<T> from_step_size(T start_point, T neighborhood, T step_size)
  54. {
  55. std::size_t step_count =
  56. 2 * static_cast<std::size_t>(std::floor(neighborhood / step_size)) + 1;
  57. // do not use step_size - neighborhood, as step_size might not allow
  58. // landing exactly on that value when starting from start_point
  59. // also use parentheses on step_count / 2 because flooring is exactly
  60. // what we want
  61. // explicitly fill out members, as aggregate init will error out with narrowing
  62. hough_parameter<T> parameter;
  63. parameter.start_point = start_point - step_size * (step_count / 2);
  64. parameter.step_size = step_size;
  65. parameter.step_count = step_count;
  66. return parameter;
  67. }
  68. };
  69. /// \ingroup HoughTransform
  70. /// \brief Calculate minimum angle which would be observable if walked on a circle
  71. ///
  72. /// When drawing a circle or moving around a point in circular motion, it is
  73. /// important to not do too many steps, but also to not have disconnected
  74. /// trajectory. This function will calculate the minimum angle that is observable
  75. /// when walking on a circle or tilting a line.
  76. /// WARNING: do keep in mind IEEE 754 quirks, e.g. no-associativity,
  77. /// no-commutativity and precision. Do not expect expressions that are
  78. /// mathematically the same to produce the same values
  79. inline double minimum_angle_step(point_t dimensions)
  80. {
  81. auto longer_dimension = dimensions.x > dimensions.y ? dimensions.x : dimensions.y;
  82. return std::atan2(1, longer_dimension);
  83. }
  84. /// \ingroup HoughTransform
  85. /// \brief Create a Hough transform parameter with optimal angle step
  86. ///
  87. /// Due to computational intensity and noise sensitivity of Hough transform,
  88. /// having any candidates missed or computed again is problematic. This function
  89. /// will properly encapsulate optimal value range around approx_angle with amplitude of
  90. /// neighborhood in each direction.
  91. /// WARNING: do keep in mind IEEE 754 quirks, e.g. no-associativity,
  92. /// no-commutativity and precision. Do not expect expressions that are
  93. /// mathematically the same to produce the same values
  94. inline auto make_theta_parameter(double approx_angle, double neighborhood, point_t dimensions)
  95. -> hough_parameter<double>
  96. {
  97. auto angle_step = minimum_angle_step(dimensions);
  98. // std::size_t step_count =
  99. // 2 * static_cast<std::size_t>(std::floor(neighborhood / angle_step)) + 1;
  100. // return {approx_angle - angle_step * (step_count / 2), angle_step, step_count};
  101. return hough_parameter<double>::from_step_size(approx_angle, neighborhood, angle_step);
  102. }
  103. }} // namespace boost::gil
  104. #endif