Exemple #1
0
        //private void thetaTrackBar_Scroll(object sender, EventArgs e)
        //{
        //    kinectController.settings.theta = thetaTrackBar.Value * (Math.PI / 180);
        //    thetaTextBox.Text = thetaTrackBar.Value.ToString();
        //}

        //private void kTrackBar_Scroll(object sender, EventArgs e)
        //{
        //    kinectController.settings.k = kTrackBar.Value;
        //    kTextBox.Text = kTrackBar.Value.ToString();
        //}

        private void showNumberFingers()
        {
            ThreadPool.QueueUserWorkItem(delegate
            {
                if (kinectController.hands.Count == 1)
                {
                    Invoke(new Action(delegate { alphabetbox.Text = "Show Both Hands"; }));
                }
                if (kinectController.hands.Count > 1)
                {
                    if (kinectController.hands[0].fingertips.Count > 0 && kinectController.hands[1].fingertips.Count == 0)
                    {
                        //fingersTextBox1.Text = kinectController.hands[0].fingertips.Count.ToString();
                        if (kinectController.hands[0].fingertips.Count == 2)
                        {
                            if (Math.Abs(kinectController.hands[0].fingertips[0].X - kinectController.hands[0].fingertips[1].X) < 17)
                            {
                                Invoke(new Action(delegate { alphabetbox.Text = "B"; }));
                                Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.B);
                                Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.B);
                                Thread.Sleep(10000);
                            }
                            else
                            {
                                Invoke(new Action(delegate { alphabetbox.Text = "K"; }));
                                Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.K);
                                Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.K);
                                Thread.Sleep(10000);
                            }
                        }
                        else if (kinectController.hands[0].fingertips.Count == 1)
                        {
                            Invoke(new Action(delegate { alphabetbox.Text = "A"; }));
                            Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.A);
                            Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.A);
                            Thread.Sleep(10000);
                        }
                        else if (kinectController.hands[0].fingertips.Count == 3)
                        {
                            Invoke(new Action(delegate { alphabetbox.Text = "L"; }));
                            Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.L);
                            Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.L);
                            Thread.Sleep(10000);
                        }
                    }
                    if (kinectController.hands.Count > 1)
                    {
                        if (kinectController.hands[0].palm.Y > kinectController.hands[1].palm.Y)
                        {
                            HandDetection temp        = kinectController.hands[0];
                            kinectController.hands[0] = kinectController.hands[1];
                            kinectController.hands[1] = temp;
                        }
                        //fingersTextBox2.Text = kinectController.hands[1].fingertips.Count.ToString();
                        if (kinectController.hands[0].fingertips.Count == 1 && kinectController.hands[1].fingertips.Count == 1)
                        {
                            if (Math.Abs(kinectController.hands[0].fingertips[0].X - kinectController.hands[1].fingertips[0].X) < 10)
                            {
                                Invoke(new Action(delegate { alphabetbox.Text = "C"; }));
                                Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.C);
                                Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.C);
                                Thread.Sleep(10000);
                            }
                            else if ((kinectController.hands[0].fingertips[0].X - kinectController.hands[1].fingertips[0].X) > 10)
                            {
                                Invoke(new Action(delegate { alphabetbox.Text = "I"; }));
                                Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.I);
                                Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.I);
                                Thread.Sleep(10000);
                            }
                            else if ((kinectController.hands[0].fingertips[0].X - kinectController.hands[1].fingertips[0].X) < -10)
                            {
                                Invoke(new Action(delegate { alphabetbox.Text = "E"; }));
                                Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.E);
                                Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.E);
                                Thread.Sleep(10000);
                            }
                            //DIFFERENTIATE B/W I AND E
                        }
                        else if ((kinectController.hands[0].fingertips.Count == 1 && kinectController.hands[1].fingertips.Count == 2)) //|| (kinectController.hands[0].fingertips.Count == 2 && kinectController.hands[1].fingertips.Count == 1))
                        {
                            if (Math.Abs(kinectController.hands[0].fingertips[0].X - kinectController.hands[1].fingertips[0].X) < 10)
                            {
                                Invoke(new Action(delegate { alphabetbox.Text = "D"; }));
                                Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.D);
                                Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.D);
                                Thread.Sleep(10000);
                            }
                            else
                            {
                                Invoke(new Action(delegate { alphabetbox.Text = "J"; }));
                                Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.J);
                                Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.J);
                                Thread.Sleep(10000);
                            }
                        }
                        else if ((kinectController.hands[0].fingertips.Count == 2 && kinectController.hands[1].fingertips.Count == 1)) //|| (kinectController.hands[0].fingertips.Count == 2 && kinectController.hands[1].fingertips.Count == 1))
                        {
                            if (Math.Abs(kinectController.hands[0].fingertips[0].X - kinectController.hands[1].fingertips[0].X) < 10)
                            {
                                if (Math.Abs(kinectController.hands[0].fingertips[0].X - kinectController.hands[0].fingertips[1].X) < 20)
                                {
                                    Invoke(new Action(delegate { alphabetbox.Text = "F"; }));
                                    Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.F);
                                    Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.F);
                                    Thread.Sleep(10000);
                                }
                                else
                                {
                                    Invoke(new Action(delegate { alphabetbox.Text = "M"; }));
                                    Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.M);
                                    Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.M);
                                    Thread.Sleep(10000);
                                }
                            }
                            else if (Math.Abs(kinectController.hands[0].fingertips[1].X - kinectController.hands[1].fingertips[0].X) < 10)
                            {
                                if (Math.Abs(kinectController.hands[0].fingertips[0].X - kinectController.hands[0].fingertips[1].X) < 20)
                                {
                                    Invoke(new Action(delegate { alphabetbox.Text = "H"; }));
                                    Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.H);
                                    Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.H);
                                    Thread.Sleep(10000);
                                }
                                else
                                {
                                    Invoke(new Action(delegate { alphabetbox.Text = "U"; }));
                                    Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.U);
                                    Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.U);
                                    Thread.Sleep(10000);
                                }
                            }
                            else if (Math.Abs(kinectController.hands[0].fingertips[0].X - kinectController.hands[0].fingertips[1].X) < 20)
                            {
                                Invoke(new Action(delegate { alphabetbox.Text = "S"; }));
                                Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.S);
                                Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.S);
                                Thread.Sleep(10000);
                            }
                            else
                            {
                                Invoke(new Action(delegate { alphabetbox.Text = "O"; }));
                                Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.O);
                                Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.O);
                                Thread.Sleep(10000);
                            }
                        }
                        else if (kinectController.hands[0].fingertips.Count == 2 && kinectController.hands[1].fingertips.Count == 2)
                        {
                            if (Math.Abs(kinectController.hands[0].fingertips[0].X - kinectController.hands[1].fingertips[0].X) < 10)
                            {
                                if (Math.Abs(kinectController.hands[0].fingertips[1].X - kinectController.hands[1].fingertips[1].X) < 10)
                                {
                                    if (Math.Abs(kinectController.hands[0].fingertips[0].X - kinectController.hands[0].fingertips[1].X) < 20)
                                    {
                                        Invoke(new Action(delegate { alphabetbox.Text = "G"; }));
                                        Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.G);
                                        Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.G);
                                        Thread.Sleep(10000);
                                    }
                                    else if (Math.Abs(kinectController.hands[0].fingertips[1].X - kinectController.hands[1].fingertips[1].X) < 10)
                                    {
                                        Invoke(new Action(delegate { alphabetbox.Text = "X"; }));
                                        Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.X);
                                        Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.X);
                                        Thread.Sleep(10000);
                                    }
                                }
                                else
                                {
                                    Invoke(new Action(delegate { alphabetbox.Text = "N"; }));
                                    Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.N);
                                    Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.N);
                                    Thread.Sleep(10000);
                                }
                            }
                            else if (Math.Abs(kinectController.hands[0].fingertips[0].X - kinectController.hands[1].fingertips[1].X) < 10)
                            {
                                if (Math.Abs(kinectController.hands[0].fingertips[0].X - kinectController.hands[0].fingertips[1].X) < 20)
                                {
                                    Invoke(new Action(delegate { alphabetbox.Text = "T"; }));
                                    Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.T);
                                    Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.T);
                                    Thread.Sleep(10000);
                                }
                            }
                            else if (Math.Abs(kinectController.hands[0].fingertips[1].X - kinectController.hands[1].fingertips[1].X) < 10)
                            {
                                if (Math.Abs(kinectController.hands[1].fingertips[0].X - kinectController.hands[1].fingertips[1].X) < 20)
                                {
                                    Invoke(new Action(delegate { alphabetbox.Text = "Z"; }));
                                    Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.Z);
                                    Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.Z);
                                    Thread.Sleep(10000);
                                }
                            }
                        }
                        /// Make others difference b/w same fingers <10
                        else if (kinectController.hands[0].fingertips.Count == 3 && kinectController.hands[1].fingertips.Count == 1)
                        {
                            if (Math.Abs(kinectController.hands[0].fingertips[0].X - kinectController.hands[1].fingertips[0].X) < 10)
                            {
                                Invoke(new Action(delegate { alphabetbox.Text = "P"; }));
                                Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.P);
                                Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.P);
                                Thread.Sleep(10000);
                            }
                            else if (Math.Abs(kinectController.hands[0].fingertips[1].X - kinectController.hands[1].fingertips[0].X) < 10)
                            {
                                Invoke(new Action(delegate { alphabetbox.Text = "R"; }));
                                Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.R);
                                Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.R);
                                Thread.Sleep(10000);
                            }
                            else if (Math.Abs(kinectController.hands[0].fingertips[2].X - kinectController.hands[1].fingertips[0].X) < 10)
                            {
                                Invoke(new Action(delegate { alphabetbox.Text = "V"; }));
                                Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.V);
                                Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.V);
                                Thread.Sleep(10000);
                            }
                        }

                        else if (kinectController.hands[0].fingertips.Count == 1 && kinectController.hands[1].fingertips.Count == 3)
                        {
                            Invoke(new Action(delegate { alphabetbox.Text = "W"; }));
                            Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.W);
                            Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.W);
                            Thread.Sleep(10000);
                        }
                        else if (kinectController.hands[0].fingertips.Count == 3 && kinectController.hands[1].fingertips.Count == 2)
                        {
                            Invoke(new Action(delegate { alphabetbox.Text = "Q"; }));
                            Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.Q);
                            Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.Q);
                            Thread.Sleep(10000);
                        }
                        else if (kinectController.hands[0].fingertips.Count == 2 && kinectController.hands[1].fingertips.Count == 3)
                        {
                            Invoke(new Action(delegate { alphabetbox.Text = "Y"; }));
                            Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.Y);
                            Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.Y);
                            Thread.Sleep(10000);
                        }
                        // Backspace keypress required,
                        else if (kinectController.hands[0].fingertips.Count == 3 && kinectController.hands[1].fingertips.Count == 3)
                        {
                            Invoke(new Action(delegate { alphabetbox.Text = "Backspace"; }));
                            Mouse.VirtualKeyboard.KeyDown(System.Windows.Forms.Keys.Back);
                            Mouse.VirtualKeyboard.KeyUp(System.Windows.Forms.Keys.Back);
                            Thread.Sleep(10000);
                        }
                    }
                }
            });
        }
