Esempio n. 1
0
    public IEnumerable <HullDefectVertice> getDefects()
    {
        int[] hullIndices = getHullIndices();
        var   defects     = Cv2.ConvexityDefects(contour, hullIndices);
        var   hullPointDefectNeighbors = hullIndices.ToDictionary(indices => indices, i => new List <int>());

        foreach (var defect in defects)
        {
            int startPoint  = defect.Item0;
            int endPoint    = defect.Item1;
            int defectPoint = defect.Item2;
            hullPointDefectNeighbors[startPoint].Add(defectPoint);
            hullPointDefectNeighbors[endPoint].Add(defectPoint);
        }

        return(hullIndices
               .Where((indice) => hullPointDefectNeighbors[indice].Count() > 1)
               .Select((indice) => {
            var defectNeighbor = hullPointDefectNeighbors[indice];
            return new HullDefectVertice {
                pt = contour[indice],
                d1 = contour[defectNeighbor[0]],
                d2 = contour[defectNeighbor[1]]
            };
        }
                       ));
    }
Esempio n. 2
0
        private static void DrawContours(IReadOnlyList <Point[]> contours, IList <Point[]> contoursPoly, Mat drawing)
        {
            var center = new Point2f[contours.Count];
            var radius = new float[contours.Count];

            for (var i = 0; i < contours.Count; i++)
            {
                if (Cv2.ContourArea(contours[i]) >= 5000)
                {
                    contoursPoly[i] = Cv2.ApproxPolyDP(contours[i], 3, true);
                    Cv2.MinEnclosingCircle(contoursPoly[i], out center[i], out radius[i]);
                    var tempContour = contours[i];

                    var hulls  = new Point[1][];
                    var hullsI = new int[1][];
                    hulls[0]  = Cv2.ConvexHull(tempContour);
                    hullsI[0] = Cv2.ConvexHullIndices(tempContour);

                    Cv2.DrawContours(drawing, hulls, -1, Scalar.Gold, 2);
                    if (hullsI[0].Length > 0)
                    {
                        var defects = Cv2.ConvexityDefects(tempContour, hullsI[0]);
                        if (defects.Length > 0)
                        {
                            for (var j = 1; j < defects.Length; j++)
                            {
                                var startIdx = defects[j][0];
                                var ptStart  = tempContour[startIdx];
                                var farIdx   = defects[j][2];
                                var ptFar    = tempContour[farIdx];

                                if (GetDistance(ptStart, ptFar) > 1000 && ptStart.Y < center[i].Y && radius[i] >= 70)
                                {
                                    Cv2.Circle(drawing, ptStart, 10, Scalar.Yellow, 2);
                                    Cv2.Line(drawing, ptStart, ptFar, Scalar.Pink, 2);

                                    _numberOfFingers++;
                                }
                            }

                            if (radius[i] > 50)
                            {
                                Cv2.DrawContours(drawing, contoursPoly, i, Scalar.Red);
                                Cv2.Circle(drawing, center[i], (int)radius[i], Scalar.White, 2);
                                Cv2.Circle(drawing, center[i], 5, Scalar.Red, 2);

                                if (Program.ControlMode)
                                {
                                    _posX = (int)(4 * (center[i].X - 100));
                                    _posY = (int)(4 * (center[i].Y - 100));
                                    WinApiUtils.SetCursorPos(_posX, _posY);
                                }
                            }
                        }
                    }
                }
            }
        }
Esempio n. 3
0
        public static void Run()
        {
            Mat image = new Mat();

            frameSource = Cv2.CreateFrameSource_Camera(0);
            while (true)
            {
                //Grab the current frame
                frameSource.NextFrame(image);

                Mat gray = new Mat();
                Cv2.CvtColor(image, gray, ColorConversionCodes.BGR2GRAY);

                Mat blur = new Mat();
                Cv2.GaussianBlur(gray, blur, new Size(19, 19), 0);

                Mat    threshImg = new Mat();
                double thresh    = Cv2.Threshold(gray, threshImg, 150, 255, ThresholdTypes.Otsu);

                Mat[] contours;

                Mat hierarchy = new Mat();
                Cv2.FindContours(threshImg, out contours, hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);
                double maxArea     = 100;
                Mat    handContour = new Mat();
                handContour = contours.OrderByDescending(x => (x.ContourArea())).ToList()[0];
                //foreach (var item in contours)
                //{
                //    if(item.ContourArea() > maxArea)
                //    {
                //        handContour = item;
                //        break;
                //    }
                //}

                Mat hull = new Mat();
                Cv2.ConvexHull(handContour, hull);

                Mat defects = new Mat();
                Cv2.ConvexityDefects(handContour, hull, defects);

                Cv2.ImShow("frame", hull);
                //Cv2.WaitKey(0);
                if (Cv2.WaitKey(1) == (int)ConsoleKey.Enter)
                {
                    break;
                }
            }
        }
