Boost GIL


histogram_equalization.hpp
1 //
2 // Copyright 2020 Debabrata Mandal <mandaldebabrata123@gmail.com>
3 //
4 // Use, modification and distribution are subject to the Boost Software License,
5 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 #ifndef BOOST_GIL_IMAGE_PROCESSING_HISTOGRAM_EQUALIZATION_HPP
9 #define BOOST_GIL_IMAGE_PROCESSING_HISTOGRAM_EQUALIZATION_HPP
10 
11 #include <boost/gil/histogram.hpp>
12 #include <boost/gil/image.hpp>
13 
14 #include <cmath>
15 #include <map>
16 #include <vector>
17 
18 namespace boost { namespace gil {
19 
35 
43 template <typename SrcKeyType>
44 auto histogram_equalization(histogram<SrcKeyType> const& src_hist)
45  -> std::map<SrcKeyType, SrcKeyType>
46 {
47  histogram<SrcKeyType> dst_hist;
48  return histogram_equalization(src_hist, dst_hist);
49 }
50 
61 template <typename SrcKeyType, typename DstKeyType>
62 auto histogram_equalization(histogram<SrcKeyType> const& src_hist, histogram<DstKeyType>& dst_hist)
63  -> std::map<SrcKeyType, DstKeyType>
64 {
65  static_assert(
66  std::is_integral<SrcKeyType>::value &&
67  std::is_integral<DstKeyType>::value,
68  "Source and destination histogram types are not appropriate");
69 
70  using value_t = typename histogram<SrcKeyType>::value_type;
71  dst_hist.clear();
72  double sum = src_hist.sum();
73  SrcKeyType min_key = (std::numeric_limits<DstKeyType>::min)();
74  SrcKeyType max_key = (std::numeric_limits<DstKeyType>::max)();
75  auto cumltv_srchist = cumulative_histogram(src_hist);
76  std::map<SrcKeyType, DstKeyType> color_map;
77  std::for_each(cumltv_srchist.begin(), cumltv_srchist.end(), [&](value_t const& v) {
78  DstKeyType trnsfrmd_key =
79  static_cast<DstKeyType>((v.second * (max_key - min_key)) / sum + min_key);
80  color_map[std::get<0>(v.first)] = trnsfrmd_key;
81  });
82  std::for_each(src_hist.begin(), src_hist.end(), [&](value_t const& v) {
83  dst_hist[color_map[std::get<0>(v.first)]] += v.second;
84  });
85  return color_map;
86 }
87 
98 template <typename SrcView, typename DstView>
99 void histogram_equalization(
100  SrcView const& src_view,
101  DstView const& dst_view,
102  std::size_t bin_width = 1,
103  bool mask = false,
104  std::vector<std::vector<bool>> src_mask = {})
105 {
106  gil_function_requires<ImageViewConcept<SrcView>>();
107  gil_function_requires<MutableImageViewConcept<DstView>>();
108 
109  static_assert(
110  color_spaces_are_compatible<
111  typename color_space_type<SrcView>::type,
112  typename color_space_type<DstView>::type>::value,
113  "Source and destination views must have same color space");
114 
115  // Defining channel type
116  using source_channel_t = typename channel_type<SrcView>::type;
117  using dst_channel_t = typename channel_type<DstView>::type;
118  using coord_t = typename SrcView::x_coord_t;
119 
120  std::size_t const channels = num_channels<SrcView>::value;
121  coord_t const width = src_view.width();
122  coord_t const height = src_view.height();
123  std::size_t pixel_max = (std::numeric_limits<dst_channel_t>::max)();
124  std::size_t pixel_min = (std::numeric_limits<dst_channel_t>::min)();
125 
126  for (std::size_t i = 0; i < channels; i++)
127  {
128  histogram<source_channel_t> h;
129  fill_histogram(nth_channel_view(src_view, i), h, bin_width, false, false, mask, src_mask);
130  h.normalize();
131  auto h2 = cumulative_histogram(h);
132  for (std::ptrdiff_t src_y = 0; src_y < height; ++src_y)
133  {
134  auto src_it = nth_channel_view(src_view, i).row_begin(src_y);
135  auto dst_it = nth_channel_view(dst_view, i).row_begin(src_y);
136  for (std::ptrdiff_t src_x = 0; src_x < width; ++src_x)
137  {
138  if (mask && !src_mask[src_y][src_x])
139  dst_it[src_x][0] = channel_convert<dst_channel_t>(src_it[src_x][0]);
140  else
141  dst_it[src_x][0] = static_cast<dst_channel_t>(
142  h2[src_it[src_x][0]] * (pixel_max - pixel_min) + pixel_min);
143  }
144  }
145  }
146 }
147 
148 }} //namespace boost::gil
149 
150 #endif
defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
Definition: algorithm.hpp:36