std.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. //
  2. // Copyright 2020 Debabrata Mandal <[email protected]>
  3. //
  4. // Distributed under the Boost Software License, Version 1.0
  5. // See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt
  7. //
  8. #ifndef BOOST_GIL_EXTENSION_HISTOGRAM_STL_HISTOGRAM_HPP
  9. #define BOOST_GIL_EXTENSION_HISTOGRAM_STL_HISTOGRAM_HPP
  10. #include <boost/gil/concepts/concept_check.hpp>
  11. #include <boost/gil/gray.hpp>
  12. #include <boost/gil/histogram.hpp>
  13. #include <boost/gil/image_view.hpp>
  14. #include <boost/gil/image_view_factory.hpp>
  15. #include <array>
  16. #include <map>
  17. #include <utility>
  18. #include <vector>
  19. namespace boost { namespace gil {
  20. //////////////////////////////////////////////////////////
  21. /// Histogram extension for STL container
  22. //////////////////////////////////////////////////////////
  23. /// \defgroup Histogram - STL Containers
  24. /// \brief Collection of functions to provide histogram support in GIL using Standard
  25. /// Template Library Containers
  26. /// The conversion from Boost.GIL images to compatible histograms are provided. The supported
  27. /// container types would be std::vector, std::array, std::map.
  28. ///
  29. /// Some general constraints on STL extension:-
  30. /// 1. Supports only 1D histogram.
  31. /// 2. Cannot use signed images with compatible random access containers.
  32. /// 3. Automatic resize of std::array in case of shortage of bins, to ensure
  33. /// correctness comes before performance.
  34. /// 4. Container key type (if exists) has to be one of std::integral types to be
  35. /// GIL compatible.
  36. /// 5. Container value type has to be of std::arithmetic types.
  37. ///
  38. ///
  39. /// \ingroup Histogram - STL Containers
  40. /// \brief Overload for std::vector of fill_histogram
  41. ///
  42. template <typename SrcView, typename T>
  43. void fill_histogram(SrcView const& srcview, std::vector<T>& histogram, bool accumulate = false)
  44. {
  45. gil_function_requires<ImageViewConcept<SrcView>>();
  46. static_assert(std::is_arithmetic<T>::value, "Improper container type for images.");
  47. static_assert(
  48. std::is_unsigned<typename channel_type<SrcView>::type>::value,
  49. "Improper container type for signed images.");
  50. using channel_t = typename channel_type<SrcView>::type;
  51. using pixel_t = pixel<channel_t, gray_layout_t>;
  52. if (!accumulate)
  53. histogram.clear();
  54. histogram.resize(std::numeric_limits<channel_t>::max() + 1);
  55. for_each_pixel(color_converted_view<pixel_t>(srcview), [&](pixel_t const& p) {
  56. ++histogram[static_cast<std::size_t>(p)];
  57. });
  58. }
  59. /// \ingroup Histogram - STL Containers
  60. /// \brief Overload for std::array of fill_histogram
  61. ///
  62. template <typename SrcView, typename T, std::size_t N>
  63. void fill_histogram(SrcView const& srcview, std::array<T, N>& histogram, bool accumulate = false)
  64. {
  65. gil_function_requires<ImageViewConcept<SrcView>>();
  66. static_assert(std::is_arithmetic<T>::value && N > 0, "Improper container type for images.");
  67. static_assert(
  68. std::is_unsigned<typename channel_type<SrcView>::type>::value,
  69. "Improper container type for signed images.");
  70. using channel_t = typename channel_type<SrcView>::type;
  71. using pixel_t = pixel<channel_t, gray_layout_t>;
  72. const size_t pixel_max = std::numeric_limits<channel_t>::max();
  73. const float scale = (histogram.size() - 1.0f) / pixel_max;
  74. if (!accumulate)
  75. std::fill(std::begin(histogram), std::end(histogram), 0);
  76. for_each_pixel(color_converted_view<pixel_t>(srcview), [&](pixel_t const& p) {
  77. ++histogram[static_cast<std::size_t>(p * scale)];
  78. });
  79. }
  80. /// \ingroup Histogram - STL Containers
  81. /// \brief Overload for std::map of fill_histogram
  82. ///
  83. template <typename SrcView, typename T1, typename T2>
  84. void fill_histogram(SrcView const& srcview, std::map<T1, T2>& histogram, bool accumulate = false)
  85. {
  86. gil_function_requires<ImageViewConcept<SrcView>>();
  87. static_assert(
  88. std::is_arithmetic<T1>::value && std::is_integral<T2>::value,
  89. "Improper container type for images.");
  90. using channel_t = typename channel_type<SrcView>::type;
  91. using pixel_t = pixel<channel_t, gray_layout_t>;
  92. if (!accumulate)
  93. histogram.clear();
  94. for_each_pixel(color_converted_view<pixel_t>(srcview), [&](pixel_t const& p) {
  95. ++histogram[static_cast<std::size_t>(p)];
  96. });
  97. }
  98. /// \ingroup Histogram - STL Containers
  99. /// \brief Overload for std::vector of cumulative_histogram
  100. ///
  101. template <typename T>
  102. std::vector<T> cumulative_histogram(std::vector<T>& hist)
  103. {
  104. std::vector<T> cumulative_hist(hist.size());
  105. static_assert(std::is_arithmetic<T>::value, "Improper container type for images.");
  106. T cumulative_counter = 0;
  107. for (std::size_t i = 0; i < hist.size(); i++)
  108. {
  109. cumulative_counter += hist[i];
  110. cumulative_hist[i] = cumulative_counter;
  111. }
  112. return cumulative_hist;
  113. }
  114. /// \ingroup Histogram - STL Containers
  115. /// \brief Overload for std::array of cumulative_histogram
  116. ///
  117. template <typename T, std::size_t N>
  118. std::array<T, N> cumulative_histogram(std::array<T, N>& histogram)
  119. {
  120. std::array<T, N> cumulative_hist;
  121. static_assert(std::is_arithmetic<T>::value && N > 0, "Improper container type for images.");
  122. T cumulative_counter = 0;
  123. for (std::size_t i = 0; i < N; i++)
  124. {
  125. cumulative_counter += histogram[i];
  126. cumulative_hist[i] = cumulative_counter;
  127. }
  128. return cumulative_hist;
  129. }
  130. /// \ingroup Histogram - STL Containers
  131. /// \brief Overload for std::map of cumulative_histogram
  132. ///
  133. template <typename T1, typename T2>
  134. std::map<T1, T2> cumulative_histogram(std::map<T1, T2>& histogram)
  135. {
  136. std::map<T1, T2> cumulative_hist;
  137. static_assert(
  138. std::is_arithmetic<T1>::value && std::is_integral<T2>::value,
  139. "Improper container type for images.");
  140. T2 cumulative_counter = 0;
  141. for (auto const& it : histogram)
  142. {
  143. cumulative_counter += it.second;
  144. cumulative_hist[it.first] = cumulative_counter;
  145. }
  146. return cumulative_hist;
  147. }
  148. }} // namespace boost::gil
  149. #endif