読者です 読者をやめる 読者になる 読者になる

OpenCVのRGBの並びがイヤなので並び替える

画像処理

モノクロ変換
をちょっと書き換え。


boost::fusion::nviewでGBRをRGBに変換してしまいましょう。

#include <iostream>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <boost/range/algorithm.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/vector_tie.hpp>
#include <boost/fusion/include/algorithm.hpp>
#include <boost/fusion/include/nview.hpp>
#include <boost/mpl/vector_c.hpp>

namespace fusion = boost::fusion;

typedef fusion::vector<uchar, uchar, uchar> color_t;
typedef boost::mpl::vector_c<uchar, 2, 1, 0> rgb_indices;

template <class Seq>
typename fusion::nview<Seq, rgb_indices> rgb_order(Seq& seq)
{
    return fusion::nview<Seq, rgb_indices>(seq);
}

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>());
}

void monochrome(color_t& pix)
{
    uchar r, g, b;
    fusion::vector_tie(r, g, b) = rgb_order(pix);

    const float f = static_cast<float>(r) * 0.587f +
                    static_cast<float>(g) * 0.114f +
                    static_cast<float>(b) * 0.299f;

    fusion::for_each(pix, [=](uchar& x) {
        x = static_cast<uchar>(f);
    });
}

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

    boost::for_each(mat_range<color_t>(image), monochrome);

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

tieしてるとこがまだ微妙なので、もう一段関数をかませたほうがいいかもしれない。