Realsense でカメラを表示させる第一歩

RealSense 事始め | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/6751

事始めと言いつつ、コンテストも終わってそのままフェードアウトしてしまうのもアカンのです。手元のカメラは6か月ぐらい借りられる(らしい)ので、5月ぐらいまでは大丈夫なのかな。

Realsense はいくつかのサンプルが付いていますが、これが結構難しい。正月の頃にちら見はしていたのですが、ちょっとこれを使いこなすだけで「参加賞がもらえるのでは?」ってなぐらい難しいです。いや、私にとってはそうだった、というだけなのかもしれませんが、カメラの描画を OnPaint で表示させているところがもうなんとも、大変です。

へばりそうになったので、OpenCV 風に簡単にやってみました。

C#のWindowsフォームプロジェクトを作る

最終的には OpenCvSharp との組み合わせがしたかったので C# を使います。まあ、C++ でもいいんですが、ここは C# で(何かのはずみで F# も使えるかもしれないので)。

libpxcclr.cs.dll を参照設定する

C:Program Files (x86)IntelRSSDKbinx64libpxcclr.cs.dll を参照設定します。この中に諸々にライブラリが入っています。ちなみに、名前空間がありませんッ!!! 清い…

ビルドイベントを設定する

プロジェクトのプロパティからビルドイベントを開いて、ビルド後に実行するコマンドに以下を設定します。

if "$(Platform)" == "x86" ( copy /y "$(RSSDK_DIR)binwin32libpxccpp2c.dll" "$(TargetDir)" ) else ( copy /y "$(RSSDK_DIR)binx64libpxccpp2c.dll" "$(TargetDir)" )

c/c++ のライブラリのコピーですね。これは Realsense のサンプルから取ってきたもので、x86 もあるので 32bit版でも動きそうです。

ターゲットを「x64」にする

同じくプロジェクトのプロパティで、プラットフォームのターゲットを「x64」にします。

あまり高度なことはやらないので、「アンセーフコードの許可」は外したままでokです。

カメラを表示するだけのコード

これで準備が整ったので、RBGカメラを表示するだけのコードを書きます。

public partial class Form1 : Form
{
	public Form1()
	{
		InitializeComponent();
	}

	private PXCMSenseManager sm;
	Task _task;
	bool _task_flag = false;

	/// <summary>
	/// 撮影開始
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void button1_Click(object sender, EventArgs e)
	{
		sm = PXCMSenseManager.CreateInstance();
		// RGBの場合
		sm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_COLOR, 640, 480, 30);
		if (sm.Init() < pxcmStatus.PXCM_STATUS_NO_ERROR)
		{
			// エラー発生
			MessageBox.Show("PXCM_STATUS_NO_ERROR");
			return;
		}
			
		_task = new Task(() =>
		{
			_task_flag = true;
			while (_task_flag)
			{
				if (sm.AcquireFrame(true) < pxcmStatus.PXCM_STATUS_NO_ERROR) 
					return;
				PXCMCapture.Sample sample = sm.QuerySample();
				if (sample.color != null)
				{
					PXCMImage image = sample.color;
					PXCMImage.ImageData data;
					pxcmStatus sts = sample.color.AcquireAccess(PXCMImage.Access.ACCESS_READ, PXCMImage.PixelFormat.PIXEL_FORMAT_RGB32, out data);
					if (sts >= pxcmStatus.PXCM_STATUS_NO_ERROR)
					{
						Bitmap bmp = data.ToBitmap(0, image.info.width, image.info.height);
						image.ReleaseAccess(data);
						pictureBox1.Image = bmp;
					}
				}
				sm.ReleaseFrame();
				/// 30fps程度にあわせる
				Thread.Sleep(33);
			}
		});
		_task.Start();
	}

	/// <summary>
	/// 終了
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void button2_Click(object sender, EventArgs e)
	{
		_task_flag = false;
	}
}

詳しくはサンプルとリファレンスマニュアルを見ていけばいいのですが、なかなか単純な例が見つからないので、さらしておきます。

Intel RealSense SDK Documentation
https://software.intel.com/sites/landingpage/realsense/camera-sdk/2014gold/documentation/html/

別スレッドにしてぐるぐる回すほうが簡単なので、こっちを使っています。まあカメラの fps とずれるという欠点はありますが、結構なスピードで動いてくれるしコードが単純になります。

  1. PXCMSenseManager.CreateInstance() でカメラのインスタンスを作成
  2. sm.EnableStream() でキャプチャするカメラのサイズを決める。RGB と Depth は同時に撮影が可能。
  3. sm.QuerySample() で(たぶん)サンプリングして
  4. sample.color で RBG のデータを取り出す用意をして、
  5. sample.color.AcquireAccess で、PXCMImage 形式にコピーして
  6. data.ToBitmap で Bitmap 形式に直す
  7. pictureBox1.Image = bmp で、ピクチャボックスに貼り付け

という仕組みですね。

実行すると、こんな感じになります。

Bitmap 形式に直したら、そのまま OpenCvSharp を使って背景差分とか特徴量抽出とかができるので結構便利です。

サンプルコード

以下からどうぞ。
https://github.com/moonmile/RealsenseSample/tree/master/SimpleCamera

カテゴリー: 開発, C#, RealSense パーマリンク