123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- #ifndef BOOST_GIL_IMAGE_PROCESSING_HISTOGRAM_EQUALIZATION_HPP
- #define BOOST_GIL_IMAGE_PROCESSING_HISTOGRAM_EQUALIZATION_HPP
- #include <boost/gil/histogram.hpp>
- #include <boost/gil/image.hpp>
- #include <cmath>
- #include <map>
- #include <vector>
- namespace boost { namespace gil {
- template <typename SrcKeyType>
- auto histogram_equalization(histogram<SrcKeyType> const& src_hist)
- -> std::map<SrcKeyType, SrcKeyType>
- {
- histogram<SrcKeyType> dst_hist;
- return histogram_equalization(src_hist, dst_hist);
- }
- template <typename SrcKeyType, typename DstKeyType>
- auto histogram_equalization(histogram<SrcKeyType> const& src_hist, histogram<DstKeyType>& dst_hist)
- -> std::map<SrcKeyType, DstKeyType>
- {
- static_assert(
- std::is_integral<SrcKeyType>::value &&
- std::is_integral<DstKeyType>::value,
- "Source and destination histogram types are not appropriate");
- using value_t = typename histogram<SrcKeyType>::value_type;
- dst_hist.clear();
- double sum = src_hist.sum();
- SrcKeyType min_key = (std::numeric_limits<DstKeyType>::min)();
- SrcKeyType max_key = (std::numeric_limits<DstKeyType>::max)();
- auto cumltv_srchist = cumulative_histogram(src_hist);
- std::map<SrcKeyType, DstKeyType> color_map;
- std::for_each(cumltv_srchist.begin(), cumltv_srchist.end(), [&](value_t const& v) {
- DstKeyType trnsfrmd_key =
- static_cast<DstKeyType>((v.second * (max_key - min_key)) / sum + min_key);
- color_map[std::get<0>(v.first)] = trnsfrmd_key;
- });
- std::for_each(src_hist.begin(), src_hist.end(), [&](value_t const& v) {
- dst_hist[color_map[std::get<0>(v.first)]] += v.second;
- });
- return color_map;
- }
- template <typename SrcView, typename DstView>
- void histogram_equalization(
- SrcView const& src_view,
- DstView const& dst_view,
- std::size_t bin_width = 1,
- bool mask = false,
- std::vector<std::vector<bool>> src_mask = {})
- {
- gil_function_requires<ImageViewConcept<SrcView>>();
- gil_function_requires<MutableImageViewConcept<DstView>>();
- static_assert(
- color_spaces_are_compatible<
- typename color_space_type<SrcView>::type,
- typename color_space_type<DstView>::type>::value,
- "Source and destination views must have same color space");
-
- using source_channel_t = typename channel_type<SrcView>::type;
- using dst_channel_t = typename channel_type<DstView>::type;
- using coord_t = typename SrcView::x_coord_t;
- std::size_t const channels = num_channels<SrcView>::value;
- coord_t const width = src_view.width();
- coord_t const height = src_view.height();
- std::size_t pixel_max = (std::numeric_limits<dst_channel_t>::max)();
- std::size_t pixel_min = (std::numeric_limits<dst_channel_t>::min)();
- for (std::size_t i = 0; i < channels; i++)
- {
- histogram<source_channel_t> h;
- fill_histogram(nth_channel_view(src_view, i), h, bin_width, false, false, mask, src_mask);
- h.normalize();
- auto h2 = cumulative_histogram(h);
- for (std::ptrdiff_t src_y = 0; src_y < height; ++src_y)
- {
- auto src_it = nth_channel_view(src_view, i).row_begin(src_y);
- auto dst_it = nth_channel_view(dst_view, i).row_begin(src_y);
- for (std::ptrdiff_t src_x = 0; src_x < width; ++src_x)
- {
- if (mask && !src_mask[src_y][src_x])
- dst_it[src_x][0] = channel_convert<dst_channel_t>(src_it[src_x][0]);
- else
- dst_it[src_x][0] = static_cast<dst_channel_t>(
- h2[src_it[src_x][0]] * (pixel_max - pixel_min) + pixel_min);
- }
- }
- }
- }
- }}
- #endif
|