Esempio n. 4
0
        public void ConvexityDefects()
        {
            var contour = new[]
            {
                // ‰š
                new Point(0, 0),
                new Point(0, 10),
                new Point(3, 10),
                new Point(3, 5),
                new Point(6, 5),
                new Point(6, 10),
                new Point(10, 10),
                new Point(10, 0),
            };
            var convexHull = Cv2.ConvexHullIndices(contour);

            Assert.Equal(4, convexHull.Length);

            // Note: ConvexityDefects does not support Point2f contour
            var convexityDefects = Cv2.ConvexityDefects(contour, convexHull);

            Assert.Single(convexityDefects);
            Assert.Equal(new Vec4i(1, 6, 3, 1280), convexityDefects[0]);
        }
Esempio n. 5
0
        // uzimamo vrhove koji nisu pravi vrhovi (imaju smetnje i sl.)
        private IEnumerable <DefectVertex> CreateHullDefectVertices(Point[] contour, IEnumerable <int> indices)
        {
            if (contour == null || !indices.Any())
            {
                return(Enumerable.Empty <DefectVertex>());
            }

            indices = indices.OrderByDescending(x => x);
            var defects    = Cv2.ConvexityDefects(contour, indices);
            var neighbours = new Dictionary <int, List <int> >();

            foreach (var induce in indices)
            {
                neighbours[induce] = new List <int>();
            }

            foreach (var defect in defects)
            {
                var startPoint  = defect.Item0;
                var endPoint    = defect.Item1;
                var defectPoint = defect.Item2;

                neighbours[startPoint].Add(defectPoint);
                neighbours[endPoint].Add(defectPoint);
            }

            return(neighbours.Keys
                   .Where(x => neighbours[x].Count > 1)
                   .Select(hull =>
            {
                var defectNeighbourId = neighbours[hull];

                return new DefectVertex(contour[hull], contour[defectNeighbourId[0]],
                                        contour[defectNeighbourId[1]]);
            }));
        }
Esempio n. 6
0
        private static Vec4i[] GetDefects(OpenCvSharp.Point[] contour)
        {
            var hull = Cv2.ConvexHull(contour);

            return(Cv2.ConvexityDefects(contour, PointsToIndex(contour, hull)));
        }
