Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:12:35

0001 //
0002 // Copyright 2020 Debabrata Mandal <mandaldebabrata123@gmail.com>
0003 //
0004 // Use, modification and distribution are subject to the Boost Software License,
0005 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 #ifndef BOOST_GIL_IMAGE_PROCESSING_HISTOGRAM_EQUALIZATION_HPP
0009 #define BOOST_GIL_IMAGE_PROCESSING_HISTOGRAM_EQUALIZATION_HPP
0010 
0011 #include <boost/gil/histogram.hpp>
0012 #include <boost/gil/image.hpp>
0013 
0014 #include <cmath>
0015 #include <map>
0016 #include <vector>
0017 
0018 namespace boost { namespace gil {
0019 
0020 /////////////////////////////////////////
0021 /// Histogram Equalization(HE)
0022 /////////////////////////////////////////
0023 /// \defgroup HE HE
0024 /// \brief Contains implementation and description of the algorithm used to compute
0025 ///        global histogram equalization of input images.
0026 ///
0027 ///        Algorithm :-
0028 ///        1. If histogram A is to be equalized compute the cumulative histogram of A.
0029 ///        2. Let CFD(A) refer to the cumulative histogram of A
0030 ///        3. For a uniform histogram A', CDF(A') = A'
0031 ///        4. We need to transfrom A to A' such that
0032 ///        5. CDF(A') = CDF(A) => A' = CDF(A)
0033 ///        6. Hence the pixel transform , px => histogram_of_ith_channel[px].
0034 ///
0035 
0036 /// \fn histogram_equalization
0037 /// \ingroup HE
0038 /// \tparam SrcKeyType Key Type of input histogram
0039 /// @param src_hist INPUT Input source histogram
0040 /// \brief Overload for histogram equalization algorithm, takes in a single source histogram
0041 ///        and returns the color map used for histogram equalization.
0042 ///
0043 template <typename SrcKeyType>
0044 auto histogram_equalization(histogram<SrcKeyType> const& src_hist)
0045     -> std::map<SrcKeyType, SrcKeyType>
0046 {
0047     histogram<SrcKeyType> dst_hist;
0048     return histogram_equalization(src_hist, dst_hist);
0049 }
0050 
0051 /// \overload histogram_equalization
0052 /// \ingroup HE
0053 /// \tparam SrcKeyType Key Type of input histogram
0054 /// \tparam DstKeyType Key Type of output histogram
0055 /// @param src_hist INPUT source histogram
0056 /// @param dst_hist OUTPUT Output histogram
0057 /// \brief Overload for histogram equalization algorithm, takes in both source histogram &
0058 ///        destination histogram and returns the color map used for histogram equalization
0059 ///        as well as transforming the destination histogram.
0060 ///
0061 template <typename SrcKeyType, typename DstKeyType>
0062 auto histogram_equalization(histogram<SrcKeyType> const& src_hist, histogram<DstKeyType>& dst_hist)
0063     -> std::map<SrcKeyType, DstKeyType>
0064 {
0065     static_assert(
0066         std::is_integral<SrcKeyType>::value &&
0067         std::is_integral<DstKeyType>::value,
0068         "Source and destination histogram types are not appropriate");
0069 
0070     using value_t = typename histogram<SrcKeyType>::value_type;
0071     dst_hist.clear();
0072     double sum          = src_hist.sum();
0073     SrcKeyType min_key  = std::numeric_limits<DstKeyType>::min();
0074     SrcKeyType max_key  = std::numeric_limits<DstKeyType>::max();
0075     auto cumltv_srchist = cumulative_histogram(src_hist);
0076     std::map<SrcKeyType, DstKeyType> color_map;
0077     std::for_each(cumltv_srchist.begin(), cumltv_srchist.end(), [&](value_t const& v) {
0078         DstKeyType trnsfrmd_key =
0079             static_cast<DstKeyType>((v.second * (max_key - min_key)) / sum + min_key);
0080         color_map[std::get<0>(v.first)] = trnsfrmd_key;
0081     });
0082     std::for_each(src_hist.begin(), src_hist.end(), [&](value_t const& v) {
0083         dst_hist[color_map[std::get<0>(v.first)]] += v.second;
0084     });
0085     return color_map;
0086 }
0087 
0088 /// \overload histogram_equalization
0089 /// \ingroup HE
0090 /// @param src_view  INPUT source image view
0091 /// @param dst_view  OUTPUT Output image view
0092 /// @param bin_width INPUT Histogram bin width
0093 /// @param mask      INPUT Specify is mask is to be used
0094 /// @param src_mask  INPUT Mask vector over input image
0095 /// \brief Overload for histogram equalization algorithm, takes in both source & destination
0096 ///        image views and histogram equalizes the input image.
0097 ///
0098 template <typename SrcView, typename DstView>
0099 void histogram_equalization(
0100     SrcView const& src_view,
0101     DstView const& dst_view,
0102     std::size_t bin_width = 1,
0103     bool mask = false,
0104     std::vector<std::vector<bool>> src_mask = {})
0105 {
0106     gil_function_requires<ImageViewConcept<SrcView>>();
0107     gil_function_requires<MutableImageViewConcept<DstView>>();
0108 
0109     static_assert(
0110         color_spaces_are_compatible<
0111             typename color_space_type<SrcView>::type,
0112             typename color_space_type<DstView>::type>::value,
0113         "Source and destination views must have same color space");
0114 
0115     // Defining channel type
0116     using source_channel_t = typename channel_type<SrcView>::type;
0117     using dst_channel_t    = typename channel_type<DstView>::type;
0118     using coord_t          = typename SrcView::x_coord_t;
0119 
0120     std::size_t const channels = num_channels<SrcView>::value;
0121     coord_t const width        = src_view.width();
0122     coord_t const height       = src_view.height();
0123     std::size_t pixel_max      = std::numeric_limits<dst_channel_t>::max();
0124     std::size_t pixel_min      = std::numeric_limits<dst_channel_t>::min();
0125 
0126     for (std::size_t i = 0; i < channels; i++)
0127     {
0128         histogram<source_channel_t> h;
0129         fill_histogram(nth_channel_view(src_view, i), h, bin_width, false, false, mask, src_mask);
0130         h.normalize();
0131         auto h2 = cumulative_histogram(h);
0132         for (std::ptrdiff_t src_y = 0; src_y < height; ++src_y)
0133         {
0134             auto src_it = nth_channel_view(src_view, i).row_begin(src_y);
0135             auto dst_it = nth_channel_view(dst_view, i).row_begin(src_y);
0136             for (std::ptrdiff_t src_x = 0; src_x < width; ++src_x)
0137             {
0138                 if (mask && !src_mask[src_y][src_x])
0139                     dst_it[src_x][0] = channel_convert<dst_channel_t>(src_it[src_x][0]);
0140                 else
0141                     dst_it[src_x][0] = static_cast<dst_channel_t>(
0142                         h2[src_it[src_x][0]] * (pixel_max - pixel_min) + pixel_min);
0143             }
0144         }
0145     }
0146 }
0147 
0148 }}  //namespace boost::gil
0149 
0150 #endif