尝试从 C# 中的 Kinect v2 获取颜色值时出现 IndexOutOfRange 异常
IndexOutOfRange Exception while trying to get color values from Kinect v2 in C#
我正在尝试获取 Kinect v2 中每个 CameraSpacePoint 的 RGB 值。尝试访问转换后的帧数据时,代码抛出 IndexOutOfRangeException
。我发现以下行引发此错误:
byte red = pixels[4 * pixelsBaseIndex + 0];
byte green = pixels[4 * pixelsBaseIndex + 1];
byte blue = pixels[4 * pixelsBaseIndex + 2];
byte alpha = pixels[4 * pixelsBaseIndex + 3];
完整代码请见下方:
int depthWidth = kinectSensor.DepthFrameSource.FrameDescription.Width;
int depthHeight = kinectSensor.DepthFrameSource.FrameDescription.Height;
int colorWidth = kinectSensor.ColorFrameSource.FrameDescription.Width;
int colorHeight = kinectSensor.ColorFrameSource.FrameDescription.Height;
ushort[] depthData = new ushort[depthWidth * depthHeight];
CameraSpacePoint[] cameraPoints = new CameraSpacePoint[depthData.Length];
ColorSpacePoint[] colorPoints = new ColorSpacePoint[depthData.Length];
// Assuming RGBA format here
byte[] pixels = new byte[colorWidth * colorHeight * 4];
depthFrame = multiSourceFrame.DepthFrameReference.AcquireFrame();
colorFrame = multiSourceFrame.ColorFrameReference.AcquireFrame();
if ((depthFrame == null) || (colorFrame == null))
{
return;
}
depthFrame.CopyFrameDataToArray(depthData);
coordinateMapper.MapDepthFrameToCameraSpace(depthData, cameraPoints);
coordinateMapper.MapDepthFrameToColorSpace(depthData, colorPoints);
// We are using RGBA format
colorFrame.CopyConvertedFrameDataToArray(pixels, ColorImageFormat.Rgba);
for (var index = 0; index < depthData.Length; index++)
{
var u = colorPoints[index].X;
var v = colorPoints[index].Y;
if (u < 0 || u >= colorWidth || v < 0 || v >= colorHeight) continue;
int pixelsBaseIndex = (int)(v * colorWidth + u);
try
{
byte red = pixels[4 * pixelsBaseIndex + 0];
byte green = pixels[4 * pixelsBaseIndex + 1];
byte blue = pixels[4 * pixelsBaseIndex + 2];
byte alpha = pixels[4 * pixelsBaseIndex + 3];
}
catch (IndexOutOfRangeException ex)
{
int minValue = 4 * pixelsBaseIndex;
int maxValue = 4 * pixelsBaseIndex + 3;
Console.WriteLine((minValue > 0) + ", " + (maxValue < pixels.Length));
}
}
代码看起来不错,但我不确定我在这里遗漏了什么! 如何避免IndexOutOfRangeException
异常?有什么建议吗?
第一件事pixelsBaseIndex =< 2070601
(2070601 = 1919 * 1079)
2074817
是 pixelsBaseIndex
的无效值。
此错误可能出在此处。
if (u < 0 || u >= colorWidth || v < 0 || v >= colorHeight) continue;
int pixelsBaseIndex = (int)(v * colorWidth + u);
最好的办法是控制日志 u, v, colorWidth, colorHeight
并验证它们。
编辑
正如我所怀疑的那样,它是由浮点运算引起的。
将一帧映射到另一帧需要复杂的矩阵计算,因此 u,v 得到浮点值。请记住 u,v 是颜色 space 的像素坐标 。它们必须是非负整数。
我推荐的解决方案是
...
int u = (int) Math.Floor(colorPoints[index].X);
int v = (int) Math.Floor(colorPoints[index].Y);
if (u < 0 || u >= colorWidth || v < 0 || v >= colorHeight) continue;
...
仅供参考
查看以下代码行以了解为什么 u、v 像素坐标获得浮点值。发言或丢弃无效值的决定取决于开发人员,因为在任何一种情况下,您都会丢失某种信息。例如,取地板意味着您正在取最近像素的颜色。
在我个人的选择中,输出更精确的值(因此浮点值)对于对输出的 values.For 示例点云配准进行更多计算的开发人员很重要。
我正在尝试获取 Kinect v2 中每个 CameraSpacePoint 的 RGB 值。尝试访问转换后的帧数据时,代码抛出 IndexOutOfRangeException
。我发现以下行引发此错误:
byte red = pixels[4 * pixelsBaseIndex + 0];
byte green = pixels[4 * pixelsBaseIndex + 1];
byte blue = pixels[4 * pixelsBaseIndex + 2];
byte alpha = pixels[4 * pixelsBaseIndex + 3];
完整代码请见下方:
int depthWidth = kinectSensor.DepthFrameSource.FrameDescription.Width;
int depthHeight = kinectSensor.DepthFrameSource.FrameDescription.Height;
int colorWidth = kinectSensor.ColorFrameSource.FrameDescription.Width;
int colorHeight = kinectSensor.ColorFrameSource.FrameDescription.Height;
ushort[] depthData = new ushort[depthWidth * depthHeight];
CameraSpacePoint[] cameraPoints = new CameraSpacePoint[depthData.Length];
ColorSpacePoint[] colorPoints = new ColorSpacePoint[depthData.Length];
// Assuming RGBA format here
byte[] pixels = new byte[colorWidth * colorHeight * 4];
depthFrame = multiSourceFrame.DepthFrameReference.AcquireFrame();
colorFrame = multiSourceFrame.ColorFrameReference.AcquireFrame();
if ((depthFrame == null) || (colorFrame == null))
{
return;
}
depthFrame.CopyFrameDataToArray(depthData);
coordinateMapper.MapDepthFrameToCameraSpace(depthData, cameraPoints);
coordinateMapper.MapDepthFrameToColorSpace(depthData, colorPoints);
// We are using RGBA format
colorFrame.CopyConvertedFrameDataToArray(pixels, ColorImageFormat.Rgba);
for (var index = 0; index < depthData.Length; index++)
{
var u = colorPoints[index].X;
var v = colorPoints[index].Y;
if (u < 0 || u >= colorWidth || v < 0 || v >= colorHeight) continue;
int pixelsBaseIndex = (int)(v * colorWidth + u);
try
{
byte red = pixels[4 * pixelsBaseIndex + 0];
byte green = pixels[4 * pixelsBaseIndex + 1];
byte blue = pixels[4 * pixelsBaseIndex + 2];
byte alpha = pixels[4 * pixelsBaseIndex + 3];
}
catch (IndexOutOfRangeException ex)
{
int minValue = 4 * pixelsBaseIndex;
int maxValue = 4 * pixelsBaseIndex + 3;
Console.WriteLine((minValue > 0) + ", " + (maxValue < pixels.Length));
}
}
代码看起来不错,但我不确定我在这里遗漏了什么! 如何避免IndexOutOfRangeException
异常?有什么建议吗?
第一件事pixelsBaseIndex =< 2070601
(2070601 = 1919 * 1079)
2074817
是 pixelsBaseIndex
的无效值。
此错误可能出在此处。
if (u < 0 || u >= colorWidth || v < 0 || v >= colorHeight) continue;
int pixelsBaseIndex = (int)(v * colorWidth + u);
最好的办法是控制日志 u, v, colorWidth, colorHeight
并验证它们。
编辑
正如我所怀疑的那样,它是由浮点运算引起的。 将一帧映射到另一帧需要复杂的矩阵计算,因此 u,v 得到浮点值。请记住 u,v 是颜色 space 的像素坐标 。它们必须是非负整数。
我推荐的解决方案是
...
int u = (int) Math.Floor(colorPoints[index].X);
int v = (int) Math.Floor(colorPoints[index].Y);
if (u < 0 || u >= colorWidth || v < 0 || v >= colorHeight) continue;
...
仅供参考
查看以下代码行以了解为什么 u、v 像素坐标获得浮点值。发言或丢弃无效值的决定取决于开发人员,因为在任何一种情况下,您都会丢失某种信息。例如,取地板意味着您正在取最近像素的颜色。
在我个人的选择中,输出更精确的值(因此浮点值)对于对输出的 values.For 示例点云配准进行更多计算的开发人员很重要。