ヒストグラム伸張処理

詳解 画像処理プログラミング C言語で実装する画像処理アルゴリズムのすべて
で画像処理を勉強中。


これの2章に載ってたヒストグラム伸張処理を、OpenCV + Boostで書いてみました。

#include <iostream>
#include <utility>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/algorithm.hpp>
#include <boost/lambda/lambda.hpp>

namespace fusion = boost::fusion;

typedef fusion::vector<uchar, uchar, uchar> color_t;

template <class T>
boost::iterator_range<cv::MatIterator_<T> > mat_range(cv::Mat& mat)
{
    return boost::make_iterator_range(mat.begin<T>(), mat.end<T>());
}

template <class R>
std::pair<typename boost::range_value<R>::type, typename boost::range_value<R>::type>
    minmax_indirect_element(const R& r)
{
    auto result = std::minmax_element(boost::begin(r), boost::end(r));
    return std::make_pair(*result.first, *result.second);
}

int average(const color_t& pix)
{
    using namespace boost::lambda;
    return fusion::accumulate(pix, static_cast<uchar>(0), _1 + _2) / 3;
}

void histogram(color_t& pix, int min_, int max_)
{
    fusion::for_each(pix, [=](uchar& x) {
        x = (255 * (x - min_)) / (max_ - min_);
    });
}

int main()
{
    cv::Mat image = cv::imread("belle.jpg");
    if (image.empty()) {
        std::cout << "load error" << std::endl;
        return 1;
    }

    int min_, max_;
    boost::tie(min_, max_) =
        minmax_indirect_element(mat_range<color_t>(image) | boost::adaptors::transformed(average));

    boost::for_each(mat_range<color_t>(image),
        [=](color_t& pix) { return histogram(pix, min_, max_); } );

    cv::imwrite("out.png", image);
}

検証には、以下のサイトにある画像を使わせていただきました。

ヒストグラム伸張 - nsystem homepage


balle.jpg

out.png


若干変わった気がする。