使用Kinect v2查找胸部尺寸

时间:2015-03-06 15:59:41

标签: c# coordinates kinect measure

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

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

  2. 使用:

    将BodyIndexFrame复制到byte [] _bodyData
    bodyIndexFrame.CopyFrameDataToArray(_bodyData);
    
  3. 我得到了Joint对象:spineShoulder和spineMid。 我认为胸部总是在这些点之间

  4. 我使用

    将两个关节转换为CameraSpacePoint(x,y,z),并将CameraSpacePoint转换为DepthSpacePoint(x,y)
    _sensor.CoordinateMapper.MapCameraPointToDepthSpace(jointPosition);
    
  5. 我仍然保留对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;
      
      }
      
    2. findElement将返回一个BodyMember对象,该对象包含farLeftX,farRightX,farLeftY和farRightY。

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

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

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

      double chestLength = (chestLeft.X > chestRight.X) ? chestLeft - chestRight : chestRight - chestLeft;
      
    6. 然而,这似乎没有返回正确的值。几个星期以来,我一直在寻找解决方案,但我似乎陷入困境。

2 个答案:

答案 0 :(得分:1)

我曾与Kinect V2合作过,可以说骨架数据本身不足以获得可靠的结果。即使是衣服也会影响Kinect如何解释身体部位,因此您必须结合其他传感器数据的结果。

此外,我建议您对如何处理此问题充满创意, 例如,你可以研究一些关于人体的可能的解剖学相关性,最可能的高度是代理指标,可能是面部识别的年龄,身高是另一个暗示等。

答案 1 :(得分:0)

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

然而,从我的角度来看,在框架内提取移动物体也是值得的(如果在Kinect前面只有一个人你会得到这个人的轮廓,但是确保你可以将它的位置与Kinect骨架进行比较)。

你可以告诉别人在短时间内举手。比使用Kinect到人体骨骼的距离并根据轮廓的大小和给定的距离 - 计算你肩膀下方的最终胸部测量值(从骨骼中取出的位置)。我还没有完全意识到Kinect处理的准确程度如何?#34;更大&#34;人

以下介绍了其中一种方法:http://onlinelibrary.wiley.com/doi/10.1002/scj.10237/abstract您还可以使用特定主题(免费)google许多其他论文。

您如何看待这个想法? 干杯