スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[Unity][Kinect]Unityで画像処理を行うときに実装しなければならないこと

そもそもUnityでKinect使うって、大抵の場合ボーン処理(プレイヤーの腕とかを取得する奴)ですよね。画像処理(カラー画像と深さ画像を併せて解析してあーだこーだ)とかやりませんよね。

でもやりたいと感じることもあるかも。
ただ解析を凡人のC#のハンドコードでやろうとすると、かなり重くなります。気に留めてください。Javascript?やめてください。
openCVを使うべきですが、また別の資料を解読する羽目になるので、ここでは触れません。


「Unity Kinect」とググるだけで、こんなUnityで使えるKinectSDKがヒットします。

ボーン取得に置いては十分(使ってないのでよく分からないけれども十分でしょう)ですし、カメラ画像も取得可能です。
カラーと深さのカメラ画像を取得して弄り倒せばできるんじゃない?と考えるでしょう。僕も考えました。


しかし、これだけでは画像処理ができない。このSDKには座標変換に関する関数が用意されていない
(2014/07/19時点。2015年現在は不明)から。
深さ画像を3次元座標に変換させたり、深さ画像をカラー画像に対応させるには、それを行う関数を追加させなければなりません。


「深さ画像を3次元座標に変換させたり、深さ画像をカラー画像に対応させる」を実現するためには、この2つの関数があれば十分でしょう。
NuiTransformDepthImageToSkeleton
深さ画像の座標から、実際の3次元座標空間に変換する
NuiImageGetColorPixelCoordinatesFromDepthPixel
深さ画像の座標に対応するカラー画像の座標を導出する

1つ目はC++のヘッダーファイルNuiSkeleton.hに、2つ目はKinect10.dllに用意されています。
各関数の詳細はMSDNを参照。後者についてはココのブログにざっくりメモガキが書いてあります。


この2つの関数をUnity上で実現するための方法を以下に記述します。

以下、追記文 ↓

2015/08/04 Kinect関連で訪問する方が多いので説明文修正


NuiTransformDepthImageToSkeletonの実装

NuiSkeleton.h(確かシステムフォルダの奥深く?)にこんな記述があります。
inline
Vector4
NuiTransformDepthImageToSkeleton(
_In_ LONG lDepthX,
_In_ LONG lDepthY,
_In_ USHORT usDepthValue,
_In_ NUI_IMAGE_RESOLUTION eResolution
)
{
DWORD width;
DWORD height;
NuiImageResolutionToSize( eResolution, width, height );

//
// Depth is in meters in skeleton space.
// The depth image pixel format has depth in millimeters shifted left by 3.
//

FLOAT fSkeletonZ = static_cast(usDepthValue >> 3) / 1000.0f;

//
// Center of depth sensor is at (0,0,0) in skeleton space, and
// and (width/2,height/2) in depth image coordinates. Note that positive Y
// is up in skeleton space and down in image coordinates.
//

FLOAT fSkeletonX = (lDepthX - width/2.0f) * (320.0f/width) * NUI_CAMERA_DEPTH_IMAGE_TO_SKELETON_MULTIPLIER_320x240 * fSkeletonZ;
FLOAT fSkeletonY = -(lDepthY - height/2.0f) * (240.0f/height) * NUI_CAMERA_DEPTH_IMAGE_TO_SKELETON_MULTIPLIER_320x240 * fSkeletonZ;

//
// Return the result as a vector.
//

Vector4 v4;
v4.x = fSkeletonX;
v4.y = fSkeletonY;
v4.z = fSkeletonZ;
v4.w = 1.0f;
return v4;
}


NUI_CAMERA_DEPTH_IMAGE_TO_SKELETON_MULTIPLIER_320x240 という定数が登場しますが、
NuiSkeleton.hによれば、
#define NUI_CAMERA_DEPTH_IMAGE_TO_SKELETON_MULTIPLIER_320x240 (NUI_CAMERA_DEPTH_NOMINAL_INVERSE_FOCAL_LENGTH_IN_PIXELS)

NuiImageCamera.hによれば、
#define NUI_CAMERA_DEPTH_NOMINAL_INVERSE_FOCAL_LENGTH_IN_PIXELS (3.501e-3f) // (1/NUI_CAMERA_DEPTH_NOMINAL_FOCAL_LENGTH_IN_PIXELS)


