今までずっとKINECT for Windows SDKでは、ビデオとデプス(ユーザー含む)の画像を重ねる時のズレは仕方ないと思っていました。
しかし、今日ヘルプを見ていたら、たまたまそれっぽいメソッドを発見したので試してみたら、ビデオとデプスの画像がきれいに重なりました。
やり方
全体のコードはこちらを見てもらうとして、肝心のところだけ解説しますI(わかりやすいように若干変えてます)。
// 距離座標をカメラ座標に変換する int videoX = 0, videoY = 0; runtime.NuiCamera.GetColorPixelCoordinatesFromDepthPixel( ImageResolution.Resolution640x480, new ImageViewArea(), x, y, 0, out videoX, out videoY ); int videoIndex = (videoX + (videoY * video.Image.Width)) * 4; videoIndex = Math.Min( videoIndex, video.Image.Bits.Length - 4 ); video.Image.Bits[videoIndex ] = Color.Red.B; video.Image.Bits[videoIndex + 1] = Color.Red.G; video.Image.Bits[videoIndex + 2] = Color.Red.R;
GetColorPixelCoordinatesFromDepthPixel
public void GetColorPixelCoordinatesFromDepthPixel ( ImageResolution colorResolution, // カメラの解像度(現在はResolution640x480のみサポート) ImageViewArea viewArea, // ズームなどの設定。特に指定しない場合は new ImageViewArea() でOK int depthX, // デプスのX位置 int depthY, // デプスのY位置 short depthValue, // デプスの値(特に指定しない場合は 0 でOK) out int videoX, // 指定したデプスのX位置に対応した、ビデオのX位置 out int videoY // 指定したデプスのY位置に対応した、ビデオのY位置
RuntimeクラスのCameraフィールドにGetColorPixelCoordinatesFromDepthPixelという長いメソッドがあります。
(たぶん)名前のとおり、デプスピクセルからカラーピクセルを取得する。というもので、引数は上記のとおりです。
ぐぐってみたら、KINECT for Windows SDKのウォークスルーに書いてあったんですね(docファイル)
ここで出力されたvideoX、およびvideoYをビデオストリームのインデックスに使用すると、ピッタリ座標を合わせることができました。
ただし、ビデオは640x480、デプスは320x240と小さいので、ベタ塗りのようにはならず、メッシュがかったようになります。工夫次第でなんとでもなりそうですが。