public Hand parseBinArray(bool[] binaryArray, DepthImagePixel[] depthImageData, double minX, double minY, double maxX, double maxY) { // Initialize local var handMatrix = new bool[Width, Height]; contourMatrix = new bool[Width, Height]; trackedHand = new Hand(); // Conver binaryArray to a binary handMatrix int index; for (int i = (int)minX; i < (int)maxX; i++) { for (int j = (int)minY; j < (int)maxY; j++) { index = Helper.Point2Index(new Point(i, j)); handMatrix[i, j] = binaryArray[index]; } } // A point is a inside point if all its adjacent point is part of the hand, // otherwise it is a "potential" contour point HashSet<Point> potentialPoints = new HashSet<Point>(); for (int i = (int)minX; i < (int)maxX; i++) { for (int j = (int)minY; j < (int)maxY; j++) { if (handMatrix[i, j]) { int adjPointCount = 0; int validPointCount = 0; // Check neighbours for contour if (i > 0) { adjPointCount++; validPointCount = handMatrix[i - 1, j] ? validPointCount + 1 : validPointCount; } if (i < Width - 1) { adjPointCount++; validPointCount = handMatrix[i + 1, j] ? validPointCount + 1 : validPointCount; } if (j > 0) { adjPointCount++; validPointCount = handMatrix[i, j - 1] ? validPointCount + 1 : validPointCount; } if (j < Height - 1) { adjPointCount++; validPointCount = handMatrix[i, j + 1] ? validPointCount + 1 : validPointCount; } if (validPointCount != adjPointCount) { // Is contour contourMatrix[i, j] = true; potentialPoints.Add(new Point(i, j)); } else { // Is inside trackedHand.insidePoints.Add(new Point(i, j)); } } } } // Get a sorted list of contour points List<Point> maxFrontier = new List<Point>(); while (potentialPoints.Count > 0) { List<Point> frontier = calculateFrontier(ref potentialPoints); if (frontier.Count > maxFrontier.Count) { maxFrontier = frontier; } } trackedHand.contourPoints = maxFrontier; // Find palm and fingers findPalm(); findFingers(depthImageData); return trackedHand; }
/// <summary> /// Adds new hand data to recognizer and collect useful data for mapper /// </summary> /// <param name="hand"></param> public void Add2Buffer(Hand hand) { // If buffer is full if (this.MovingBuffer.Count == mBufferLength) this.MovingBuffer.Dequeue(); if (this.ClickBuffer.Count == cBufferLength) this.ClickBuffer.Dequeue(); if (this.ClickFilter.Count == cFilterLength) this.ClickFilter.Dequeue(); if (hand.fingertips.Count == 0) { if (++this.zeroCount == 5) { // Stopping condition (fives trailing 0s) this.clickCount = this.clickCount / 2; if (this.clickCount > 0) { Console.WriteLine(numFingers + " fingers click " + clickCount + " times"); GestureReady(numFingers, clickCount, null); } this.Reset(); return; } } else { // Collects number of fingers this.zeroCount = 0; this.numFingers = Math.Max(hand.fingertips.Count, this.numFingers); } // Cursor click setup ClickFilter.Enqueue(hand.fingertips.Count > 0 ? 1 : 0); this.ClickBuffer.Enqueue(ClickFilter.Average()); bool tooClose = false; this.clickCount = 0; // Number of clicks checking with double buffer solution for optimization // Optimized from linear to constant foreach (double d in this.ClickBuffer) { if (d == 0.50 && !tooClose) { tooClose = true; this.clickCount++; } else tooClose = false; } // Cursor move setup if (hand.fingertips.Count > 0 && (this.numFingers == 1 || this.numFingers == 2)) { if (this.clickCount == 3 && this.MovingBuffer.Count < mBufferLength) { isDragging = true; } // Cursor movement condition // Added differentiator for dragging Point finger = Helper.Convert2DrawingPoint(hand.fingertips[0].point); finger.X = (int)((finger.X - relativeX) * xMultiplier * 2); finger.Y = (int)((relativeY - finger.Y) * yMultiplier * 2); this.MovingBuffer.Enqueue(finger); if (this.MovingBuffer.Count == 1) { FingerDownPos = this.MovingBuffer.ElementAt(0); } else if (this.MovingBuffer.Count == mBufferLength) { Point pos = new Point(); double averageX = this.MovingBuffer.Average(k => k.X); double averageY = this.MovingBuffer.Average(k => k.Y); int scroll = (int)(finger.Y - averageY) * -2 / 3; pos.X = (int)(this.MouseDownPos.X + averageX - FingerDownPos.X); pos.Y = (int)(this.MouseDownPos.Y + averageY - FingerDownPos.Y); GestureReady(this.numFingers, 0, new MapperObject(pos, isDragging, scroll)); } } }