using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using Emgu.CV; using Emgu.CV.Structure; using bbiwarg.Recognition.FingerRecognition; using bbiwarg.Utility; using bbiwarg.Recognition.Tracking; using bbiwarg.Recognition.PalmRecognition; namespace bbiwarg.Recognition.HandRecognition { /// /// Represents a Hand. /// public class Hand : TrackableObject { /// /// the center of gravity of the hand /// public Vector2D Centroid { get; private set; } /// /// a mask of the hand (0=outside, 1=in hand) /// public Image Mask { get; private set; } /// /// the fingers belonging to the hand /// public List Fingers { get; private set; } /// /// the palm belonging to the hand /// public Palm Palm { get; set; } /// /// Initializes a new instance of the Hand class. /// /// The mask. /// The fingers. public Hand(Image mask, List fingers) { Mask = mask; Fingers = fingers; foreach (Finger finger in Fingers) finger.Hand = this; } /// /// Checks wether a given point is inside the hand. /// /// the point /// wether the point is inside the hand public bool isInside(Vector2D point) { return (Mask.Data[point.IntY, point.IntX, 0] != 0); } /// /// Merges another Hand to this hand by extending the mask and adding the fingers. /// /// the other hand public void mergeWith(Hand mergeHand) { extendMask(mergeHand.Mask); Fingers.AddRange(mergeHand.Fingers); foreach (Finger finger in mergeHand.Fingers) finger.Hand = this; } /// /// Extends the mask. /// /// the mask of the extension public void extendMask(Image extendMask) { Mask = Mask.Or(extendMask); } /// /// Fills the Hand mask defects caused by overlapping fingers. /// /// list of fingers that don't belong to this hand public void fillOverlappingFingers(List otherFingers) { ImageSize imageSize = new ImageSize(Mask.Width, Mask.Height); foreach (Finger finger in otherFingers) { FingerSliceTrail trail = null; foreach (FingerSlice slice in finger.SliceTrail.Slices) { Vector2D direction = slice.Direction; Vector2D out1 = slice.Start.moveWithinBound(imageSize, direction.getInverse(), Parameters.FingerContourMargin); Vector2D out2 = slice.End.moveWithinBound(imageSize, direction, Parameters.FingerContourMargin); if (isInside(out1) && isInside(out2)) { if (trail == null) trail = new FingerSliceTrail(slice); else trail.addSlice(slice); } } if (trail != null) Mask.FillConvexPoly(trail.getContour(Parameters.FingerOutMargin).ToArray(), new Gray(1)); } Mask = Mask.Dilate(1); } /// /// Finds the hands centroid (center of gravity). /// public void findCentroid() { MCvPoint2D64f gravityCenter = Mask.GetMoments(true).GravityCenter; Centroid = new Vector2D((float)gravityCenter.x, (float)gravityCenter.y); } } }