使用Kinect v2查找胸部尺寸

Des*_*tro 21 c# coordinates measure kinect

我需要找到任何使用Kinect的人在面对镜头时的胸部前部尺寸.我目前的解决方案是:

  1. 当MultiFrameSource到达时获取颜色(以显示ui中的主体)主体(获取关节)和bodyIndex帧.

  2. 使用以下方法将BodyIndexFrame复制到byte [] _bodyData:

    bodyIndexFrame.CopyFrameDataToArray(_bodyData);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 我得到了Joint对象:spineShoulder和spineMid.我认为胸部总是在这些点之间.

  4. 我通过使用将两个关节转换为CameraSpacePoint(x,y,z)并从CameraSpacePoint转换为DepthSpacePoint(x,y)

    _sensor.CoordinateMapper.MapCameraPointToDepthSpace(jointPosition);
    
    Run Code Online (Sandbox Code Playgroud)

我仍然保留对spineShoulder的z值的引用.

  1. 第二个假设=> 从spineShoulderY开始到spineMidY我试图找到播放器区域中最宽的点.为了做到这一点,我将尝试找到spineShoulderX和找到的第一个不属于玩家的左边区域之间的最长段,以及发现不属于玩家的spineShoulderX和第一个右侧区域之间的最长段.找到的两个x段必须位于相同的y坐标中.

    /***************
     * Returns the distance between 2 points
     */
    private static int getDistanceToMid(int pointX, int midX)
    {
        if (midX > pointX)
        {
            return (midX - pointX);
        }
        else if (pointX > midX)
        {
            return (pointX - midX);
        }
        else
        {
            return 0;
        }
    }
    
    
    /*********
     * Loops through the bodyData array 
     * It will look for the longest x distance from midX to the last left x value 
     * which still belongs to a player in the y coordinate
     */
    private static int findFarLeftX(byte[] bodyData,int depthWidth, int midX, int y)
    {
        int farLeftX = -1;
        for (int x = midX; x >= 0; --x)
        {
            int depthIndex = (y * depthWidth) + x;
    
            if (depthIndex > 0 && depthIndex < bodyData.Length)
            {
                byte player = bodyData[depthIndex];
    
                if (player != 0xff){
                    if (farLeftX == -1 || farLeftX > x)
                    {
                        farLeftX = x;
                    }
                } else{
                    return farLeftX;
                }
            }
        }
        return farLeftX;
    }
    
    /*********
     * Loops through the bodyData array 
     * It will look for the longest x distance from midX to the last right x value 
     * which still belongs to a player in the y coordinate
     */
    private static int findFarRightX(byte[] bodyData, int depthWidth, int midX, int y)
    {
        int farRightX = -1;
        for (int x = midX; x < depthWidth; ++x)
        {
            int depthIndex = (y * depthWidth) + x;
    
            if (depthIndex > 0 && depthIndex < bodyData.Length)
            {
                byte player = bodyData[depthIndex];
    
                if (player != 0xff)
                {
                    if (farRightX == -1 || farRightX < x)
                    {
                        farRightX = x;
                    } else{
                        return farRightX;
                    }
                }
            }
        }
        return farRightX;
    }
    
    
    private static BodyMember findElement(byte[] bodyData, int   depthHeight, int depthWidth, int startX, int startY, int endY)
    {
        BodyMember member = new BodyMember(-1, -1, -1, -1);
        int totalMaxSum = 0;
        int farLeftX = -1;
        int farRightX = -1;
        int selectedY = -1;
        for (int y = startY; y < depthHeight && y <= endY; ++y)
        {
    
            int leftX = findFarLeftX(bodyData, depthWidth, startX, y);
            int rightX = findFarRightX(bodyData, depthWidth, startX, y);
            if (leftX > -1 && rightX > -1)
            {
                int leftToMid = getDistanceToMid(leftX, startX);
                int rightToMid = getDistanceToMid(rightX, startX);
                int sum = leftToMid + rightToMid;
                if (sum > totalMaxSum)
                {
                    totalMaxSum = sum;
                    farLeftX = leftX;
                    farRightX = rightX;
                    selectedY = y;
                }
            }
        }
    
        member.setFarLeftX(farLeftX);
        member.setFarLeftY(selectedY);
        member.setFarRightX(farRightX);
        member.setFarRightY(selectedY);
        return member;
    
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. findElement将返回一个BodyMember对象,该对象包含farLeftX,farRightX,farLeftY和farRightY.

  3. 我创建了2个DepthSpacePoint对象:DepthSpacePoint chestX1 = new DepthSpacePoint(); chestX1.X = bodyMemberObj.getFarLeftX(); chestX1.Y = bodyMemberObj.getFarLeftY();

    DepthSpacePoint chestX2 = new DepthSpacePoint();
    chestX2.X = bodyMemberObj.getFarRightX();
    chestX2.Y = bodyMemberObj.getFarRightY();
    
    Run Code Online (Sandbox Code Playgroud)
  4. 为了获得以米为单位的真实世界坐标,必须将这些点转换为CameraSpacePoint对象.为了做到这一点,我将使用关节的z值,我在第4点保留了对它的引用.

    CameraSpacePoint chestLeft = _sensor.CoordinateMapper.MapDepthPointToCameraSpace(chestX1,spineShoulderZ);
    CameraSpacePoint chestRight = _sensor.CoordinateMapper.MapDepthPointToCameraSpace(chestX1,spineShoulderZ);
    
    Run Code Online (Sandbox Code Playgroud)
  5. 现在,如果我的代码和假设是正确的,我应该能够获得前胸的正确距离(米).

    double chestLength = (chestLeft.X > chestRight.X) ? chestLeft - chestRight : chestRight - chestLeft;
    
    Run Code Online (Sandbox Code Playgroud)

但是,这似乎没有返回正确的值.几个星期以来,我一直在寻找解决方案,但我似乎陷入困境.

小智 0

您使用的是 kinect One 吗?旧的 kinect 中的测量可能不够准确,无法满足您的要求。

然而,从我的角度来看,提取帧内的移动对象也是值得的(如果 Kinect 前面只有一个人,您将收到此人的轮廓,但要确保您可以比较其位置)与 Kinect 骨架)。

您可以告诉人们在短时间内举起手。然后使用 Kinect 到人体骨骼的距离,并根据轮廓的大小和给定距离 - 计算肩膀下方的最终胸部测量值(从骨骼获取的位置)。我也不完全清楚 Kinect 处理“体型较大”的人的准确度如何。

这里描述了其中一种方法:http://onlinelibrary.wiley.com/doi/10.1002/scj.10237/abstract您还可以用谷歌搜索许多其他给定主题的论文(免费)。

你觉得这个想法怎么样?干杯