using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using bbiwarg.Recognition.HandRecognition; using bbiwarg.Utility; using Emgu.CV.Structure; using Emgu.CV; namespace bbiwarg.Recognition.PalmRecognition { class PalmDetector { private List hands; private List palmHands; public List Palms { get; private set; } public PalmDetector(List hands) { this.hands = hands; findPalmHands(); createPalms(); } private void findPalmHands() { palmHands = new List(); foreach (Hand hand in hands) { if (hand.ThumbDefect != null) palmHands.Add(hand); } } private void createPalms() { Palms = new List(); foreach (Hand palmHand in palmHands) { ConvexityDefect thumbDefect = palmHand.ThumbDefect; Vector2D directionWristFinger = thumbDefect.VectorLong.normalize(); Vector2D directionFingerWrist = directionWristFinger.getInverse(); Vector2D directionUpperLower = directionWristFinger.getOrthogonal(palmHand.Side == HandSide.Right); Vector2D directionLowerUpper = directionUpperLower.getInverse(); //handLength Vector2D handLength = 1.5f * thumbDefect.VectorLong; //fingersUpper Vector2D fingersUpper = thumbDefect.OuterLong; bool handBelow = true; while (handBelow && fingersUpper.isInBound()) { fingersUpper += directionWristFinger; Vector2D below = fingersUpper.copy(); bool handBelowFound = false; while (!handBelowFound && below.getDistanceTo(fingersUpper) < 2 * Parameters.FingerMaxWidth && below.isInBound()) { below += directionUpperLower; handBelowFound = palmHand.isInside(below); } handBelow = handBelowFound; } //wristUpper Vector2D wristUpper = thumbDefect.Inner + 5 * directionFingerWrist; while (wristUpper.isInBound() && palmHand.isInside(wristUpper)) wristUpper += directionFingerWrist; //handWidth Vector2D handWidth = getHandWidth(palmHand, directionUpperLower); //wristLower Vector2D wristLower = wristUpper + handWidth; //fingersLower Vector2D fingersLower = wristLower + 0.75f * handLength - 0.25f * handWidth; Palm palm = new Palm(palmHand, wristUpper, wristLower, fingersLower, fingersUpper); Palms.Add(palm); palmHand.setPalm(palm); } } private Vector2D getHandWidth(Hand palmHand, Vector2D directionUpperLower) { Vector2D lineStart = palmHand.ThumbDefect.Inner; Vector2D lineEnd = palmHand.ThumbDefect.OuterLong; Vector2D step = (lineEnd - lineStart) / Parameters.PalmNumPositionsForHandWidth; Vector2D currentStart = lineStart; Vector2D maxWidth = null; float maxWidthLength = float.MinValue; for (int i = 0; i < Parameters.PalmNumPositionsForHandWidth; i++) { Vector2D lower = currentStart + 10 * directionUpperLower; while (lower.isInBound() && palmHand.isInside(lower)) lower += directionUpperLower; Vector2D width = (lower - currentStart); float length = width.Length; if (length > maxWidthLength) { maxWidth = width; maxWidthLength = length; } currentStart += step; } return maxWidth; } } }