/// <summary> /// Get the farthest hand along the camera up axis from a list of valids hands /// </summary> /// <param name="validHDs">The valid hands</param> /// <returns>The farthest hands or null if the list is empty</returns> public HandDetected GetFarthestHand(List <HandDetected> validHDs) { if (validHDs.Count == 0) { return(null); } Vector3 forward = Camera.main.transform.forward; forward = (new Vector3(forward.x, 0.0f, forward.z)).normalized; HandDetected hd = validHDs[0]; float posZ = Vector3.Dot(forward, validHDs[0].Position - Camera.main.transform.position); for (int i = 1; i < validHDs.Count; i++) { float tempPosZ = Vector3.Dot(forward, validHDs[i].Position - Camera.main.transform.position); if (posZ < tempPosZ) { posZ = tempPosZ; hd = validHDs[i]; } } return(hd); }
/// <summary> /// Get the optimal hand given a list of valid hands /// </summary> /// <param name="validHDs">The list of valid Hands</param> /// <returns></returns> public HandDetected GetOptimalHand(List <HandDetected> validHDs) { if (validHDs.Count == 0) { return(null); } float optimalLimit = 0.25f; Vector3 forward = Camera.main.transform.forward; forward = (new Vector3(forward.x, 0.0f, forward.z)).normalized; HandDetected hd = validHDs[0]; float maxPosZ = Vector3.Dot(forward, validHDs[0].Position - Camera.main.transform.position); float minPosZ = float.MaxValue; for (int i = 1; i < validHDs.Count; i++) { bool computeMin = false; float tempPosZ = Vector3.Dot(forward, validHDs[i].Position - Camera.main.transform.position); if (maxPosZ < tempPosZ) { maxPosZ = tempPosZ; if (tempPosZ < optimalLimit) //Take the farthest between a range of 0 and the optimal limit { hd = validHDs[i]; } else { computeMin = true; } } else { computeMin = true; } if (computeMin) { if (tempPosZ < minPosZ && tempPosZ >= optimalLimit) { minPosZ = tempPosZ; hd = validHDs[i]; } } } return(hd); }
public void OnHandUpdate(CameraParameter cameraParam, SpatialCoordinateSystem CoordinateSystem, IList <Hand> hands) { lock (this) { if (m_spatialCoordinateSystem != null) { //Start a new frame foreach (HandDetected hand in m_handsDetected) { hand.NewDetection = true; } //For each detected hand foreach (Hand hand in hands) { //Get the needed transformation matrices to convert hand in image space to camera and world space System.Numerics.Matrix4x4?cameraToWorld = CoordinateSystem.TryGetTransformTo(m_spatialCoordinateSystem).Value; System.Numerics.Matrix4x4 viewToCamera; System.Numerics.Matrix4x4.Invert(cameraParam.CameraViewTransform, out viewToCamera); if (cameraToWorld == null) { cameraToWorld = System.Numerics.Matrix4x4.Identity; } //Hand in camera space System.Numerics.Vector4 handVecCamera = System.Numerics.Vector4.Transform(new System.Numerics.Vector4(hand.PalmX, hand.PalmY, hand.PalmZ, 1.0f), viewToCamera); Vector3 unityHandCamera = new Vector3(handVecCamera.X, handVecCamera.Y, handVecCamera.Z) / handVecCamera.W; //Wrist in camera space System.Numerics.Vector4 wristVecCamera = System.Numerics.Vector4.Transform(new System.Numerics.Vector4(hand.WristX, hand.WristY, hand.WristZ, 1.0f), viewToCamera); Vector3 unityWristCamera = new Vector3(wristVecCamera.X, wristVecCamera.Y, wristVecCamera.Z) / wristVecCamera.W; //Add offsets in the ROI float[] roi = new float[4]; roi[0] = hand.WristROIMinX - 10; roi[1] = hand.WristROIMinY - 10; roi[2] = hand.WristROIMaxX + 10; roi[3] = hand.WristROIMaxY + 10; //check if we already know it bool created = false; HandDetected handDetected = null; foreach (HandDetected hd in m_handsDetected) { if (!hd.IsDetected && hd.HandCollision(roi) && (hd.CameraSpacePosition - unityHandCamera).magnitude <= 0.10) //Test the ROI and the magnitude in the position (no more than 5 cm) { handDetected = hd; break; } } //If not, this is a new hand! if (handDetected == null) { handDetected = new HandDetected(); handDetected.NewDetection = true; m_handsDetected.Add(handDetected); created = true; } float smoothness = m_smoothness; if (created == true) { smoothness = 0.0f; } //Smooth the hand Vector3 smoothPosCamera = unityHandCamera * (1.0f - smoothness) + handDetected.CameraSpacePosition * smoothness; //Smooth the position System.Numerics.Vector4 handVec = System.Numerics.Vector4.Transform(new System.Numerics.Vector4(smoothPosCamera.x, smoothPosCamera.y, smoothPosCamera.z, 1.0f), cameraToWorld.Value); Vector3 unityHandVec = new Vector3(handVec.X, handVec.Y, -handVec.Z) / handVec.W; //Smooth the wrist Vector3 smoothWristCamera = unityWristCamera * (1.0f - smoothness) + handDetected.CameraSpaceWristPosition * smoothness; //Smooth the position System.Numerics.Vector4 wristVec = System.Numerics.Vector4.Transform(new System.Numerics.Vector4(smoothWristCamera.x, smoothWristCamera.y, smoothWristCamera.z, 1.0f), cameraToWorld.Value); Vector3 unityWristVec = new Vector3(wristVec.X, wristVec.Y, -wristVec.Z) / wristVec.W; handDetected.PushPosition(unityHandVec, unityWristVec, smoothPosCamera, smoothWristCamera, roi); //Clear fingers information handDetected.Fingers.Clear(); handDetected.UppestFinger = null; FingerDetected formerFinger = handDetected.UppestFinger; if (hand.Fingers.Count > 0) { //Conver each fingers detected foreach (Finger f in hand.Fingers) { //Register the finger position System.Numerics.Vector4 fingerVec = System.Numerics.Vector4.Transform(new System.Numerics.Vector4(f.TipX, f.TipY, f.TipZ, 1.0f), viewToCamera); fingerVec = System.Numerics.Vector4.Transform(fingerVec, cameraToWorld.Value); Vector3 unityFingerVec = new Vector3(fingerVec.X, fingerVec.Y, -fingerVec.Z) / fingerVec.W; handDetected.Fingers.Add(new FingerDetected(unityFingerVec)); } //Detect the uppest finger float minFY = hand.Fingers[0].TipY; handDetected.UppestFinger = handDetected.Fingers[0]; for (int j = 1; j < handDetected.Fingers.Count; j++) { if (minFY > hand.Fingers[0].TipY) { minFY = hand.Fingers[0].TipY; handDetected.UppestFinger = handDetected.Fingers[j]; } } } } } int i = 0; while (i < m_handsDetected.Count) { HandDetected hd = m_handsDetected[i]; //Handle non detected hands if (!hd.IsDetected) { hd.PushUndetection(); //Delete the non valid hands if (!hd.IsValid) { m_handsDetected.RemoveAt(i); continue; } } i++; } } }