unsafeコードを利用してC++とC#の間で画像を伝達する

1844 ワード

http://blog.csdn.net/halfwet/article/details/7052897
実際の応用では,OpenCVなどのC++プラットフォームのライブラリで画像を収集し,C#に渡して描画する場合が多い.このとき,C++からC#への画像(配列)の伝達が重要な問題となる.ここでは実験した3つの方法を記録する.1.以前から画素毎のコピー方法を採用していた:C++で採集画像関数を定義する:
extern "C"  __declspec(dllexport) bool __stdcall  GetBGRMap(BYTE *bgrMap)
{
	bool result = capture->retrieve( bgrImage, CV_CAP_OPENNI_BGR_IMAGE ) ;
	for (int i=0;i<480;i++)
	{
		for (int j = 0;j<640;j++)
		{
			bgrMap[(i*640+j)*4+0] = bgrImage.data[(i*640+j)*3+0];
			bgrMap[(i*640+j)*4+1] = bgrImage.data[(i*640+j)*3+1];
			bgrMap[(i*640+j)*4+2] = bgrImage.data[(i*640+j)*3+2];
			bgrMap[(i*640+j)*4+3] = 255;
		}
	}
	return result;
}

C#の呼び出し方法は次のとおりです.
 [DllImport("OpencvKinectGrabber.dll", EntryPoint = "GetBGRMap")]
  public static extern bool GetBGRMap(byte[] data);
 
 BGRData = new byte[640 * 480 * 4];
 GetBGRMap(BGRData);

2.Marshalを利用してメモリコピーを行う方法もありますが、原理は上記の方法と一致するはずです.3.上記の2つの方法はいずれもメモリをコピーしてデータ伝達を行う必要がある.C#は管理ポインタを使用し、ポインタの直接操作は一般的に許されないため、上記の2つの方法は、C++で作成したメモリ領域からC#で作成したメモリ領域に画像データをコピーしなければならない.しかし、これにより、特に画像などの大量のデータに対して効率が低下する.このため、第3の方法はunsafeコードを用いてC#にC++で作成されたメモリ領域のポインタを直接取得する.
C++コードで画像のデータを直接返します.
EXTERN BYTE* __stdcall  GetBGRMap()
{
	bool result = capture->retrieve( bgrImage, CV_CAP_OPENNI_BGR_IMAGE ) ;
	imshow("shit",bgrImage);
	return (BYTE*)bgrImage.data;
}

C#の呼び出し方法は次のとおりです.
[DllImport("OpencvKinectGrabber.dll", EntryPoint = "GetBGRMap")]
public unsafe static extern byte*  GetBGRMap();

private unsafe void grabImg()
{
	byte* BGRData = GetBGRMap();
	//  unsafe    ,   c++          
	//      。。。
}

理論的には、3つ目の方法は、メモリをコピーする操作ではなく、C#にC++で作成されたポインタを直接使用しているため、最も効率的であるべきです.