123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using bbiwarg.Images;
- using bbiwarg.Utility;
- using bbiwarg.Recognition.FingerRecognition;
- using bbiwarg.Recognition.HandRecognition;
- using bbiwarg.Input.InputHandling;
- using Emgu.CV;
- using Emgu.CV.Structure;
- namespace bbiwarg.Recognition.PalmRecognition
- {
- class PalmDetector
- {
- private DepthImage depthImage;
- private List<Hand> hands;
- private List<Palm> palms;
- public void detectPalms(FrameData frameData)
- {
- depthImage = frameData.DepthImage;
- hands = frameData.TrackedHands;
- findPalms();
- frameData.DetectedPalms = palms;
- }
- private void findPalms()
- {
- palms = new List<Palm>();
- foreach (Hand hand in hands)
- {
- if (hand.Fingers.Count == 1)
- {
- List<ConvexityDefect> convexityDefects = findConvexityDefects(hand);
- ConvexityDefect thumbDefect = findThumbDefect(hand.Fingers[0], convexityDefects);
- if (thumbDefect != null)
- {
- Palm palm = createPalm(hand, thumbDefect);
- palms.Add(palm);
- }
- }
- }
- }
- private List<ConvexityDefect> findConvexityDefects(Hand hand)
- {
- List<ConvexityDefect> convexityDefects;
- using (MemStorage ms = new MemStorage())
- {
- Contour<Point> contour = hand.Mask.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL);
- List<MCvConvexityDefect> mcvConvexityDefects = new List<MCvConvexityDefect>(contour.GetConvexityDefacts(ms, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE));
- convexityDefects = new List<ConvexityDefect>();
- foreach (MCvConvexityDefect defect in mcvConvexityDefects)
- convexityDefects.Add(new ConvexityDefect(defect));
- }
- return convexityDefects;
- }
- private ConvexityDefect findThumbDefect(Finger thumb, List<ConvexityDefect> convexityDefects)
- {
- convexityDefects.Sort((cd1, cd2) => (cd2.Depth.CompareTo(cd1.Depth)));
- foreach (ConvexityDefect defect in convexityDefects)
- {
- if (defect.isPossibleThumbDefect(thumb))
- return defect;
- }
- return null;
- }
- private Palm createPalm(Hand hand, ConvexityDefect thumbDefect)
- {
- HandSide side = determineHandSide(thumbDefect);
- Vector2D wristUpper = findWristUpper(hand, thumbDefect);
- Vector2D fingersUpper = findFingersUpper(hand, thumbDefect, side);
- float palmWidth = findPalmWidth(hand, thumbDefect, side);
- float palmLength = wristUpper.getDistanceTo(fingersUpper);
- Vector2D directionWristFingers = thumbDefect.VectorLong.normalize();
- Vector2D directionUpperLower = thumbDefect.VectorLong.getOrthogonal(side == HandSide.Right).normalize();
- Vector2D wristLower = wristUpper + palmWidth*directionUpperLower;
- Vector2D fingersLower = wristUpper + 0.75f * palmLength * directionWristFingers + 0.75f * palmWidth * directionUpperLower;
- return new Palm(hand, thumbDefect, side, wristUpper, fingersUpper, fingersLower, wristLower);
- }
- private HandSide determineHandSide(ConvexityDefect thumbDefect)
- {
- if (thumbDefect.VectorShort.crossProduct(thumbDefect.VectorLong) < 0)
- return HandSide.Right;
- else
- return HandSide.Left;
- }
- private Vector2D findWristUpper(Hand hand, ConvexityDefect thumbDefect)
- {
- Vector2D wristDirection = thumbDefect.VectorLong.getInverse().normalize();
- Vector2D wristUpper = thumbDefect.Inner;
- Vector2D wristUpperNext = wristUpper + 5*wristDirection;
- while (wristUpperNext.isInBound(depthImage.Size) && hand.isInside(wristUpperNext))
- {
- wristUpper = wristUpperNext;
- wristUpperNext += wristDirection;
- }
- return wristUpper;
- }
- private Vector2D findFingersUpper(Hand hand, ConvexityDefect thumbDefect, HandSide side)
- {
- Vector2D fingersDirection = thumbDefect.VectorLong.normalize();
- Vector2D lowerDirection = fingersDirection.getOrthogonal(side == HandSide.Right).normalize();
- Vector2D fingersUpper = thumbDefect.OuterLong;
- Vector2D fingersUpperNext = fingersUpper + fingersDirection;
- bool handBelow = true;
- while (handBelow && fingersUpperNext.isInBound(depthImage.Size))
- {
- fingersUpper = fingersUpperNext;
- fingersUpperNext += fingersDirection;
- Vector2D below = fingersUpper.copy();
- handBelow = false;
- int distance = 0;
- while (!handBelow && distance < Parameters.FingerMaxWidth2D && below.isInBound(depthImage.Size))
- {
- handBelow = hand.isInside(below);
- below += lowerDirection;
- }
- }
- return fingersUpper;
- }
- private float findPalmWidth(Hand hand, ConvexityDefect thumbDefect, HandSide side)
- {
- Vector2D lowerDirection = thumbDefect.VectorLong.getOrthogonal(side == HandSide.Right).normalize();
- Vector2D current = thumbDefect.Inner;
- Vector2D step = thumbDefect.VectorLong / Parameters.PalmNumPositionsForPalmWidth;
- float maxWidth = float.MinValue;
- for (int i = 0; i < Parameters.PalmNumPositionsForPalmWidth; i++)
- {
- Vector2D lower = current;
- Vector2D lowerNext = lower + 10 * lowerDirection;
- while (lowerNext.isInBound(depthImage.Size) && hand.isInside(lowerNext))
- {
- lower = lowerNext;
- lowerNext += lowerDirection;
- }
- maxWidth = Math.Max(maxWidth, current.getDistanceTo(lower));
- current += step;
- }
- return maxWidth;
- }
- }
- }
|