RGBカメラのデータは色情報ですので、ほぼそのまま画像データとして利用できますが、Depthカメラのデータは距離データ+αなのでそれを画像データに変換することが必要になります。
MainWindow.xaml
------------------------------------------------------------------------------
<Window x:Class="KinectDepthforSDK15.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="520" Width="700">
<Grid>
<Image Name="Depth" Stretch="Uniform" Height="480" Width="640" />
</Grid>
</Window>
------------------------------------------------------------------------------
RGBカメラの時と同様にイメージコントロールを一つ配置しています。
MainWindow.xaml.cs
------------------------------------------------------------------------------
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Microsoft.Kinect;
namespace KinectDepthforSDK15
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
KinectSensor kinect;
public MainWindow()
{
InitializeComponent();
//接続の確認
if (KinectSensor.KinectSensors.Count == 0)
{
MessageBox.Show("KINECTが見つかりません。");
Close();
}
kinect = KinectSensor.KinectSensors[0];
//Depthカメラの設定
kinect.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
//イベントの登録
kinect.DepthFrameReady += new EventHandler<DepthImageFrameReadyEventArgs>(kinect_DepthFrameReady);
//KINECTのスタート
kinect.Start();
}
void kinect_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
{
using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
{
if (depthFrame != null)
{
//Depthカメラの深度データ
short[] depthPixel = new short[depthFrame.PixelDataLength];
depthFrame.CopyPixelDataTo(depthPixel);
//表示用画像データ配列(画像データは4チャンネル必要なので要素数は4倍になる)
byte[] colorPixel = new byte[depthFrame.Width*depthFrame.Height * 4];
//距離データから画像を生成するループ
int j = 0;
for (int i = 0; i < depthPixel.Length; i++)
{
//距離データの取り出し
short depth = (short)( depthPixel[i] >> DepthImageFrame.PlayerIndexBitmaskWidth);
//画素データに変換(距離データのうち下位1バイトで表現している)
//SDKのDepthサンプルを参考
byte dist = (byte)((depth + 1) & byte.MaxValue); //byte.MaxValue=255
//距離データ(0-4095)を100分率で表現するなら次の式で
//byte dist = (byte)(255 - (255 * depth / 4095));
//距離データ 13ビットを4ビットシフトしてから8ビット分だけ取り出す場合
//byte dist = (byte)(depth + 1 >> 4 & byte.MaxValue);
//RGBイメージ配列に書込み
colorPixel[j] = dist;
colorPixel[j + 1] = dist;
colorPixel[j + 2] = dist;
j += 4;
}
//イメージコントロールに設定
Depth.Source = BitmapSource.Create(depthFrame.Width, depthFrame.Height, 96, 96, PixelFormats.Bgr32, null, colorPixel, depthFrame.Width * 4);
}
}
}
}
}
------------------------------------------------------------------------------
プログラムの前半はRGBカメラの時とほとんど変わりません。
Depthカメラからのデータは1ピクセルあたり2バイト(16ビット)になりますのでshort型配列に取り込みます。
表示用のイメージデータはBGR32タイプになるので画像サイズ(640*480)の4倍必要になります。
距離データは16ビット中上位13ビットで標準モードの場合0-4095(mm)の距離を表します。残り3ビットは認識しているプレイヤーのIDが入るのですが、今回は骨格認識を有効にしていないので利用できません。
「depthPixel[i] >> DepthImageFrame.PlayerIndexBitmaskWidth」で3ビット右にシフトして距離データを取り出しています。
距離データは0-4095の値になるのでこれを0-255(画素データは8ビット)に収まるようにすれば距離に応じたイメージデータを得ることができます。
SDKのサンプルでは取り出した距離データに1を足して(計測できない距離データが-1になるのでそれを補正しているのだと思います。)から下位8ビットデータを取り出して画素データとしています。
ほかにもいろいろ表現の仕方はあると思います。
得られた画像を見てみると人物などに影ができていますが、これはDepthカメラの仕様(赤外線を利用している)でどうしてもできてしまうようです。
0 件のコメント:
コメントを投稿