/// <summary> /// Returns the length of the source point. /// </summary> /// <returns>The length of the point.</returns> public static float length(PointFT point1) { return((float)Math.Sqrt(point1.X * point1.X + point1.Y * point1.Y)); }
/// <summary> /// Calculate the number of points you have to cross to go from one point to another. /// </summary> /// <param name="point1">Source point.</param> /// <param name="point2">Source point.</param> /// <returns>Returns the distance between the points.</returns> public static int distance(PointFT point1, PointFT point2) { return(Math.Abs(point1.X - point2.X) + Math.Abs(point1.Y - point2.Y)); }
private List <Hand> localizeHands(bool[][] valid) { int i, j, k; List <Hand> hands = new List <Hand>(); List <PointFT> insidePoints = new List <PointFT>(); List <PointFT> contourPoints = new List <PointFT>(); bool[][] contour = new bool[valid.Length][]; for (i = 0; i < valid.Length; ++i) { contour[i] = new bool[valid[0].Length]; } // Divide points in contour and inside points int count = 0; for (i = 1; i < valid.Length - 1; ++i) { for (j = 1; j < valid[i].Length - 1; ++j) { if (valid[i][j]) { // Count the number of valid adjacent points count = this.numValidPixelAdjacent(ref i, ref j, ref valid); if (count == 4) // Inside { insidePoints.Add(new PointFT(i, j)); } else // Contour { contour[i][j] = true; contourPoints.Add(new PointFT(i, j)); } } } } // Create the sorted contour list, using the turtle algorithm for (i = 0; i < contourPoints.Count; ++i) { Hand hand = new Hand(); // If it is a possible start point if (contour[contourPoints[i].X][contourPoints[i].Y]) { // Calculate the contour hand.contour = CalculateFrontier(ref valid, contourPoints[i], ref contour); // Check if the contour is big enough to be a hand if (hand.contour.Count / (contourPoints.Count * 1.0f) > 0.20f && hand.contour.Count > settings.k) { // Calculate the container box hand.calculateContainerBox(settings.containerBoxReduction); // Add the hand to the list hands.Add(hand); } // Don't look for more hands, if we reach the limit if (hands.Count >= settings.maxTrackedHands) { break; } } } // Allocate the inside points to the correct hand using its container box //List<int> belongingHands = new List<int>(); for (i = 0; i < insidePoints.Count; ++i) { for (j = 0; j < hands.Count; ++j) { if (hands[j].isPointInsideContainerBox(insidePoints[i])) { hands[j].inside.Add(insidePoints[i]); //belongingHands.Add(j); } } // A point can only belong to one hand, if not we don't take that point into account /*if (belongingHands.Count == 1) * { * hands[belongingHands.ElementAt(0)].inside.Add(insidePoints[i]); * } * belongingHands.Clear();*/ } // Find the center of the palm float min, max, distance = 0; for (i = 0; i < hands.Count; ++i) { max = float.MinValue; for (j = 0; j < hands[i].inside.Count; j += settings.findCenterInsideJump) { min = float.MaxValue; for (k = 0; k < hands[i].contour.Count; k += settings.findCenterInsideJump) { distance = PointFT.distanceEuclidean(hands[i].inside[j], hands[i].contour[k]); if (!hands[i].isCircleInsideContainerBox(hands[i].inside[j], distance)) { continue; } if (distance < min) { min = distance; } if (min < max) { break; } } if (max < min && min != float.MaxValue) { max = min; hands[i].palm = hands[i].inside[j]; } } } // Find the fingertips PointFT p1, p2, p3, pAux, r1, r2; int size; double angle; int jump; for (i = 0; i < hands.Count; ++i) { // Check if there is a point at the beginning to avoid checking the last ones of the list max = hands[i].contour.Count; size = hands[i].contour.Count; jump = (int)(size * settings.fingertipFindJumpPerc); for (j = 0; j < settings.k; j += 1) { p1 = hands[i].contour[(j - settings.k + size) % size]; p2 = hands[i].contour[j]; p3 = hands[i].contour[(j + settings.k) % size]; r1 = p1 - p2; r2 = p3 - p2; angle = PointFT.angle(r1, r2); if (angle > 0 && angle < settings.theta) { pAux = p3 + ((p1 - p3) / 2); if (PointFT.distanceEuclideanSquared(pAux, hands[i].palm) > PointFT.distanceEuclideanSquared(hands[i].contour[j], hands[i].palm)) { continue; } hands[i].fingertips.Add(hands[i].contour[j]); max = hands[i].contour.Count + j - jump; max = Math.Min(max, hands[i].contour.Count); j += jump; break; } } // Continue with the rest of the points for ( ; j < max; j += settings.findFingertipsJump) { p1 = hands[i].contour[(j - settings.k + size) % size]; p2 = hands[i].contour[j]; p3 = hands[i].contour[(j + settings.k) % size]; r1 = p1 - p2; r2 = p3 - p2; angle = PointFT.angle(r1, r2); if (angle > 0 && angle < settings.theta) { pAux = p3 + ((p1 - p3) / 2); if (PointFT.distanceEuclideanSquared(pAux, hands[i].palm) > PointFT.distanceEuclideanSquared(hands[i].contour[j], hands[i].palm)) { continue; } hands[i].fingertips.Add(hands[i].contour[j]); j += jump; } } } return(hands); }