2012-11-28 3 views
2

다른 스켈레톤의 크기와 일치하도록 스켈레톤 크기를 조정하려고합니다. 내 알고리즘으로는 다음을 수행하십시오Kinect 스켈레톤 이상한 동작 크기 조절

  • 두 기원 골격의 관절과 곱셈 요인을 찾을 수 phytagorean teorem이이 개 거리를
  • 나누기를 사용하여 운명 골격 사이의 거리를 찾습니다.
  • 각 관절에이 계수를 곱하십시오. 여기

내 실제 코드 :

public static Skeleton ScaleToMatch(this Skeleton skToBeScaled, Skeleton skDestiny) 
    { 
     Joint newJoint = new Joint(); 

     double distanciaOrigem = 0; 
     double distanciaDestino = 0; 
     double fator = 1; 
     SkeletonPoint pos = new SkeletonPoint(); 

     foreach (BoneOrientation bo in skToBeScaled.BoneOrientations) 
     { 
      distanciaOrigem = FisioKinectCalcs.Distance3DBetweenJoint(skToBeScaled.Joints[bo.StartJoint], skToBeScaled.Joints[bo.EndJoint]); 
      distanciaDestino = FisioKinectCalcs.Distance3DBetweenJoint(skDestiny.Joints[bo.StartJoint], skDestiny.Joints[bo.EndJoint]); 

      if (distanciaOrigem > 0 && distanciaDestino > 0) 
      { 
       fator = (distanciaDestino/distanciaOrigem); 

       newJoint = skToBeScaled.Joints[bo.EndJoint]; // escaling only the end joint as the BoneOrientatios starts from HipCenter, i am scaling from center to edges. 

       // applying the new values to the joint 
       pos = new SkeletonPoint() 
       { 
        X = (float)(newJoint.Position.X * fator), 
        Y = (float)(newJoint.Position.Y * fator), 
        Z = (float)(newJoint.Position.Z * fator) 
       }; 

       newJoint.Position = pos; 
       skToBeScaled.Joints[bo.EndJoint] = newJoint; 
      } 
     } 

     return skToBeScaled; 
    } 

모든이의 손을 제외하고 잘 작동하는 것 같다,이 이미지

enter image description here enter image description here

I에서

봐 발자취 내 자신의 뼈대가 있고, 뼈대 sc 다른 사람의 크기에 따라 달라졌지 만, 손과 발은 여전히 ​​미쳤다. (하지만 코드는 올바르게 보입니다)

어떤 제안이 있습니까?

+1

이 나이를 깨달았습니다. 파티에 늦게 늦었습니다! 나는 당신의 문제가 원래의 거리를 계산하는데 여전히 사용하면서 당신을 해골로 스케일하는 것을 시도하는 것에 기인한다고 생각합니다. 마지막에 반환 할 수있는 세 번째 스케일 된 뼈대를 만듭니다. 올바른 거리 계산을 위해 원래의 조인트 위치를 그대로 유지해야하므로 루프의 원래 조인트 위치를 수정하지 마십시오. – zeFrenchy

답변

1

코드를 실행하지 않고 말하기는 어렵지만 다소 좋게 보입니다. distanciaOrigem 다음

0에 매우 근접하지만, 심지어 단지 epsilon 멀리 0에서, 그것이 if에 의해 포착되지 않고, 경우

내가 생각 검증 할 무엇, 당신의

if (distanciaOrigem > 0 && distanciaDestino > 0) 

입니다

fator = (distanciaDestino/distanciaOrigem); 

매우 큰 숫자가됩니다!

+0

답변 해 주셔서 감사합니다. 좋은데, 나중에 시도해보고 피드백을 줄 것입니다. – Ewerton

+0

나는 나쁜 영어, 미안, whats 엡실론, 일부 분수와 함께 브라질 사람입니까? – Ewerton

+0

@Ewerton 엡실론은 매우 작은 수를 의미하는 데 사용할 수 있습니다.이 스레드 참조 http://stackoverflow.com/questions/2411392/double-epsilon-for-equality-greater-than-less-than-less-than-or -equal-to-gre – emartel

1

