c# - 对在 C# 中从 IntPtr 访问元素感到困惑

标签 c# kinect

<分区>

我正在使用包含以下内容的 Kinect v2 CameraSpacePoint结构:

public struct CameraSpacePoint : IEquatable<CameraSpacePoint>
{
    public float X;
    public float Y;
    public float Z;
}

CameraSpacePoint 还包含一些方法 EqualsGetHashCode 等,上面没有显示这些方法以保持帖子简洁明了。

好吧,我在类构造函数中定义cameraSpacePoints如下:

IntPtr cameraSpacePoints = Marshal.AllocHGlobal(512 * 424 * 4 * 3);

下面是对上述内存分配的解释:

  • 512:宽度
  • 424:高度
  • 4:单个'float'需要的字节数
  • 3:总共三个变量,即“X”、“Y”和“Z”

后来,我使用 CoordinateMapper 将值复制到 cameraSpacePoints如下:

coordinateMapper.MapDepthFrameToCameraSpaceUsingIntPtr(depthFrameData,
                                                   512 * 424 * 2,
                                                   cameraSpacePoints,
                                                   512 * 424 * 4 * 3);

看起来很完美。现在我想从 cameraSpacePoints 获取值。所以我在 unsafe block 中使用了以下代码:

float* cameraSpacePoint = (float*)cameraSpacePoints;
for (var index = 0; index < 512 * 424; index++)
{
    float X = cameraSpacePoint[index];
    float Y = cameraSpacePoint[index + 1];
    float Z = cameraSpacePoint[index + 2];
}

我在想象它时意识到它似乎不起作用。在我看来,使用 IntPtr 从 cameraSapacePoints 访问元素时会出现一些困惑。这里缺少什么?有什么建议吗?

最佳答案

在您的初始代码中,您正在将 IntPtr(指向 CameraSpacePoint 的数组[])转换为原始浮点指针。如果您将 IntPtr 解释为原始 float,因为您一次处理 3 个点(x、y 和 z),您需要将循环递增每次 3 个 float ,例如(为清楚起见,我重命名了变量):

var floats = (float*)cameraSpacePoints;
for (var index = 0; index < 512 * 424; index+=3)
{
    var x = floats[index];
    var y = floats[index + 1];
    var z = floats[index + 2];
    var myCameraSpacePoint = new CameraSpacePoint 
    {
       X = x,
       Y = y,
       Z = z
    };
   // use myCameraSpacePoint here
}

但这是处理数据的一种非常低效的方式,因为无论如何数据最初都是 CameraSpacePoint。更好的方法是将结构直接转换回实际类型:

var cameraSpacePoints = (CameraSpacePoint*)cameraSpacePoints;
for (var index = 0; index < 512 * 424; index++)
{
    var cameraSpacePoint = cameraSpacePoints[index];
    // Do something with cameraSpacePoint
}

通过转换为正确的类型 (CameraSpacePoint),我们还提高了代码的稳健性 - 例如如果将来在 CameraSpacePoint 的新版本中添加了其他字段,那么针对新版本重新编译代码将再次起作用,而直接访问 float会破坏封装并使维护变得困难。

我们不再需要将循环递增 3 的原因是,当我们在 cameraSpacePoints[index] 上使用下标/索引操作时,编译器知道在以下位置找到元素 n在初始 cameraSpacePoints[0] 的位置之后 n * sizeof(CameraSpacePoint) 的偏移量。 sizeof(CameraSpacePoint) 是 3 个 float 的大小。

关于c# - 对在 C# 中从 IntPtr 访问元素感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47869363/

相关文章:

c# - 如何获得小时之间的间隔并从开始到结束放入列表?

c# - Selenium Grid 和本地运行

c++ - 在 Kinect 深度相机中隔离玩家

c# - 如何在 Razor View MVC C# 中将文本转换为超链接或 ActionLink

c# - .NET Forms 身份验证在超时之前注销用户

c# - 尝试将流事件附加到 EventStore 会引发异常

c# - 基于原始 SDK 的 kinect 数据需要什么校正数学

c# - 命名空间 `Kinect' 中不存在类型或命名空间名称 `Microsoft'

java - 将整个 kinect 骨架放置在 3D 空间的中心

controller - USB3 Controller 和 Kinect 2