Пример #1
0
        public List <GameObject> FindByWhiteMask(Mat src, Mat preview)
        {
            // thresh = cv2.inRange(image, (210, 210, 210), (255, 255, 255))
            //var
            mask_white = new Mat();
            //Cv2.InRange(src, new Scalar(150, 150, 150), new Scalar(255, 255, 255), mask_white);
            Cv2.InRange(src, new Scalar(210, 210, 210), new Scalar(255, 255, 255), mask_white);

            // cv2.imshow("edges", thresh)
            //_, cnts, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
            //thresh.DrawContours()

            Mat[] contours = null;
            Mat   dst      = new Mat();

            //Cv2.FindContours(edged, out contours, new Mat(), RetrievalModes.List, ContourApproximationModes.ApproxSimple);
            Cv2.FindContours(mask_white, out contours, dst, RetrievalModes.List, ContourApproximationModes.ApproxNone);
            //Cv2.ImShow("dst", dst);
            //if (config.Preview == 4)
            Cv2.ImShow("thresh", mask_white);
            //dst.Release();
            //thresh.Release();

            List <GameObject> list_result = new List <GameObject>();

            if (contours != null)
            {
                Console.WriteLine("contours.size= " + contours.Length);

                for (int i = 0; i < contours.Length; i++)
                {
                    Mat    contour = contours[i];
                    double area    = Cv2.ContourArea(contour);

                    // if the contour is not sufficiently large, ignore it
                    if (area < 9)
                    {
                        continue;
                    }

                    double peri   = Cv2.ArcLength(contour, true);
                    Mat    approx = contour.ApproxPolyDP(0.04 * peri, true);

                    // Point p2f= approx.Get<Point>(0, 1);
                    // Console.WriteLine("p2x= " + p2f.X + ", " + p2f.Y);
                    // Console.WriteLine("cols= "+ approx.Cols + ", rows= " + approx.Rows);
                    //
                    // Point[] points_approx = new Point[approx.Rows];
                    // for (int j = 0; j < approx.Rows; j++) {
                    //     points_approx[j] = approx.Get<Point>(0, j);
                    // }

                    if (config.Preview > 0)
                    {
                        Cv2.Polylines(preview, approx, true, new Scalar(0, 255, 0), 1);
                    }

                    //Rect rect = Cv2.BoundingRect(contour);
                    //Cv2.Rectangle(preview, rect, new Scalar(0, 255, 0));

                    // https://csharp.hotexamples.com/examples/OpenCvSharp/RotatedRect/-/php-rotatedrect-class-examples.html
                    // https://stackoverflow.com/questions/43342199/draw-rotated-rectangle-in-opencv-c
                    RotatedRect rrect    = Cv2.MinAreaRect(contour);
                    Point2f[]   points2f = rrect.Points();
                    //points2f = ImUtils.OrderPoints(points2f);

                    if (config.Preview > 0)
                    {
                        ImUtils.PolylinesPoints2f(preview, points2f, Colors.green);
                    }

                    // https://www.pyimagesearch.com/2016/03/21/ordering-coordinates-clockwise-with-python-and-opencv/
                    // # loop over the original points and draw them
                    //for (int i1 = 0; i1 < points2f.Length; i1++) {
                    //    Cv2.Circle(preview, new Point((int)points2f[i1].X, (int)points2f[i1].Y), 5, colors[i1], -1);
                    //}


                    double h     = ImUtils.Distance(points2f[0], points2f[1]);
                    double w     = ImUtils.Distance(points2f[0], points2f[3]);
                    double ratio = h / w;
                    if (h > w)
                    {
                        ratio = w / h;
                    }

                    // compute the center of the contour
                    Moments m         = Cv2.Moments(contour);
                    Point   pt_center = new Point((int)(m.M10 / m.M00), (int)(m.M01 / m.M00));
                    if (this.config.Preview > 0)
                    {
                        Cv2.Circle(preview, pt_center, 2, new Scalar(255, 0, 0), -1);
                    }


                    //Console.Write(", " + Cv2.ContourArea(contour));
                    // if (Cv2.ContourArea(contour) > max_val && Cv2.ContourArea(contour) < 408)
                    // {
                    //    max_val = Cv2.ContourArea(contour);
                    //    max_i = i;
                    //    //Cv2.DrawContours(image, contours, i, new Scalar(255, 128, 128), 5);
                    // }
                    //Cv2.DrawContours(image, contours, i, new Scalar(255, 128, 128), 5);

                    // https://metanit.com/sharp/tutorial/7.5.php
                    //Console.WriteLine($"object: area={(int)area,5}, pts_count={approx.Rows,3}, ratio= {ratio:f4}, center={pt_center}              ");

                    GameObject obj = new GameObject(contour, area, approx, pt_center, ratio, rrect);
                    if (ratio > 0.05)
                    {
                        obj.type = GameObject.ObjectType.unknown;
                        list_result.Add(obj);
                    }
                    else
                    {
                        //obj.type = GameObject.ObjectType.noise;
                    }
                }

                dst.Release();
                //mask_white.Release();
            }

            //if (configPreview!=0) {
            //    Cv2.DrawContours(preview, contours, -1, new Scalar(0, 255, 0), 2);
            //}

            return(list_result);
        }