Exemple #2
0
        private List <HandDetection> localizeHands(bool[][] valid)
        {
            int i, j, k;

            List <HandDetection> hands = new List <HandDetection>();

            List <PointsFingers> insidePoints  = new List <PointsFingers>();
            List <PointsFingers> contourPoints = new List <PointsFingers>();


            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 PointsFingers(i, j));
                        }
                        else // Contour
                        {
                            contour[i][j] = true;
                            contourPoints.Add(new PointsFingers(i, j));
                        }
                    }
                }
            }

            // Create the sorted contour list, using the turtle algorithm
            for (i = 0; i < contourPoints.Count; ++i)
            {
                HandDetection hand = new HandDetection();

                // 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 = PointsFingers.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
            PointsFingers 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 = PointsFingers.angle(r1, r2);

                    if (angle > 0 && angle < settings.theta)
                    {
                        pAux = p3 + ((p1 - p3) / 2);
                        if (PointsFingers.distanceEuclideanSquared(pAux, hands[i].palm) >
                            PointsFingers.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 = PointsFingers.angle(r1, r2);

                    if (angle > 0 && angle < settings.theta)
                    {
                        pAux = p3 + ((p1 - p3) / 2);
                        if (PointsFingers.distanceEuclideanSquared(pAux, hands[i].palm) >
                            PointsFingers.distanceEuclideanSquared(hands[i].contour[j], hands[i].palm))
                        {
                            continue;
                        }

                        hands[i].fingertips.Add(hands[i].contour[j]);
                        j += jump;
                    }
                }
            }

            return(hands);
        }
