File indexing completed on 2025-12-16 09:51:45
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GIL_EXTENSION_IMAGE_PROCESSING_HOUGH_TRANSFORM_HPP
0010 #define BOOST_GIL_EXTENSION_IMAGE_PROCESSING_HOUGH_TRANSFORM_HPP
0011
0012 #include <boost/gil/extension/image_processing/hough_parameter.hpp>
0013 #include <boost/gil/extension/rasterization/circle.hpp>
0014
0015 #include <algorithm>
0016 #include <cmath>
0017 #include <cstddef>
0018 #include <iterator>
0019 #include <vector>
0020
0021 namespace boost { namespace gil {
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 template <typename InputView, typename OutputView>
0038 void hough_line_transform(InputView const& input_view, OutputView const& accumulator_array,
0039 hough_parameter<double> const& theta,
0040 hough_parameter<std::ptrdiff_t> const& radius)
0041 {
0042 std::ptrdiff_t r_lower_bound = radius.start_point;
0043 std::ptrdiff_t r_upper_bound = r_lower_bound + radius.step_size * (radius.step_count - 1);
0044
0045 for (std::ptrdiff_t y = 0; y < input_view.height(); ++y)
0046 {
0047 for (std::ptrdiff_t x = 0; x < input_view.width(); ++x)
0048 {
0049 if (!input_view(x, y)[0])
0050 {
0051 continue;
0052 }
0053
0054 for (std::size_t theta_index = 0; theta_index < theta.step_count; ++theta_index)
0055 {
0056 double theta_current =
0057 theta.start_point + theta.step_size * static_cast<double>(theta_index);
0058 std::ptrdiff_t current_r =
0059 std::llround(static_cast<double>(x) * std::cos(theta_current) +
0060 static_cast<double>(y) * std::sin(theta_current));
0061 if (current_r < r_lower_bound || current_r > r_upper_bound)
0062 {
0063 continue;
0064 }
0065 std::size_t r_index = static_cast<std::size_t>(
0066 std::llround((current_r - radius.start_point) / radius.step_size));
0067
0068 if (r_index < radius.step_count)
0069 {
0070 accumulator_array(theta_index, r_index)[0] += 1;
0071 }
0072 }
0073 }
0074 }
0075 }
0076
0077
0078
0079
0080
0081
0082
0083
0084 template <typename ImageView, typename ForwardIterator, typename Rasterizer>
0085 void hough_circle_transform_brute(ImageView const& input,
0086 hough_parameter<std::ptrdiff_t> const& radius_parameter,
0087 hough_parameter<std::ptrdiff_t> const& x_parameter,
0088 hough_parameter<std::ptrdiff_t> const& y_parameter,
0089 ForwardIterator d_first, Rasterizer rasterizer)
0090 {
0091 for (std::size_t radius_index = 0; radius_index < radius_parameter.step_count; ++radius_index)
0092 {
0093 const auto radius = radius_parameter.start_point +
0094 radius_parameter.step_size * static_cast<std::ptrdiff_t>(radius_index);
0095 Rasterizer rasterizer{point_t{}, radius};
0096 std::vector<point_t> circle_points(rasterizer.point_count());
0097 rasterizer(circle_points.begin());
0098
0099 std::sort(circle_points.begin(), circle_points.end(),
0100 [](point_t const& lhs, point_t const& rhs) { return lhs.y < rhs.y; });
0101 const auto translate = [](std::vector<point_t>& points, point_t offset) {
0102 std::transform(points.begin(), points.end(), points.begin(), [offset](point_t point) {
0103 return point_t(point.x + offset.x, point.y + offset.y);
0104 });
0105 };
0106
0107
0108 typename std::iterator_traits<ForwardIterator>::reference current_image = *d_first;
0109
0110
0111
0112
0113
0114 for (std::size_t x_index = 0; x_index < x_parameter.step_count; ++x_index)
0115 {
0116 for (std::size_t y_index = 0; y_index < y_parameter.step_count; ++y_index)
0117 {
0118 const std::ptrdiff_t x = x_parameter.start_point + x_index * x_parameter.step_size;
0119 const std::ptrdiff_t y = y_parameter.start_point + y_index * y_parameter.step_size;
0120
0121 auto translated_circle = circle_points;
0122 translate(translated_circle, {x, y});
0123 for (const auto& point : translated_circle)
0124 {
0125 if (input(point))
0126 {
0127 ++current_image(x_index, y_index)[0];
0128 }
0129 }
0130 }
0131 }
0132 ++d_first;
0133 }
0134 }
0135
0136 }}
0137
0138 #endif