나는 요인을 부드럽게하여 일반적으로 적절한 척도에 맞출 것을 제안합니다. 그냥 먼저 SmoothenFactor 방법을 사용하여 사용을 고려하기 위해 올 때

private static Dictionary<JointType, double> jointFactors = null; 
    static CalibrationUtils() 
    { 
     InitJointFactors(); 
    } 
    public static class EnumUtil 
    { 
     public static IEnumerable<T> GetValues<T>() 
     { 
      return Enum.GetValues(typeof(T)).Cast<T>(); 
     } 
    } 
    private static void InitJointFactors() 
    { 
     var jointTypes = EnumUtil.GetValues<JointType>(); 
     jointFactors = new Dictionary<JointType, double>(); 
     foreach(JointType type in jointTypes) 
     { 
      jointFactors.Add(type, 0); 
     } 
    } 
    private static double SmoothenFactor(JointType jointType, double factor, int weight) 
    { 
     double currentValue = jointFactors[jointType]; 
     double newValue = 0; 
     if(currentValue != 0) 
      newValue = (weight * currentValue + factor)/(weight + 1); 
     else 
      newValue = factor; 
     jointFactors[jointType] = newValue; 
     return newValue; 
    } 

:이 코드를 사용해보십시오 당신이 보는대로 나는 또한 당신의 ScaleToMatch 방법을 수정

public static Skeleton ScaleToMatch(this Skeleton skToBeScaled, Skeleton skDestiny, double additionalFactor = 1) 
    { 
     Joint newJoint = new Joint(); 

     double distanceToScale = 0; 
     double distanceDestiny = 0; 
     double factor = 1; 
     int weight = 500; 
     SkeletonPoint pos = new SkeletonPoint(); 
     Skeleton newSkeleton = null; 
     KinectHelper.CopySkeleton(skToBeScaled, ref newSkeleton); 
     SkeletonPoint hipCenterPosition = newSkeleton.Joints[JointType.HipCenter].Position; 
     foreach(BoneOrientation bo in skToBeScaled.BoneOrientations) 
     { 
      distanceToScale = Distance3DBetweenJoints(skToBeScaled.Joints[bo.StartJoint], skToBeScaled.Joints[bo.EndJoint]); 
      distanceDestiny = Distance3DBetweenJoints(skDestiny.Joints[bo.StartJoint], skDestiny.Joints[bo.EndJoint]); 

      if(distanceToScale > 0 && distanceDestiny > 0) 
      { 

       factor = (distanceDestiny/distanceToScale) * additionalFactor; 


       newJoint = skToBeScaled.Joints[bo.EndJoint]; // escaling only the end joint as the BoneOrientatios starts from HipCenter, i am scaling from center to edges. 

       factor = SmoothenFactor(newJoint.JointType, factor, weight); 

       pos = new SkeletonPoint() 
       { 
        X = (float)((newJoint.Position.X - hipCenterPosition.X) * factor + hipCenterPosition.X), 
        Y = (float)((newJoint.Position.Y - hipCenterPosition.Y) * factor + hipCenterPosition.Y), 
        Z = (float)((newJoint.Position.Z - hipCenterPosition.Z) * factor + hipCenterPosition.Z) 
       }; 
       newJoint.Position = pos; 
       newSkeleton.Joints[bo.EndJoint] = newJoint; 
      } 
     } 
     return newSkeleton; 
    } 

. HipCenter 위치와 관련하여 관절을 이동할 필요가있었습니다. 또한 새 위치는 새로운 벡터 계산에 사용되지 않도록 새 Skeleton 인스턴스에 저장됩니다.

weight으로 실험하십시오.하지만 뼈 길이가 일정하므로 잘못된 Kinect 판독 값이 올바른 크기를 방해하지 않도록 100과 같은 큰 숫자를 사용할 수 있습니다.

여기가 HandRight 공동 위치를 스케일링 도움이 방법의 예 :

enter image description here

weight500로 설정했다. 결과 factor은 약 2으로 추정됩니다 (기본 골격이 의도적으로 2의 배수로 축소 되었기 때문에).

도움이 되었기를 바랍니다.