Exemple #3
0
        private List<HandDetection> localizeHands(bool[][] valid)
        {
            int i, j, k;

            List<HandDetection> hands = new List<HandDetection>();

            List<PointsFingers> insidePoints = new List<PointsFingers>();
            List<PointsFingers> contourPoints = new List<PointsFingers>();

            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 PointsFingers(i, j));
                        }
                        else // Contour
                        {
                            contour[i][j] = true;
                            contourPoints.Add(new PointsFingers(i, j));
                        }

                    }
                }
            }

            // Create the sorted contour list, using the turtle algorithm
            for (i = 0; i < contourPoints.Count; ++i)
            {
                HandDetection hand = new HandDetection();

                // 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 = PointsFingers.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
            PointsFingers 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 = PointsFingers.angle(r1, r2);

                    if (angle > 0 && angle < settings.theta)
                    {
                        pAux = p3 + ((p1 - p3) / 2);
                        if (PointsFingers.distanceEuclideanSquared(pAux, hands[i].palm) >
                            PointsFingers.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 = PointsFingers.angle(r1, r2);

                    if (angle > 0 && angle < settings.theta)
                    {
                        pAux = p3 + ((p1 - p3) / 2);
                        if (PointsFingers.distanceEuclideanSquared(pAux, hands[i].palm) >
                            PointsFingers.distanceEuclideanSquared(hands[i].contour[j], hands[i].palm))
                            continue;

                        hands[i].fingertips.Add(hands[i].contour[j]);
                        j += jump;
                    }
                }
            }

            return hands;
        }