[KinectWPF程序]将深度图像用彩色图像表示,其实就是深度值和像素值的简单转换
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;
namespace WpfApplication9
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
KinectSensor kinectSensor;
private const int LowDepthThreshold = 800;
private const int HighDepthThreshold = 3000;
private const int DepthDistanceOffset = HighDepthThreshold - LowDepthThreshold;
//BGR32图像,红色、绿色、蓝色分别对应的偏移(32位,4字节中的第几个)
private const int RedIndex = 2;
private const int GreenIndex = 1;
private const int BlueIndex = 0;
short[] DepthValueData;
//初始化Kinect直接调用InitKinect()即可;注册的同步事件为AllFramesReadyEventArgs
/// <summary>
/// 启动Kinect设备,初始化选项,并注册AllFrameReady同步事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void InitKinect()
{
if (KinectSensor.KinectSensors.Count > 0)
{
kinectSensor = (from sensor in KinectSensor.KinectSensors
where sensor.Status == KinectStatus.Connected
select sensor).FirstOrDefault();
kinectSensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
kinectSensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
kinectSensor.SkeletonStream.Enable();
kinectSensor.Start();
kinectSensor.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(kinectSensor_AllFramesReady);
}
else
{
MessageBox.Show("没有检测到Kinect设备");
}
}
/// <summary>
/// 单色直方图计算公式,返回256色灰阶。颜色越黑约远,约白则约近。
/// 将DepthDistanceOffset控制在0~255的范围内
/// </summary>
/// <param name="distance">深度值,有效范围LowDepthThreshold到HighDepthThreshold之间</param>
/// <returns>256色灰阶</returns>
private static byte CalculateIntensityFromDepth(int distance)
{
return (byte)(255 - (255 * Math.Max(distance - LowDepthThreshold, 0) / (HighDepthThreshold)));
}
/// <summary>
/// 将深度数据帧转换成彩色图像帧
/// </summary>
private byte[] convertDepthFrameToColorFrame(DepthImageFrame depthFrame)
{
//创建Height*Width*4的RGB数组(Red,Green,Blue,empty byte)
Byte[] pixels = new byte[depthFrame.Height * depthFrame.Width * 4];
//Bgr32 - Blue,Green,Red,empty byte;
//Bgra32 - Blue,Green,Red,transparency
//需要为Bgra32设置透明度transparency,.NET默认设置该字节为0(全透明)
for (int depthIndex = 0, colorIndex = 0; depthIndex < DepthValueData.Length && colorIndex < pixels.Length;
depthIndex++, colorIndex += 4)
{
//用户分割,0代表该像素不属于用户身体,低3位字节代表被跟踪的使用者的索引编号
int player = DepthValueData[depthIndex] & DepthImageFrame.PlayerIndexBitmask;
//获得深度数值,高13位字节。
int depth = DepthValueData[depthIndex] >> DepthImageFrame.PlayerIndexBitmaskWidth;
//0.8m内
if (depth <= 800)
{
//离Kinect很近
pixels[colorIndex + BlueIndex] = 255;
pixels[colorIndex + GreenIndex] = 0;
pixels[colorIndex + RedIndex] = 0;
}
else if (depth > 800 && depth < 2000)
{
pixels[colorIndex + BlueIndex] = 0;
pixels[colorIndex + GreenIndex] = 255;
pixels[colorIndex + RedIndex] = 0;
}
else if (depth > 2000)
{
pixels[colorIndex + BlueIndex] = 0;
pixels[colorIndex + GreenIndex] = 0;
pixels[colorIndex + RedIndex] = 255;
}
//直方图着色
byte intensity = CalculateIntensityFromDepth(depth);
pixels[colorIndex + BlueIndex] = intensity;
pixels[colorIndex + GreenIndex] = intensity;
pixels[colorIndex + RedIndex] = intensity;
//如果是人体区域,用亮绿色标注
if (player > 0)
{
pixels[colorIndex + BlueIndex] = Colors.LightGreen.B;
pixels[colorIndex + GreenIndex] = Colors.LightGreen.G;
pixels[colorIndex + RedIndex] = Colors.LightGreen.R;
}
}
return pixels;
}
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
InitKinect();
}
void kinectSensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
//获取深度图像
using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
{
if (depthFrame != null)
{
//建立存储深度值的矩阵,一维矩阵
//depthFrame.PixelDataLength每一帧的数据长度
DepthValueData = new short[depthFrame.PixelDataLength];
depthFrame.CopyPixelDataTo(DepthValueData);
//将Kicent获取的深度值拷贝存储像素的矩阵中
byte[] pixels = convertDepthFrameToColorFrame(depthFrame);
//创建BGR32格式的图片
ShowImage.Source = BitmapSource.Create(depthFrame.Width, depthFrame.Height, 96, 96, PixelFormats.Bgr32,
null, pixels, depthFrame.Width * 4);
}
}
}
}
}