libcarla/include/system/boost/gil/extension/histogram/std.hpp
2024-10-18 13:19:59 +08:00

173 lines
5.8 KiB
C++

//
// Copyright 2020 Debabrata Mandal <mandaldebabrata123@gmail.com>
//
// 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