示例#1
0
 /// <summary>
 /// Calculates the smaller angle between two points.
 /// </summary>
 /// <param name="point1">Source point.</param>
 /// <param name="point2">Source point.</param>
 /// <returns>Returns the angle in radians.</returns>
 public static float angle(PointFT point1, PointFT point2)
 {
     return((float)Math.Acos((point1.X * point2.X + point1.Y * point2.Y) / (length(point1) * length(point2))));
 }
示例#2
0
 /// <summary>
 /// Copy and create a new instance of PointFT.
 /// </summary>
 /// <param name="other">The PointFT to copy.</param>
 public PointFT(PointFT other)
 {
     this.X = other.X;
     this.Y = other.Y;
 }
示例#3
0
 /// <summary>
 /// Calculates the Euclidean distance between two points.
 /// </summary>
 /// <param name="point1">Source point.</param>
 /// <param name="point2">Source point.</param>
 /// <returns>Returns the distance between the points squared.</returns>
 public static float distanceEuclideanSquared(PointFT point1, PointFT point2)
 {
     return((point1.X - point2.X) * (point1.X - point2.X) + (point1.Y - point2.Y) * (point1.Y - point2.Y));
 }
示例#4
0
 /// <summary>
 /// Calculates the dot product of two points. Returns a floating point value between -1 and 1.
 /// </summary>
 /// <param name="point1">Source point.</param>
 /// <param name="point2">Source point.</param>
 /// <returns>Returns the dot product of the source points.</returns>
 public static float dot(PointFT point1, PointFT point2)
 {
     return((point1.X * point2.X + point1.Y * point2.Y) / (length(point1) * length(point2)));
 }
示例#5
0
 /// <summary>
 /// Calculates the Euclidean distance between two points.
 /// </summary>
 /// <param name="point1">Source point.</param>
 /// <param name="point2">Source point.</param>
 /// <returns>Returns the distance between the points.</returns>
 public static float distanceEuclidean(PointFT point1, PointFT point2)
 {
     return((float)Math.Sqrt((point1.X - point2.X) * (point1.X - point2.X) + (point1.Y - point2.Y) * (point1.Y - point2.Y)));
 }
示例#6
0
 /// <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));
 }
示例#7
0
 /// <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));
 }
示例#8
0
        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);
        }
示例#9
0
        public void depthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
        {
            // Get the depth frame from Kinect
            DepthImageFrame frame = e.OpenDepthImageFrame();

            // Check that the frame is not null
            if (frame == null)
            {
                return;
            }

            // Calculate the real distance for every pixel in the depth image
            int[] distances = generateDistances(frame);

            // Return a 0 or 1 matrix, which contains wich pixels are near enough
            bool[][] near = generateValidMatrix(frame, distances);

            // Return the tracked hands based on the near pixels
            hands = localizeHands(near);

            byte[] pixels = new byte[frame.PixelDataLength * 4];

            // Free last depth Matrix
            Marshal.FreeHGlobal(depthPtr);
            depthPtr = Marshal.AllocHGlobal(pixels.Length);
            Marshal.Copy(pixels, 0, depthPtr, pixels.Length);

            // Create the bitmap
            int height = near.Length;
            int width  = 0;

            if (near.Length > 0)
            {
                width = near[0].Length;
            }
            int stride = width * 4;

            depthImage = new Bitmap(
                width,
                height,
                stride,
                PixelFormat.Format32bppRgb,
                depthPtr);

            // Calculate 3D points for the hands
            for (int i = 0; i < hands.Count; ++i)
            {
                hands[i].calculate3DPoints(settings.screenWidth, settings.screenHeight, distances);
            }

            // Call the rest of the functions
            afterDepthReady();

            // Draw fingertips and palm center
            Graphics gBmp      = Graphics.FromImage(depthImage);
            Brush    blueBrush = new SolidBrush(Color.Blue);
            Brush    redBrush  = new SolidBrush(Color.Red);

            for (int i = 0; i < hands.Count; ++i)
            {
                // Red point which is the center of the palm
                gBmp.FillEllipse(redBrush, hands[i].palm.Y - 5, hands[i].palm.X - 5, 10, 10);

                // Draw inside points
                //for (int j = 0; j < hands[i].inside.Length; ++j)
                //{
                //    Point p = hands[i].inside.Get(j);
                //    depthImage.SetPixel(p.Y, p.X, Color.Blue);
                //}

                // Draw the contour of the hands
                for (int j = 0; j < hands[i].contour.Count; ++j)
                {
                    PointFT p = hands[i].contour[j];
                    depthImage.SetPixel(p.Y, p.X, Color.Red);
                }

                // Blue points which represent the fingertips
                for (int j = 0; j < hands[i].fingertips.Count; ++j)
                {
                    if (hands[i].fingertips[j].X != -1)
                    {
                        gBmp.FillEllipse(blueBrush, hands[i].fingertips[j].Y - 5,
                                         hands[i].fingertips[j].X - 5, 10, 10);
                    }
                }
            }

            blueBrush.Dispose();
            redBrush.Dispose();
            gBmp.Dispose();
        }