Kinect学习笔记第五篇InfraredFrame
C#
简述:
从Kinect获得的红外红外数据也是一个16位无符号整数,这个整数直接代表了这个点的灰度值。
如果和一代一样的话,这16位只有高10位是有效的,10位灰度,只有高级显示器才能显示,
我们这一般的显示只能显示256级即8位灰度,所以我们应该舍弃其中2位。据他人博客,舍弃最低2位貌似较好。
红外意义不明?他保证了Kinect没灯光也可以使用!!
处理中唯一特殊的是,将灰度调解。
16位Unshort类型转换为0.01-1.00(亮度范围?),然后缩小合适倍数(可自己定),又要保证不要越过1。
InfraredFrame显示代码:(C#)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 myInfraedFrameViewer
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private const float InfraredSourceValueMaximum = (float)ushort.MaxValue;//红外可返回的最大数
private const float InfraredSourceScale = 0.75f;//红外返回值将被缩小
private const float InfraredOutputValueMinimum = 0.01f;//正常的红外显示值的最小数
private const float InfraredOutputValueMaximum = 1.0f;
private KinectSensor kinectSensor = null;
private InfraredFrameReader infraredFrameReader = null;
private FrameDescription infraredFrameDescription = null;
private WriteableBitmap infraredBitmap = null;
public MainWindow()
{
this.kinectSensor = KinectSensor.GetDefault();
this.infraredFrameReader = this.kinectSensor.InfraredFrameSource.OpenReader();
this.infraredFrameReader.FrameArrived += this.Reader_InfraredFrameArrived;
this.infraredFrameDescription = this.kinectSensor.InfraredFrameSource.FrameDescription;
this.infraredBitmap = new WriteableBitmap(this.infraredFrameDescription.Width, this.infraredFrameDescription.Height, 96.0, 96.0, PixelFormats.Gray32Float, null);
this.kinectSensor.Open();
this.DataContext = this;
InitializeComponent();
}
private void Reader_InfraredFrameArrived(object sender, InfraredFrameArrivedEventArgs e)
{
// InfraredFrame is IDisposable
using (InfraredFrame infraredFrame = e.FrameReference.AcquireFrame())
{
if (infraredFrame != null)
{
//操纵数据最快的是直接访问内存
using (Microsoft.Kinect.KinectBuffer infraredBuffer = infraredFrame.LockImageBuffer())
{
// 验证+更新
if (((this.infraredFrameDescription.Width * this.infraredFrameDescription.Height) == (infraredBuffer.Size / this.infraredFrameDescription.BytesPerPixel)) &&
(this.infraredFrameDescription.Width == this.infraredBitmap.PixelWidth) && (this.infraredFrameDescription.Height == this.infraredBitmap.PixelHeight))
{
this.ProcessInfraredFrameData(infraredBuffer.UnderlyingBuffer, infraredBuffer.Size);
}
}
}
}
}
private unsafe void ProcessInfraredFrameData(IntPtr infraredFrameData, uint infraredFrameDataSize)
{
// infrared frame data is a 16 bit value
ushort* frameData = (ushort*)infraredFrameData;
// Lock保证单线程访问
this.infraredBitmap.Lock();
// get the pointer to the bitmap's back buffer
float* backBuffer = (float*)this.infraredBitmap.BackBuffer;
// process the infrared data
for (int i = 0; i < (int)(infraredFrameDataSize / this.infraredFrameDescription.BytesPerPixel); ++i)
{
// since we are displaying the image as a normalized grey scale image, we need to convert from
// the ushort data (as provided by the InfraredFrame) to a value from [InfraredOutputValueMinimum, InfraredOutputValueMaximum]
backBuffer[i] = Math.Min(InfraredOutputValueMaximum, (((float)frameData[i] / InfraredSourceValueMaximum * InfraredSourceScale) * (1.0f - InfraredOutputValueMinimum)) + InfraredOutputValueMinimum);
}
// mark the entire bitmap as needing to be drawn
this.infraredBitmap.AddDirtyRect(new Int32Rect(0, 0, this.infraredBitmap.PixelWidth, this.infraredBitmap.PixelHeight));
this.infraredBitmap.Unlock();
}
public ImageSource ImageSource
{
get
{
return this.infraredBitmap;
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (this.infraredFrameReader != null)
{
// InfraredFrameReader is IDisposable
this.infraredFrameReader.Dispose();
this.infraredFrameReader = null;
}
if (this.kinectSensor != null)
{
this.kinectSensor.Close();
this.kinectSensor = null;
}
}
}
}
程序流程与深度,色彩几乎一致!
附:
Xaml添加代码:
<Image HorizontalAlignment="Left" VerticalAlignment="Top" Source="{Binding ImageSource}" Stretch="UniformToFill"/>