C#结合Kinect v2:获取与深度像素匹配的RGB值
Kinect v2 + C#:生成512×424的深度+RGBA融合图像数组
我之前在做Kinect v2相关的C#项目时,刚好实现过类似需求——要输出一个512×424分辨率的数组,每个元素同时包含对应位置的深度值和RGBA颜色信息。这里给你梳理一下完整的实现思路和代码:
核心思路
Kinect v2的深度帧原生分辨率就是512×424,但彩色帧默认是1920×1080,所以不能直接用原始彩色数组和深度数组拼接,必须通过Kinect的坐标映射功能,把彩色像素精准对应到深度帧的每个像素位置上,这样才能得到一一对应的融合数据。
实现步骤与代码示例
1. 初始化必要的对象
首先要初始化KinectSensor、MultiSourceFrameReader,还有坐标映射器(CoordinateMapper):
private KinectSensor _kinectSensor; private MultiSourceFrameReader _multiSourceReader; private CoordinateMapper _coordinateMapper; private ushort[] _depthData; private byte[] _colorData; // 自定义结构体存储每个像素的深度+RGBA信息 public struct DepthRgbaPixel { public ushort Depth; public byte R; public byte G; public byte B; public byte A; } private DepthRgbaPixel[] _mergedDepthRgbaData; // 最终的512×424数组 // 初始化方法 private void InitializeKinect() { _kinectSensor = KinectSensor.GetDefault(); if (_kinectSensor != null) { // 指定读取深度帧和彩色帧 _multiSourceReader = _kinectSensor.OpenMultiSourceFrameReader( FrameSourceTypes.Depth | FrameSourceTypes.Color); _multiSourceReader.MultiSourceFrameArrived += MultiSourceFrameArrived; _coordinateMapper = _kinectSensor.CoordinateMapper; // 初始化数组:深度数组是512×424的ushort数组;彩色数组是1920×1080×4的RGBA数组 _depthData = new ushort[_kinectSensor.DepthFrameSource.FrameDescription.LengthInPixels]; _colorData = new byte[_kinectSensor.ColorFrameSource.FrameDescription.LengthInPixels * 4]; // 初始化融合数组 _mergedDepthRgbaData = new DepthRgbaPixel[512 * 424]; _kinectSensor.Open(); } }
2. 处理帧到达事件
在MultiSourceFrameArrived事件中提取帧数据,并完成坐标映射:
private void MultiSourceFrameArrived(object sender, MultiSourceFrameArrivedEventArgs e) { var reference = e.FrameReference.AcquireFrame(); // 提取深度帧 using (var depthFrame = reference.DepthFrameReference.AcquireFrame()) // 提取彩色帧 using (var colorFrame = reference.ColorFrameReference.AcquireFrame()) { if (depthFrame != null && colorFrame != null) { // 获取深度数据 depthFrame.CopyFrameDataToArray(_depthData); // 将彩色帧转换为RGBA格式并复制到数组(原始彩色帧是YUV422,需要转换) colorFrame.CopyConvertedFrameDataToArray(_colorData, ColorImageFormat.Rgba); // 获取深度帧的描述 var depthDesc = depthFrame.FrameDescription; int depthWidth = depthDesc.Width; // 512 int depthHeight = depthDesc.Height; // 424 int colorWidth = _kinectSensor.ColorFrameSource.FrameDescription.Width; // 1920 // 准备坐标映射:获取每个深度像素对应的彩色空间坐标 ColorSpacePoint[] colorSpacePoints = new ColorSpacePoint[depthWidth * depthHeight]; _coordinateMapper.MapDepthFrameToColorSpace(_depthData, colorSpacePoints); // 生成融合数组 for (int y = 0; y < depthHeight; y++) { for (int x = 0; x < depthWidth; x++) { int depthIndex = y * depthWidth + x; ColorSpacePoint colorPoint = colorSpacePoints[depthIndex]; // 检查彩色坐标是否在有效范围内 if (colorPoint.X >= 0 && colorPoint.X < colorWidth && colorPoint.Y >= 0 && colorPoint.Y < _kinectSensor.ColorFrameSource.FrameDescription.Height) { // 计算彩色数组的索引(RGBA格式,每个像素4字节) int colorIndex = (int)(colorPoint.Y * colorWidth + colorPoint.X) * 4; // 填充融合像素数据 _mergedDepthRgbaData[depthIndex] = new DepthRgbaPixel { Depth = _depthData[depthIndex], R = _colorData[colorIndex], G = _colorData[colorIndex + 1], B = _colorData[colorIndex + 2], A = _colorData[colorIndex + 3] }; } else { // 如果坐标无效,设置默认颜色(黑色不透明) _mergedDepthRgbaData[depthIndex] = new DepthRgbaPixel { Depth = _depthData[depthIndex], R = 0, G = 0, B = 0, A = 255 }; } } } // 这里就可以使用_mergedDepthRgbaData了,它是512×424的融合数据数组 } } }
关键注意事项
- 坐标映射的必要性:直接拿原始1920×1080的彩色数组和512×424的深度数组是无法一一对应的,必须通过
CoordinateMapper.MapDepthFrameToColorSpace方法把深度像素的坐标转换到彩色空间,才能拿到对应的颜色值。 - 帧资源释放:一定要用
using语句包裹获取到的DepthFrame和ColorFrame,避免资源泄漏。 - 边界检查:转换后的彩色坐标可能会超出彩色帧的范围,必须做有效性判断,否则会出现数组越界错误。
- 数组大小计算:深度数组的大小是
512*424(每个元素是ushort),彩色RGBA数组的大小是1920*1080*4(每个像素4字节),融合数组的大小根据你的存储方式调整。
内容的提问来源于stack exchange,提问作者oRole
相关产品推荐
相关产品推荐

