173 lines
5.8 KiB
C++
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
|