File indexing completed on 2024-11-15 09:12:35
0001
0002
0003
0004
0005
0006
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
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
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
0052
0053
0054
0055
0056
0057
0058
0059
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
0089
0090
0091
0092
0093
0094
0095
0096
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
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 }}
0149
0150 #endif