本文主要是介绍Kinect for windows 开发入门 五:彩色数据获取和使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
背景知识
1. WriteableBitmap之于Bitmap,就好像StringBuilder之于String。可以减少内存消耗。WriteableBitmap在初始化时需要指定高度,宽度和格式。上一节示例中,获取每帧图像都需要创建并初始化一个新的Bitmap,对GPU来说是一个极大的负担。用WriteableBitmap替代可以很大程度上提高性能。
2. 色彩数据流的解析式根据格式而定的。ColorImageFormat枚举用来指定格式。下表列出了支持的格式。简单的说支持四种颜色格式RGB,YUV,Bayer,Infrared;两种分辨率640*480,1280*960;最快支持30帧每秒;
ColorImageFormat | Description | 含义 |
InfraredResolution640x480Fps30 | 16 bits, using the top 10 bits from a PixelFormats.Gray16 format (with the 6 least significant bits always set to 0) whose resolution is 640 x 480 and frame rate is 30 frames per second. Introduced in 1.6. | 格式:红外(有亮度无彩色) 分辨率:640*480 最高频:30帧/秒 |
RawBayerResolution1280x960Fps12 | Bayer data (8 bits per pixel, layout in alternating pixels of red, green and blue) whose resolution is 1280 x 960 and frame rate is 12 frames per second. Introduced in 1.6. | 格式:Bayer 分辨率:1280*960 最高频:12帧/秒 |
RawBayerResolution640x480Fps30 | Bayer data (8 bits per pixel, layout in alternating pixels of red, green and blue) whose resolution is 640 x 480 and frame rate is 30 frames per second. Introduced in 1.6. | 格式:Bayer 分辨率:640*480 最高频:30帧/秒 |
RawYuvResolution640x480Fps15 | Raw YUV data whose resolution is 640 x 480 and frame rate is 15 frames per second. | 格式:YUV 分辨率:640*480 最高频:15帧/秒 |
RgbResolution1280x960Fps12 | RBG data whose resolution is 1280 x 960 and frame rate is 12 frames per second. | 格式:RGB 分辨率:1280*960 最高频:12帧/秒 |
RgbResolution640x480Fps30 | RBG data whose resolution is 640 x 480 and frame rate is 30 frames per second. | 格式:RGB 分辨率:640*480 最高频:30帧/秒 |
YuvResolution640x480Fps15 | YUV data whose resolution is 640 x 480 and frame rate is 15 frames per second. | 格式:YUV 分辨率:640*480 最高频:15帧/秒 |
Undefined | The format is not defined. | 图像格式未定义 |
3. 示例中使用的颜色格式是Bgr32,每个像素占4个字节,每个字节8个位。第一个字节是蓝色通道,第二个是绿色,第三个是红色,第四个待用(表示像素的Alpha?或者透明度)。
4. Stride是指图像中一行像素所占的字节(如RGB:width*height*BytesPerPixel=640*480*4).
5. Stream会为每一帧图像加一个编号(不一定连续)和Timestamp。
6. 获取ColorStream有两种方式,主动和被动,示例中采用被动模式(多用),即被动的持续接受sensor传过来的信息;主动则是,根据需要定时地去获取,可参考“拉”的模式。
7. 本示例展示了一些简单的图像处理。下面代码中以EditColor_开头的方法就是各种处理方法。
示例代码
privateKinectSensor kinect;
privateWriteableBitmapcolorImageBitmap;
privateInt32RectcolorImageBitmapRect;
privateint colorImageStride;
privatebyte[] colorImagePixelData;
// Get and set connected Kinect Sensor;
publicKinectSensor Kinect
{
get
{
returnthis.kinect;
}
set
{
if (this.kinect != value)
{
if (null != this.kinect)
{
UninitializeKinectSensor(this.kinect);
this.kinect= null;
}
}
if (null != value && KinectStatus.Connected== value.Status)
{
this.kinect = value;
InitializeKinectSensor(this.kinect);
}
}
}
// Bind color stream handler
privatevoid InitializeKinectSensor(KinectSensorkinectSensor)
{
if (null != kinectSensor)
{
ColorImageStreamcolorStream = kinectSensor.ColorStream;
colorStream.Enable();
this.colorImageBitmap = newWriteableBitmap(colorStream.FrameWidth,colorStream.FrameHeight, 96, 96, PixelFormats.Bgr32, null);
this.colorImageBitmapRect = newInt32Rect(0, 0,colorStream.FrameWidth, colorStream.FrameHeight);
this.colorImageStride =colorStream.FrameWidth * colorStream.FrameBytesPerPixel;
ColorImageElement.Source = this.colorImageBitmap;
kinectSensor.ColorFrameReady += kinectSensor_ColorFrameReady;
kinectSensor.Start();
}
}
privatevoid UninitializeKinectSensor(KinectSensorkinectSensor)
{
if (kinectSensor != null)
{
kinectSensor.Stop();
kinectSensor.ColorFrameReady -= newEventHandler<ColorImageFrameReadyEventArgs>(kinectSensor_ColorFrameReady);
}
}
privatevoidkinectSensor_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
// Use 'using' to dispose the frame after using.
// 30 frame per second
using (ColorImageFrame frame =e.OpenColorImageFrame())
{
if (null != frame)
{
byte[] pixelData = newbyte[frame.PixelDataLength];
frame.CopyPixelDataTo(pixelData);
EditColor_HighSaturation(pixelData, frame.BytesPerPixel);
this.colorImageBitmap.WritePixels(this.colorImageBitmapRect,pixelData, this.colorImageStride,0);
}
}
}
privatevoid EditColor_Inverted(byte[] pixelData, int bytesPerPixel)
{
for (int i = 0; i <pixelData.Length; i += bytesPerPixel)
{
pixelData[i] = 0x00;//Blue
pixelData[i + 1] = 0x00;//Green
}
}
privatevoid EditColor_Gray(byte[] pixelData, int bytesPerPixel)
{
for (int i = 0; i <pixelData.Length; i += bytesPerPixel)
{
byte gray = Math.Max(pixelData[i],pixelData[i + 1]);
gray= Math.Max(gray,pixelData[i + 2]);
pixelData[i] = gray;
pixelData[i + 1] = gray;
pixelData[i + 2] = gray;
}
}
privatevoid EditColor_BlackWhite(byte[] pixelData, int bytesPerPixel)
{
for (int i = 0; i <pixelData.Length; i += bytesPerPixel)
{
byte gray = Math.Min(pixelData[i], pixelData[i + 1]);
gray= Math.Min(gray,pixelData[i + 2]);
pixelData[i] = gray;
pixelData[i + 1] = gray;
pixelData[i + 2] = gray;
}
}
privatevoid EditColor_Apocalyptic(byte[] pixelData, int bytesPerPixel)
{
for (int i = 0; i <pixelData.Length; i += bytesPerPixel)
{
pixelData[i] = pixelData[i + 1];
pixelData[i + 2] = (byte)~pixelData[i + 2];
}
}
privatevoid EditColor_WashedOut(byte[] pixelData, int bytesPerPixel)
{
for (int i = 0; i <pixelData.Length; i += bytesPerPixel)
{
double gray =(pixelData[i] * 0.11) + (pixelData[i + 1] * 0.59) + (pixelData[i + 2] * 0.3);
double desaturation =0.75;
pixelData[i] = (byte)(pixelData[i] + desaturation * (gray - pixelData[i]));
pixelData[i + 1] = (byte)(pixelData[i + 1] +desaturation * (gray - pixelData[i + 1]));
pixelData[i + 2] = (byte)(pixelData[i + 2] + desaturation * (gray - pixelData[i +2]));
}
}
privatevoid EditColor_HighSaturation(byte[] pixelData, int bytesPerPixel)
{
for (int i = 0; i <pixelData.Length; i += bytesPerPixel)
{
if (pixelData[i] < 0x33 ||pixelData[i] > 0xE5)
{
pixelData[i] = 0x00;
}
else
{
pixelData[i] = 0Xff;
}
if (pixelData[i + 1] < 0x33|| pixelData[i + 1] > 0xE5)
{
pixelData[i + 1] = 0x00;
}
else
{
pixelData[i + 1] = 0Xff;
}
if (pixelData[i + 2] < 0x33|| pixelData[i + 2] > 0xE5)
{
pixelData[i + 2] = 0x00;
}
else
{
pixelData[i + 1] = 0Xff;
}
}
}
public MainWindow()
{
InitializeComponent();
// Action according to the app start or stop
this.Loaded += (sender, e) =>DiscoverKinectSensor();
this.Unloaded += (s, e) => this.kinect = null;
}
privatevoid DiscoverKinectSensor()
{
KinectSensor.KinectSensors.StatusChanged+= KinectSensors_StatusChanged;
this.Kinect = KinectSensor.KinectSensors.FirstOrDefault(x=> x.Status == KinectStatus.Connected);
}
// Monitor Kinect Sensor status, get the first one if it'sconnected, remove if it's disconnected.
privatevoid KinectSensors_StatusChanged(object sender, StatusChangedEventArgs e)
{
switch (e.Status)
{
caseKinectStatus.Connected:
if (null == this.kinect)
{
this.kinect= e.Sensor;
}
break;
caseKinectStatus.Disconnected:
if (this.kinect == e.Sensor)
{
this.kinect= null;
this.kinect= KinectSensor.KinectSensors.FirstOrDefault(x => x.Status == KinectStatus.Connected);
if (this.kinect == null)
{
// Message to show that all kinects weredisconnected.
}
}
break;
}
}
效果演示
翻转:
灰化:
黑白:
血腥:
冲洗:
饱和:
这篇关于Kinect for windows 开发入门 五:彩色数据获取和使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!