KinectSDK 正式版(一)图像、景深数据获取。

      上篇描述了一下Kinect for windows SDK的正式版的一部分提升,这篇主要来介绍一下正式版的SDK的图像方面的功能,以及部分强大的API支持。

      第一步:创建了一个WPF程序,并将Microsoft.Kinect添加入引用。

     第二步:然后在页面上简单的拖拽了两个按钮一个下拉列表。这里的两个按钮分别是启动程序和获取现在机器上的Kinect设备,而下拉列表中用来显示获取到的Kinect的名字。如上篇博客中介绍的一样目前Kinectfor windows支持四个Kinect同时连接到电脑上并接受信号进行分析。所以这里准备了一个下拉列表来获取所有连接的Kinect的设备。

MainWindow.xaml文件中添加了代码:

<Button Content="获取Kinect" Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />

<ComboBox Height="23" HorizontalAlignment="Left" Margin="93,12,0,0" Name="comboBox1" VerticalAlignment="Top" Width="120" />

<Button Content="启动" Height="23" HorizontalAlignment="Left" Margin="416,12,0,0" Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click" />

后置文件中添加了代码:

private void button1_Click(object sender, RoutedEventArgs e)

{

KinectSensorCollection ksc = KinectSensor.KinectSensors;

foreach (var item in ksc)

{

this.comboBox1.Items.Add(item.UniqueKinectId);

}

}

private void button2_Click(object sender, RoutedEventArgs e)

{

KinectSensor ks = KinectSensor.KinectSensors[this.comboBox1.SelectedIndex];

ks.Start();

}

运行一下,点击获取kinect按钮后的效果如图:

第三步,加入两个图片控件,一个用来显示颜色图像,一个用来显示景深图像。

MainWindow.xaml文件中添加了代码:

<Image Height="150" HorizontalAlignment="Left" Margin="13,41,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="200" />
<Image Height="150" HorizontalAlignment="Left" Margin="291,41,0,0" Name="image2" Stretch="Fill" VerticalAlignment="Top" Width="200" />

并修改了启动按钮的点击事件:

private void button2_Click(object sender, RoutedEventArgs e)
{
    KinectSensor ks = KinectSensor.KinectSensors[this.comboBox1.SelectedIndex];
    //添加颜色图像获取事件
    ks.ColorFrameReady += new EventHandler<ColorImageFrameReadyEventArgs>(ks_ColorFrameReady);
    //设置启动模式,ColorImageFormat枚举中包含5个值
    ks.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
    //添加景深图像获取事件
    ks.DepthFrameReady += new EventHandler<DepthImageFrameReadyEventArgs>(ks_DepthFrameReady);
    //设置启动模式,DepthImageFormat枚举中包含4个值
    ks.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
    ks.Start();
}
颜色图像获取事件为:
void ks_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
    ColorImageFrame cif = e.OpenColorImageFrame();
    if (cif != null)
    {
        //准备装图像数据的数组
        byte[] imagesource = new byte[cif.PixelDataLength];
        //获取图像数据
        cif.CopyPixelDataTo(imagesource);
        //转换后放到控件上
        image1.Source = BitmapSource.Create(cif.Width, cif.Height, 96, 96, PixelFormats.Bgr32, null, imagesource, cif.Width * cif.BytesPerPixel);
    }
}

景深图像获取事件为:

void ks_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
{
    DepthImageFrame dif = e.OpenDepthImageFrame();
    if (dif != null)
    {
        //准备装图像数据的数组
        short[] imagesourceS = new short[dif.PixelDataLength];
        dif.CopyPixelDataTo(imagesourceS);
        int length=dif.Width * dif.Height * ((PixelFormats.Bgr32.BitsPerPixel + 7) / 8);
        byte[] imagesourceB = new byte[length];
        //景深数据转换成byte
        imagesourceB = this.ConvertDepthFrame(imagesourceS, ((KinectSensor)sender).DepthStream, imagesourceB, length);

        //生成图片放到控件上
        WriteableBitmap outputBitmap = new WriteableBitmap(dif.Width,dif.Height,96,96,PixelFormats.Bgr32,null);

        this.image2.Source = outputBitmap;

        outputBitmap.WritePixels(new Int32Rect(0, 0, dif.Width, dif.Height),imagesourceB,dif.Width * ((PixelFormats.Bgr32.BitsPerPixel + 7) / 8),0);              
    }
}

景深图像转换方法:

private byte[] ConvertDepthFrame(short[] depthFrame, DepthImageStream depthStream, byte[] depthFrame32, int length)
{
        int RedIndex = 2;
        int GreenIndex = 1;
        int BlueIndex = 0;

        int[] IntensityShiftByPlayerR = { 1, 2, 0, 2, 0, 0, 2, 0 };
        int[] IntensityShiftByPlayerG = { 1, 2, 2, 0, 2, 0, 0, 1 };
        int[] IntensityShiftByPlayerB = { 1, 0, 2, 2, 0, 2, 0, 2 };

        int tooNearDepth = depthStream.TooNearDepth;
        int tooFarDepth = depthStream.TooFarDepth;
        int unknownDepth = depthStream.UnknownDepth;

        for (int i16 = 0, i32 = 0; i16 < depthFrame.Length && i32 < length; i16++, i32 += 4)
        {
            int player = depthFrame[i16] & DepthImageFrame.PlayerIndexBitmask;
            int realDepth = depthFrame[i16] >> DepthImageFrame.PlayerIndexBitmaskWidth;
            byte intensity = (byte)(~(realDepth >> 4));

            if (player == 0 && realDepth == 0)
            {
                depthFrame32[i32 + RedIndex] = 255;
                depthFrame32[i32 + GreenIndex] = 255;
                depthFrame32[i32 + BlueIndex] = 255;
            }
            else if (player == 0 && realDepth == tooFarDepth)
            {
                depthFrame32[i32 + RedIndex] = 66;
                depthFrame32[i32 + GreenIndex] = 0;
                depthFrame32[i32 + BlueIndex] = 66;
            }
            else if (player == 0 && realDepth == unknownDepth)
            {
                depthFrame32[i32 + RedIndex] = 66;
                depthFrame32[i32 + GreenIndex] = 66;
                depthFrame32[i32 + BlueIndex] = 33;
            }
            else
            {
                depthFrame32[i32 + RedIndex] = (byte)(intensity >> IntensityShiftByPlayerR[player]);
                depthFrame32[i32 + GreenIndex] = (byte)(intensity >> IntensityShiftByPlayerG[player]);
                depthFrame32[i32 + BlueIndex] = (byte)(intensity >> IntensityShiftByPlayerB[player]);
            }
        }
        return depthFrame32;
}

运行效果如图:



 哈哈,有趣的是出现了六指,也许在光线不好的位置kinect的景深数据还是有些出入的,光线良好的位置数据准确度是很高的。

OK了,现在本篇要介绍的部分已经完成了,如果阅读后发现什么问题可以留言,或者发送邮件到:57512434@qq.com,看到后会第一时间回复的。

以上是颜色获取以及景深数据获取的代码,希望能给大家些帮助,这篇就先到这里,对了多补充一下,截图来看下刚刚项目的output :

这是因为示例使用的kinect是 xbox用的,不是专门的kinect for windows设备,所以会有这个提示。

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值