コード書いてて嵌ったのでメモ。
cv::Mat型のデータを関数オブジェクト経由でコピーしようとしたら上手くいかなかった。
環境はVC10。
1.関数オブジェクト経由での値の代入
#include <iostream> #include <functional> void func(const int src, int& dst) {dst = src;} int main( void ) { int data = 0; std::function<void (int)> f = std::bind( func, std::placeholders::_1, data ); f( 5 ); std::cout << data << std::endl; return 0; }
出力結果
0
dataに5が代入されることを期待してたんですが、うまくいきません。
そんなときは、std::refを使うことで解決します。
std::function<void (int)> f = std::bind( func, std::placeholders::_1, std::ref(data) );
出力結果
5
2.関数オブジェクト経由でのOpenCVのMat型データのコピー
#include <iostream> #include <functional> #include <opencv2/core/core.hpp> int main( void ) { cv::Mat data; std::function<void (const cv::Mat&)> f = std::bind( &cv::Mat::copyTo, std::placeholders::_1, data); f( cv::Mat::eye(3,3,CV_8U) ); std::cout << data << std::endl; return 0; }
出力結果
[]
ここまでは、1と同じ。
ただし、std::refを使って解決しようとするとコンパイルエラー。
std::function<void (const cv::Mat&)> f = std::bind( &cv::Mat::copyTo, std::placeholders::_1, std::ref(data));
error C2664: 'void (cv::OutputArray) const' : 1 番目の引数を 'std::tr1::reference_wrapper<_Ty>' から 'cv::OutputArray' に変換できません。
std::refを経由するとMatとOutputArrayの型変換が失敗するみたい。
解決策1
ラムダ式を使用。
std::function<void (const cv::Mat&)> f = [&](const cv::Mat& src){src.copyTo(data);};
出力結果
[1, 0, 0; 0, 1, 0; 0, 0, 1]
解決策2
ポインタ使用。あまりスマートじゃないかな。
#include <iostream> #include <functional> #include <opencv2/core/core.hpp> void copy( const cv::Mat& src, cv::Mat* dst ) {src.copyTo(*dst);} int main( void ) { cv::Mat data; std::function<void (const cv::Mat&)> f = std::bind( copy, std::placeholders::_1, &data); f( cv::Mat::eye(3,3,CV_8U) ); std::cout << data << std::endl; return 0; }
出力結果
[1, 0, 0; 0, 1, 0; 0, 0, 1]