Esempio n. 7
0
    public Mat getHandContour(Mat input, Mat frame)
    {
        Mat detectImage = frame.Clone();

        if (input.Empty())
        {
            return(detectImage);
        }

        // we work only on the 1 channel result, since this function is called inside a loop we are not sure that this is always the case
        if (input.Channels() != 1)
        {
            return(detectImage);
        }

        Point[][]        contours;
        HierarchyIndex[] hierarchy;

        Cv2.FindContours(input,
                         out contours,
                         out hierarchy,
                         RetrievalModes.External,
                         ContourApproximationModes.ApproxSimple);

        if (contours.Length <= 0)
        {
            return(detectImage);
        }


        int    biggest_contour_index = -1;
        double biggest_area          = 0.0;

        for (int i = 0; i < contours.GetLength(0); i++)
        {
            double area = Cv2.ContourArea(contours[i], false);
            if (area > biggest_area)
            {
                biggest_area          = area;
                biggest_contour_index = i;
            }
        }

        if (biggest_contour_index < 0)
        {
            return(detectImage);
        }

        // Debug.Log(" " + biggest_area + " " + biggest_contour_index);
        Point[] hull_points;
        int[]   hull_ints;


        hull_points = Cv2.ConvexHull(contours[biggest_contour_index]);
        hull_ints   = Cv2.ConvexHullIndices(contours[biggest_contour_index]);
        //Debug.Log("hull " + hull_points.Length);
        //Debug.Log("hull " + hull_ints.Length);

        Vec4i[] defects;

        if (hull_ints.Length > 3)
        {
            defects = Cv2.ConvexityDefects(contours[biggest_contour_index], hull_ints);
        }
        else
        {
            return(detectImage);
        }



        ///////////////
        OpenCvSharp.Rect bounding_rectangle = Cv2.BoundingRect(hull_points);

        // we find the center of the bounding rectangle, this should approximately also be the center of the hand
        Point center_bounding_rect = new Point(
            (bounding_rectangle.TopLeft.X + bounding_rectangle.BottomRight.X) / 2,
            (bounding_rectangle.TopLeft.Y + bounding_rectangle.BottomRight.Y) / 2
            );


        // we separate the defects keeping only the ones of intrest
        List <Point> start_points = new List <Point>();
        List <Point> far_points   = new List <Point>();

        // Debug.Log(" " + defects.Length);
        //Debug.Log(" " + contours[biggest_contour_index].Length);
        //Debug.Log(" " + contours.Length);


        for (int i = 0; i < defects.Length; i++)
        {
            start_points.Add(contours[biggest_contour_index][defects[i].Item0]);
            // filtering the far point based on the distance from the center of the bounding rectangle
            if (findPointsDistance(contours[biggest_contour_index][defects[i].Item2], center_bounding_rect) < bounding_rectangle.Height * BOUNDING_RECT_FINGER_SIZE_SCALING)
            {
                far_points.Add(contours[biggest_contour_index][defects[i].Item2]);
            }
        }

        // we compact them on their medians
        List <Point> filtered_start_points = compactOnNeighborhoodMedian(start_points, bounding_rectangle.Height * BOUNDING_RECT_NEIGHBOR_DISTANCE_SCALING);
        List <Point> filtered_far_points   = compactOnNeighborhoodMedian(far_points, bounding_rectangle.Height * BOUNDING_RECT_NEIGHBOR_DISTANCE_SCALING);

        // now we try to find the fingers
        List <Point> filtered_finger_points = new List <Point>();

        if (filtered_far_points.Count > 1)
        {
            List <Point> finger_points = new List <Point>();

            for (int i = 0; i < filtered_start_points.Count; i++)
            {
                List <Point> closest_points = findClosestOnX(filtered_far_points, filtered_start_points[i]);

                if (isFinger(closest_points[0], filtered_start_points[i], closest_points[1], LIMIT_ANGLE_INF, LIMIT_ANGLE_SUP, center_bounding_rect, bounding_rectangle.Height * BOUNDING_RECT_FINGER_SIZE_SCALING))
                {
                    finger_points.Add(filtered_start_points[i]);
                }
            }

            if (finger_points.Count > 0)
            {
                // we have at most five fingers usually :)
                while (finger_points.Count > 5)
                {
                    finger_points.RemoveAt(0);
                }

                // filter out the points too close to each other
                for (int i = 0; i < finger_points.Count - 1; i++)
                {
                    if (findPointsDistanceOnX(finger_points[i], finger_points[i + 1]) > bounding_rectangle.Height * BOUNDING_RECT_NEIGHBOR_DISTANCE_SCALING * 1.5)
                    {
                        filtered_finger_points.Add(finger_points[i]);
                    }
                }

                if (finger_points.Count > 2)
                {
                    if (findPointsDistanceOnX(finger_points[0], finger_points[finger_points.Count - 1]) > bounding_rectangle.Height * BOUNDING_RECT_NEIGHBOR_DISTANCE_SCALING * 1.5)
                    {
                        filtered_finger_points.Add(finger_points[finger_points.Count - 1]);
                    }
                }
                else
                {
                    filtered_finger_points.Add(finger_points[finger_points.Count - 1]);
                }
            }
        }

        // we draw what found on the returned image
        Cv2.DrawContours(detectImage, contours, biggest_contour_index, new Scalar(0, 255, 0), 8, LineTypes.Link8, hierarchy);
        //Cv2.Polylines(input, new IEnumerable<IEnumerable<Point>>( hull_points), true, new Scalar(1, 0, 0));
        Cv2.Rectangle(detectImage, bounding_rectangle.TopLeft, bounding_rectangle.BottomRight, new Scalar(0, 0, 255), 8, LineTypes.Link8);
        Cv2.Circle(detectImage, center_bounding_rect.X, center_bounding_rect.Y, 15, new Scalar(255, 0, 255), 3, LineTypes.Link8);
        drawVectorPoints(detectImage, filtered_start_points, new Scalar(255, 0, 0), true);
        drawVectorPoints(detectImage, filtered_far_points, new Scalar(0, 0, 25), true);
        drawVectorPoints(detectImage, filtered_finger_points, new Scalar(0, 255, 255), false);
        Cv2.PutText(detectImage, filtered_finger_points.Count.ToString(), center_bounding_rect, HersheyFonts.HersheyTriplex, 10, new Scalar(255, 0, 25));

        // and on the starting frame
        Cv2.DrawContours(frame, contours, biggest_contour_index, new Scalar(0, 255, 0), 8, LineTypes.Link8, hierarchy);
        Cv2.Circle(frame, center_bounding_rect.X, center_bounding_rect.Y, 15, new Scalar(255, 0, 255), 8, LineTypes.Link8);
        drawVectorPoints(frame, filtered_finger_points, new Scalar(0, 255, 255), false);
        Cv2.PutText(frame, filtered_finger_points.Count.ToString(), center_bounding_rect, HersheyFonts.HersheyTriplex, 10, new Scalar(255, 0, 255));

        fingerCount = filtered_finger_points.Count;
        if (fingerCount <= 1)
        {
            finalPose = "rock";
        }

        if (fingerCount == 2 && fingerCount <= 3)
        {
            finalPose = "scissor";
        }

        if (fingerCount >= 4)
        {
            finalPose = "paper";
        }

        return(detectImage);
    }