123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- 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
- {
- public List<ConvexityDefect> ConvexityDefects { get; private set; }
- public Vector2D Centroid { get; private set; }
- public Image<Gray, byte> Mask { get; private set; }
- public List<Finger> 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<Gray, byte> mask, Finger finger)
- {
- Mask = mask;
- Fingers = new List<Finger>();
- 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 mergeWith(Hand mergeHand)
- {
- extendMask(mergeHand.Mask);
- Fingers.AddRange(mergeHand.Fingers);
- foreach (Finger finger in Fingers)
- {
- finger.setHand(this);
- }
- findCentroids();
- }
- public void extendMask(Image<Gray, byte> extendMask)
- {
- Mask = Mask.Or(extendMask);
- findCentroids();
- }
- public void fillOverlappingFingers(List<Finger> otherFingers)
- {
- foreach (Finger finger in otherFingers)
- {
- FingerSliceTrail trail = null;
- foreach (FingerSlice slice in finger.SliceTrail.Slices)
- {
- Vector2D out1 = slice.Start.moveWithinBound(slice.Direction.getInverse(), Parameters.FingerContourMargin);
- Vector2D out2 = slice.End.moveWithinBound(slice.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);
- }
- 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()
- {
- MemStorage ms = new MemStorage();
- Contour<Point> contour = 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));
- ms.Clear();
- }
- 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);
- }
- }
- }
|