// // Copyright 2020 Debabrata Mandal // // 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 #include #include #include #include #include #include #include #include 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 void fill_histogram(SrcView const& srcview, std::vector& histogram, bool accumulate = false) { gil_function_requires>(); static_assert(std::is_arithmetic::value, "Improper container type for images."); static_assert( std::is_unsigned::type>::value, "Improper container type for signed images."); using channel_t = typename channel_type::type; using pixel_t = pixel; if (!accumulate) histogram.clear(); histogram.resize(std::numeric_limits::max() + 1); for_each_pixel(color_converted_view(srcview), [&](pixel_t const& p) { ++histogram[static_cast(p)]; }); } /// \ingroup Histogram - STL Containers /// \brief Overload for std::array of fill_histogram /// template void fill_histogram(SrcView const& srcview, std::array& histogram, bool accumulate = false) { gil_function_requires>(); static_assert(std::is_arithmetic::value && N > 0, "Improper container type for images."); static_assert( std::is_unsigned::type>::value, "Improper container type for signed images."); using channel_t = typename channel_type::type; using pixel_t = pixel; const size_t pixel_max = std::numeric_limits::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(srcview), [&](pixel_t const& p) { ++histogram[static_cast(p * scale)]; }); } /// \ingroup Histogram - STL Containers /// \brief Overload for std::map of fill_histogram /// template void fill_histogram(SrcView const& srcview, std::map& histogram, bool accumulate = false) { gil_function_requires>(); static_assert( std::is_arithmetic::value && std::is_integral::value, "Improper container type for images."); using channel_t = typename channel_type::type; using pixel_t = pixel; if (!accumulate) histogram.clear(); for_each_pixel(color_converted_view(srcview), [&](pixel_t const& p) { ++histogram[static_cast(p)]; }); } /// \ingroup Histogram - STL Containers /// \brief Overload for std::vector of cumulative_histogram /// template std::vector cumulative_histogram(std::vector& hist) { std::vector cumulative_hist(hist.size()); static_assert(std::is_arithmetic::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 std::array cumulative_histogram(std::array& histogram) { std::array cumulative_hist; static_assert(std::is_arithmetic::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 std::map cumulative_histogram(std::map& histogram) { std::map cumulative_hist; static_assert( std::is_arithmetic::value && std::is_integral::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