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 { public enum HandSide { Undefined = 0, Right = 1, Left = 2 } class Hand : TrackableObject { private List convexityDefects; public int ZIndex { get; private set; } public Vector2D Centroid { get; private set; } public Vector2D CentroidInHand { get; private set; } public Image Mask { get; private set; } public List Fingers { get; private set; } public ConvexityDefect ThumbDefect { get; private set; } public Palm Palm { get; private set; } public HandSide Side { get; private set; } public Hand(Image mask, Finger finger) { Mask = mask; Fingers = new List(); addFinger(finger); findCentroids(); } public bool isInside(Vector2D point) { return (Mask.Data[point.IntY, point.IntX, 0] != 0); } public void addFinger(Finger finger) { Fingers.Add(finger); } public void setZIndex(int zIndex) { ZIndex = zIndex; } public void findThumbDefect() { if (isThumbOnly()) { findConvexityDefects(); filterThumbDefect(); } determineHandSide(); } public void setPalm(Palm palm) { Palm = palm; } private bool isThumbOnly() { return (Fingers.Count == 1); } private void findConvexityDefects() { Contour contour = Mask.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL); List mcvConvexityDefects = new List(contour.GetConvexityDefacts(new MemStorage(), Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE)); convexityDefects = new List(); foreach (MCvConvexityDefect defect in mcvConvexityDefects) convexityDefects.Add(new ConvexityDefect(defect)); } private void filterThumbDefect() { if (convexityDefects.Count > 0) { convexityDefects.Sort((cd1, cd2) => (cd2.Depth.CompareTo(cd1.Depth))); Finger thumb = Fingers[0]; foreach (ConvexityDefect defect in convexityDefects) { if (defect.isPossibleThumbDefect(thumb)) { ThumbDefect = defect; break; } } } } private void determineHandSide() { if (ThumbDefect != null) { if (ThumbDefect.VectorShort.crossProduct(ThumbDefect.VectorLong) > 0) Side = HandSide.Left; else Side = HandSide.Right; } else Side = HandSide.Undefined; } private void findCentroids() { //find centroid MCvPoint2D64f gravityCenter = Mask.GetMoments(true).GravityCenter; Centroid = new Vector2D((float)gravityCenter.x, (float)gravityCenter.y); //find centroid in hand if (isInside(Centroid)) CentroidInHand = Centroid; else { Finger finger = Fingers[0]; Vector2D direction = (finger.HandPoint - Centroid).normalize(); CentroidInHand = Centroid + direction; while (!isInside(CentroidInHand)) CentroidInHand += direction; } } } }