123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- //
- // Copyright 2020 Debabrata Mandal <[email protected]>
- //
- // Distributed under the Boost Software License, Version 1.0
- // See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt
- //
- #ifndef BOOST_GIL_EXTENSION_HISTOGRAM_STL_HISTOGRAM_HPP
- #define BOOST_GIL_EXTENSION_HISTOGRAM_STL_HISTOGRAM_HPP
- #include <boost/gil/concepts/concept_check.hpp>
- #include <boost/gil/gray.hpp>
- #include <boost/gil/histogram.hpp>
- #include <boost/gil/image_view.hpp>
- #include <boost/gil/image_view_factory.hpp>
- #include <array>
- #include <map>
- #include <utility>
- #include <vector>
- namespace boost { namespace gil {
- //////////////////////////////////////////////////////////
- /// Histogram extension for STL container
- //////////////////////////////////////////////////////////
- /// \defgroup Histogram - STL Containers
- /// \brief Collection of functions to provide histogram support in GIL using Standard
- /// Template Library Containers
- /// The conversion from Boost.GIL images to compatible histograms are provided. The supported
- /// container types would be std::vector, std::array, std::map.
- ///
- /// Some general constraints on STL extension:-
- /// 1. Supports only 1D histogram.
- /// 2. Cannot use signed images with compatible random access containers.
- /// 3. Automatic resize of std::array in case of shortage of bins, to ensure
- /// correctness comes before performance.
- /// 4. Container key type (if exists) has to be one of std::integral types to be
- /// GIL compatible.
- /// 5. Container value type has to be of std::arithmetic types.
- ///
- ///
- /// \ingroup Histogram - STL Containers
- /// \brief Overload for std::vector of fill_histogram
- ///
- template <typename SrcView, typename T>
- void fill_histogram(SrcView const& srcview, std::vector<T>& histogram, bool accumulate = false)
- {
- gil_function_requires<ImageViewConcept<SrcView>>();
- static_assert(std::is_arithmetic<T>::value, "Improper container type for images.");
- static_assert(
- std::is_unsigned<typename channel_type<SrcView>::type>::value,
- "Improper container type for signed images.");
- using channel_t = typename channel_type<SrcView>::type;
- using pixel_t = pixel<channel_t, gray_layout_t>;
- if (!accumulate)
- histogram.clear();
- histogram.resize(std::numeric_limits<channel_t>::max() + 1);
- for_each_pixel(color_converted_view<pixel_t>(srcview), [&](pixel_t const& p) {
- ++histogram[static_cast<std::size_t>(p)];
- });
- }
- /// \ingroup Histogram - STL Containers
- /// \brief Overload for std::array of fill_histogram
- ///
- template <typename SrcView, typename T, std::size_t N>
- void fill_histogram(SrcView const& srcview, std::array<T, N>& histogram, bool accumulate = false)
- {
- gil_function_requires<ImageViewConcept<SrcView>>();
- static_assert(std::is_arithmetic<T>::value && N > 0, "Improper container type for images.");
- static_assert(
- std::is_unsigned<typename channel_type<SrcView>::type>::value,
- "Improper container type for signed images.");
- using channel_t = typename channel_type<SrcView>::type;
- using pixel_t = pixel<channel_t, gray_layout_t>;
- const size_t pixel_max = std::numeric_limits<channel_t>::max();
- const float scale = (histogram.size() - 1.0f) / pixel_max;
- if (!accumulate)
- std::fill(std::begin(histogram), std::end(histogram), 0);
- for_each_pixel(color_converted_view<pixel_t>(srcview), [&](pixel_t const& p) {
- ++histogram[static_cast<std::size_t>(p * scale)];
- });
- }
- /// \ingroup Histogram - STL Containers
- /// \brief Overload for std::map of fill_histogram
- ///
- template <typename SrcView, typename T1, typename T2>
- void fill_histogram(SrcView const& srcview, std::map<T1, T2>& histogram, bool accumulate = false)
- {
- gil_function_requires<ImageViewConcept<SrcView>>();
- static_assert(
- std::is_arithmetic<T1>::value && std::is_integral<T2>::value,
- "Improper container type for images.");
- using channel_t = typename channel_type<SrcView>::type;
- using pixel_t = pixel<channel_t, gray_layout_t>;
- if (!accumulate)
- histogram.clear();
- for_each_pixel(color_converted_view<pixel_t>(srcview), [&](pixel_t const& p) {
- ++histogram[static_cast<std::size_t>(p)];
- });
- }
- /// \ingroup Histogram - STL Containers
- /// \brief Overload for std::vector of cumulative_histogram
- ///
- template <typename T>
- std::vector<T> cumulative_histogram(std::vector<T>& hist)
- {
- std::vector<T> cumulative_hist(hist.size());
- static_assert(std::is_arithmetic<T>::value, "Improper container type for images.");
- T cumulative_counter = 0;
- for (std::size_t i = 0; i < hist.size(); i++)
- {
- cumulative_counter += hist[i];
- cumulative_hist[i] = cumulative_counter;
- }
- return cumulative_hist;
- }
- /// \ingroup Histogram - STL Containers
- /// \brief Overload for std::array of cumulative_histogram
- ///
- template <typename T, std::size_t N>
- std::array<T, N> cumulative_histogram(std::array<T, N>& histogram)
- {
- std::array<T, N> cumulative_hist;
- static_assert(std::is_arithmetic<T>::value && N > 0, "Improper container type for images.");
- T cumulative_counter = 0;
- for (std::size_t i = 0; i < N; i++)
- {
- cumulative_counter += histogram[i];
- cumulative_hist[i] = cumulative_counter;
- }
- return cumulative_hist;
- }
- /// \ingroup Histogram - STL Containers
- /// \brief Overload for std::map of cumulative_histogram
- ///
- template <typename T1, typename T2>
- std::map<T1, T2> cumulative_histogram(std::map<T1, T2>& histogram)
- {
- std::map<T1, T2> cumulative_hist;
- static_assert(
- std::is_arithmetic<T1>::value && std::is_integral<T2>::value,
- "Improper container type for images.");
- T2 cumulative_counter = 0;
- for (auto const& it : histogram)
- {
- cumulative_counter += it.second;
- cumulative_hist[it.first] = cumulative_counter;
- }
- return cumulative_hist;
- }
- }} // namespace boost::gil
- #endif
|