つまり、NUI_CAMERA_DEPTH_IMAGE_TO_SKELETON_MULTIPLIER_320x240 は (3.501e-3f) です。

これらの情報から、Unityに実装する関数は次のようにできるはずです。※若干変更を加えていますが。あ、C#です。

public Vector4 arranged_NuiTransformDepthImageToSkeleton(int lDepthX,int lDepthY,ushort usDepthValue,int width,int height){
float fSkeletonZ = (float)(usDepthValue) / 1000.0f;
float fSkeletonX = (lDepthX - width/2.0f) * (320.0f/width) * (3.501e-3f) * fSkeletonZ;
float fSkeletonY = -(lDepthY - height/2.0f) * (240.0f/height) * (3.501e-3f) * fSkeletonZ;
return new Vector4(fSkeletonX,fSkeletonY,fSkeletonZ,1.0f);
}


お好きなところに張り付けて、どうぞ。



NuiImageGetColorPixelCoordinatesFromDepthPixelの実装

C:\Windows\System32\Kinect10.dllにある関数なので、要はDLLImportです。
MSDNを参照しながら記述すれば普通はこう考えるはずです。(もちろんC#)


[DllImportAttribute(@"C:\Windows\System32\Kinect10.dll", EntryPoint = "NuiImageGetColorPixelCoordinatesFromDepthPixel")]
public static extern int NuiImageGetColorPixelCoordinatesFromDepthPixel (NuiImageResolution eColorResolution,ref NuiImageViewArea pcViewArea,long lDepthX,long lDepthY,ushort usDepthValue,ref longplColorX,ref longplColorY);

というのは不正解なので注意。pcViewAreaにはNULLを指定したいので、関数呼び出しに当てる型はIntPtrにしました。

また、C++でのlong型はC#ではint型に該当するそうです。とても引っかかりやすい所だとおもいます。(詳しい対応表は別サイトを参照してください。)

よって、正しい記述は、

[DllImportAttribute(@"C:\Windows\System32\Kinect10.dll", EntryPoint = "NuiImageGetColorPixelCoordinatesFromDepthPixel")]
public static extern int NuiImageGetColorPixelCoordinatesFromDepthPixel (NuiImageResolution eColorResolution,IntPtr pcViewArea,int lDepthX,int lDepthY,ushort usDepthValue,ref int plColorX,ref int plColorY);

実際に用いるときは、下記のようになります。NULLはSystem.IntPtr.Zeroと指定します。

// ※関数をNativeMethods空間に定義した例
NativeMethods.NuiImageGetColorPixelCoordinatesFromDepthPixel(NuiImageResolution.resolution640x480,System.IntPtr.Zero,(int)x,(int)y,(ushort)(0),ref px,ref py);





2015/08/04追記
良く考えたらこの記事、これらの関数を使用するサンプルコードを提示していませんでした。
そもそもKinectは学校でのグループ学習で触っていたものなので、現在kinectのコードは書けません。ごめんね!
2015/08/20修正
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

tag : Kinect Unity C#

コメントの投稿

非公開コメント

ブログ移転のお知らせ
ブログをshonen.hateblo.jpに移転します. 新規の記事はこちらに投稿します.
プロフィール

舞葉(ぶよう)

Author:舞葉(ぶよう)
github.io
はてなブログ(競プロ)

古い記事のソースコードは色分けしていないので、高機能テキストエディタに貼り付けたほうが見やすいかも。

検索フォーム
このブログについて
自分がつまづいた話題、なんとなく書きたいと思ったこと、ググったけど殆ど資料なかったぞオイ な話等をアップする予定。通りすがりでも、参考になっていただければと。プログラムの例外入力、メモリリークは責任負いません。投稿された記事は修正・削除する場合があります。
カテゴリ
タグ

HSP3アルゴリズムとデータ構造c++RubyJavaUnity画像解析C機械学習C#LinuxcodeIQKinectMinecraftTonyuSystemraspberrypiPythonHTML5音声制御Simulinkruby俺ルール通信制御Javascriptシミュレーション

counter-shinobi
固定記事
最新記事
最新コメント
月別アーカイブ
ブロとも申請フォーム

この人とブロともになる

アクセスランキング
[ジャンルランキング]
コンピュータ
995位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
199位
アクセスランキングを見る>>
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。