関数オブジェクト経由でのMat型のコピー

コード書いてて嵌ったのでメモ。
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]