『詳解 画像処理プログラミング 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); }
検証には、以下のサイトにある画像を使わせていただきました。
若干変わった気がする。