Пример #2
0
        //public Mat mask_white = null;
        // за первый проход наполняю с сортировкой по X
        // за второй ищу цифры по высоте
        // https://answers.opencv.org/question/74777/how-to-use-approxpolydp-to-close-contours/
        public void PreProcessByWhiteMask(Mat src, Mat preview, Mat mask_white)
        {
            // количество гиганских объектов
            int big_count = 0;
            int max_y     = 0;

            //Point pt_tmp = new Point(0, 0);

            Mat[] contours = null;
            Mat   dst      = new Mat();

            //Cv2.FindContours(edged, out contours, new Mat(), RetrievalModes.List, ContourApproximationModes.ApproxSimple);
            Cv2.FindContours(mask_white, out contours, dst, RetrievalModes.External, ContourApproximationModes.ApproxNone);

            if (contours != null)
            {
                Console.WriteLine($"contours.size={contours.Length}   ");

                for (int i = 0; i < contours.Length; i++)
                {
                    Mat    contour = contours[i];
                    double area    = Cv2.ContourArea(contour);

                    // if the contour is not sufficiently large, ignore it
                    if (area < 1)
                    {
                        continue;
                    }

                    double peri          = Cv2.ArcLength(contour, true);
                    Mat    points_approx = contour.ApproxPolyDP(0.04 * peri, true);

                    //                    Vec2i pt_top= points_approx.Get<Vec2i>(0, 0), pt_bottom = points_approx.Get<Vec2i>(0, 0);
                    //                    for (int y = 0; y < points_approx.Height; y++)
                    //                    {
                    //                        for (int x = 0; x < points_approx.Width; x++)
                    //                        {
                    //                            Vec2i pt = points_approx.Get<Vec2i>(y, x);
                    //                            //if (i==3) {
                    //                            //Console.WriteLine("" + y + "=" + pt.Item0 + ", "+ pt.Item1+ "                             ");
                    //                            if (this.config.Preview > 0) Cv2.Circle(preview, new Point(pt.Item0, pt.Item1), 3, new Scalar(0, 255, 0), -1);
                    //                            //}
                    //
                    //                            if (pt.Item1 < pt_top.Item1) { pt_top = pt; }
                    //                            if (pt.Item1 > pt_bottom.Item1) { pt_bottom = pt; }
                    //                        }
                    //                    }

                    // Point[] points_approx = new Point[approx.Rows];
                    // for (int j = 0; j < approx.Rows; j++) {
                    //     points_approx[j] = approx.Get<Point>(0, j);
                    // }

                    // if (config.Preview > 0) Cv2.Polylines(preview, points_approx, true, new Scalar(0, 0, 255), 4);

                    //Rect rect = Cv2.BoundingRect(contour);
                    //Cv2.Rectangle(preview, rect, new Scalar(0, 255, 0));

                    // https://csharp.hotexamples.com/examples/OpenCvSharp/RotatedRect/-/php-rotatedrect-class-examples.html
                    // https://stackoverflow.com/questions/43342199/draw-rotated-rectangle-in-opencv-c
                    RotatedRect rrect = Cv2.MinAreaRect(contour);

                    // скопировано из ImUtils
                    Point2f[] rrpoints = ImUtils.OrderPoints(rrect.Points());
                    Point2f   tl       = rrpoints[0];
                    Point2f   tr       = rrpoints[1];
                    Point2f   br       = rrpoints[2];
                    Point2f   bl       = rrpoints[3];
                    //if (config.Preview > 0) ImUtils.PolylinesPoints2f(preview, rrpoints);

                    double widthA = ImUtils.Distance(br, bl);
                    double widthB = ImUtils.Distance(tr, tl);
                    double width  = (widthA > widthB ? widthA : widthB);

                    double heightA = ImUtils.Distance(tr, br);
                    double heightB = ImUtils.Distance(tl, bl);
                    double height  = (heightA > heightB ? heightA : heightB);

                    double ratio = height / width;
                    if (height > width)
                    {
                        ratio = width / height;
                    }

                    int top = (int)tl.Y;
                    if (top > (int)tr.Y)
                    {
                        top = (int)tr.Y;
                    }
                    int bottom = (int)bl.Y;
                    if (bottom < (int)br.Y)
                    {
                        bottom = (int)br.Y;
                    }

                    // compute the center of the contour
                    Moments m         = Cv2.Moments(contour);
                    Point   pt_center = new Point((int)(m.M10 / m.M00), (int)(m.M01 / m.M00));
                    //if (this.config.Preview > 0) Cv2.Circle(preview, pt_center, 2, new Scalar(255, 0, 0), -1);

                    // ищу большие буквы - конец игры
                    if (top > 15 && top < 125 &&
                        bottom > 300 && bottom < 390 &&
                        height > 180 &&
                        area > 1000)
                    {
                        // рисую голубым большую цифру  rgb(0, 255, 255) new Scalar(51, 0, 153)
                        //if (this.config.Preview > 0) Cv2.Circle(preview, pt_center, 2, new Scalar(255, 255, 0), -1);
                        //if (config.Preview > 0) ImUtils.PolylinesPoints2f(preview, rrpoints, colors[1]);
                        if (config.Preview > 0)
                        {
                            Cv2.DrawContours(preview, contours, i, Colors.red, 2);
                        }
                        //if (config.Preview > 0) Cv2.Polylines(preview, points_approx, true, colors[0], 2);
                        big_count++;
                    }

                    // проверяю цифры
                    if (
                        //&& obj.center.Y < Program.screenCenter.Y // должен быть в верхней половине экрана
                        bottom < 240 && // должен быть в верхней половине экрана
                        points_approx.Rows >= 2 &&    // у него должно быть более 2 точек
                        area > 4 && area < 1000 &&    // должен быть относительно крупный
                        ratio > 0.05 &&
                        height > 20 && height < 41 && width > 5 && width < 126
                        )
                    {
                        //if (config.Preview > 0) Cv2.Polylines(preview, points_approx, true, colors[1], 2);
                        if (config.Preview > 0)
                        {
                            ImUtils.PolylinesPoints2f(preview, rrpoints, Colors.green2);
                        }
                        if (config.Preview > 0)
                        {
                            Cv2.DrawContours(preview, contours, i, Colors.green2, 2);
                        }

                        GameObject obj = new GameObject(contour, area, points_approx, pt_center, ratio, rrect);
                        list_digits.Add(obj);
                    }

                    // ищу игрока
                    if (player != null && // игнорирую проход до поворота
                        top > screenCenter.Y &&
                        pt_center.Y > max_y &&       // объект должен быть снизу других
                        pt_center.Y > screenCenter.Y && // должен быть в нижней половине экрана
                        points_approx.Rows > 2 &&    // у него должно быть более 2 точек
                        area > 100 &&                // должен быть относительно крупный
                        ratio > 0.19
                        )
                    {
                        max_y = pt_center.Y;

                        player.contour       = contour;
                        player.area          = area;
                        player.points_approx = points_approx; // точки контура
                        player.center        = pt_center;
                        //player.ratio; // width / height to skip lines

                        //Console.WriteLine("PLAYER" + i);
                    }


                    // https://metanit.com/sharp/tutorial/7.5.php
                    //Console.WriteLine($"object{i}: area={(int)area,5}, pts_count={points_approx.Rows,3}, ratio= {ratio:f4}, top={top}, bottom={bottom}, h={height}, w= {width}, center={pt_center}              ");

                    // https://www.pyimagesearch.com/2016/03/21/ordering-coordinates-clockwise-with-python-and-opencv/
                    // # loop over the original points and draw them
                    //for (int i1 = 0; i1 < points2f.Length; i1++) {
                    //    Cv2.Circle(preview, new Point((int)points2f[i1].X, (int)points2f[i1].Y), 2, colors[i1], -1);
                    //}

                    //double h = ImUtils.Distance(points2f[0], points2f[1]);
                    //double w = ImUtils.Distance(points2f[0], points2f[3]);
                }

                //mask_white.Release();
            }

            //Cv2.WaitKey(5000);
            //if (configPreview!=0) {
            //    Cv2.DrawContours(preview, contours, -1, new Scalar(0, 255, 0), 2);
            //}

            dst.Release();

            if (big_count >= 2)
            {
                isGameOver = true;
            }
            if (max_y == 0)
            {
                player = null;
            }
            Console.WriteLine($"big_count={big_count}, isGameOver={isGameOver}   ");
        }