using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using bbiwarg.Images; using bbiwarg.Detectors.FingerDetection; using bbiwarg.Graphics; using bbiwarg.Utility; using Emgu.CV; using Emgu.CV.Structure; namespace bbiwarg.Detectors.HandDetection { class HandDetector { private DepthImage depthImage; private EdgeImage edgeImage; private List fingers; public List Hands { get; private set; } public OutputImage outputImage; public HandDetector(DepthImage depthImage, EdgeImage edgeImage, List fingers, OutputImage outputImage) { this.depthImage = depthImage; this.edgeImage = edgeImage; this.fingers = fingers; this.outputImage = outputImage; detectHands(); drawHands(); } private void detectHands() { int width = depthImage.Width; int height = depthImage.Height; int maxArea = width * height; Image image = edgeImage.Image.Copy().Dilate(2).Erode(2).Mul(255); //draw top finger slice foreach (Finger finger in fingers) { // TODO: connect contour with other edges Contour contour = finger.getContour(); image.FillConvexPoly(contour.ToArray(), new Gray(0)); image.DrawPolyline(finger.getContour().ToArray(), true, new Gray(255), 1); FingerSlice slice = finger.SliceTrail.End; Vector2D direction = slice.LineSegment.Line.Direction; Vector2D start = slice.Start+(Constants.FingerContourMargin+Constants.FingerSliceOverlapFactor)*direction; Vector2D end = slice.End-(Constants.FingerContourMargin+Constants.FingerSliceOverlapFactor)*direction; image.Draw(new Emgu.CV.Structure.LineSegment2D(start, end), new Gray(0), 2); //FingerSlice slice = finger.SliceTrail.Slices[1]; //image.Draw(new Emgu.CV.Structure.LineSegment2D(slice.Start, slice.End), new Gray(255), 2); } Hands = new List(); foreach (Finger finger in fingers) { bool newHand = true; foreach (Hand hand in Hands) { if (hand.isInside(finger.HandPoint)) { hand.addFinger(finger); newHand = false; break; } } if (newHand) { Image mask = new Image(width + 2, height + 2); MCvConnectedComp comp = new MCvConnectedComp(); CvInvoke.cvFloodFill(image, finger.HandPoint, new MCvScalar(255), new MCvScalar(1), new MCvScalar(1), out comp, Emgu.CV.CvEnum.CONNECTIVITY.FOUR_CONNECTED, Emgu.CV.CvEnum.FLOODFILL_FLAG.DEFAULT, mask); if (comp.area < maxArea * Constants.HandMaxSize) { Hand hand = new Hand(mask.Copy(new Rectangle(1, 1, width, height)).Mul(255)); hand.addFinger(finger); Hands.Add(hand); } } } } private void drawHands() { int maxIndex = Math.Min(3, Hands.Count); for (int i = 0; i < maxIndex; i++) { outputImage.Image[i] = Hands[i].Mask; } } } }