Exemple #1
0
        public static Point[] GetContours(Mat edgesImg)
        {
            Point[]   screenCut = null;
            Point[][] contours;
            Mat       heirchy = Mat.Zeros(edgesImg.Size(), edgesImg.Type());

            HierarchyIndex[] hIndex;
            Cv2.FindContours(edgesImg, out contours, out hIndex, RetrievalModes.List, ContourApproximationModes.ApproxSimple);

            var query = contours
                        .OrderBy(n => Cv2.ContourArea(n))
                        .Reverse();

            foreach (var contour in query)
            {
                double  peri   = Cv2.ArcLength(contour, true);
                Point[] approx = Cv2.ApproxPolyDP(contour, 0.02 * peri, true);

                if (approx.Length == 4)
                {
                    screenCut = approx;
                    break;
                }
            }
            return(screenCut);
        }
Exemple #2
0
        /// <summary>
        /// Takes candidate shape and combined hull and returns best match
        /// </summary>
        /// <param name="areaSize">Area size</param>
        /// <param name="candidates">Candidates</param>
        /// <param name="hull">Hull</param>
        /// <returns></returns>
        private Point[] GetBestMatchingContour(double areaSize, List <Point[]> candidates, Point[] hull)
        {
            Point[] result = hull;
            if (candidates.Count == 1)
            {
                result = candidates[0];
            }
            else if (candidates.Count > 1)
            {
                List <Point> keys = new List <Point>();
                foreach (var c in candidates)
                {
                    keys.AddRange(c);
                }

                Point[] joinedCandidates = Cv2.ConvexHull(keys);
                Point[] joinedHull       = Cv2.ApproxPolyDP(joinedCandidates, Cv2.ArcLength(joinedCandidates, true) * 0.01, true);
                result = joinedHull;
            }

            // check further
            if (Settings.DropBadGuess)
            {
                double area = Cv2.ContourArea(result);
                if (area / areaSize < Settings.ExpectedArea * 0.75)
                {
                    result = null;
                }
            }

            return(result);
        }
Exemple #3
0
        private OpenCvSharp.Point[] findMostOuterBoxCorner(Mat canny)
        {
            OpenCvSharp.Point[][] contours;
            HierarchyIndex[]      hierarchy;
            Cv2.FindContours(canny, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxTC89KCOS);

            int    maxIndex = 0;
            double maxArea  = double.MinValue;

            for (int i = 0; i < contours.Length; i++)
            {
                OpenCvSharp.Point[] p = contours[i];
                double length         = Cv2.ArcLength(p, true);
                double area           = Cv2.ContourArea(p, true);

                //if (Math.Abs(area) > maxArea)


                if (area > maxArea)
                {
                    maxArea  = area;//maxArea = Math.Abs(area);
                    maxIndex = i;
                }
            }
            OpenCvSharp.Point[] p1 = contours[maxIndex];
            double length1         = Cv2.ArcLength(p1, true);

            OpenCvSharp.Point[] pp = Cv2.ApproxPolyDP(p1, 0.02 * length1, true);
            return(pp);
        }
Exemple #4
0
        public static OpenCvSharp.Point[] Square(Mat src)
        {
            Mat[] split  = Cv2.Split(src);
            Mat   blur   = new Mat();
            Mat   binary = new Mat();

            OpenCvSharp.Point[] squares = new OpenCvSharp.Point[4];

            int    N   = 10;
            double max = src.Size().Width *src.Size().Height * 0.9;
            double min = src.Size().Width *src.Size().Height * 0.1;

            for (int channel = 0; channel < 3; channel++)
            {
                Cv2.GaussianBlur(split[channel], blur, new OpenCvSharp.Size(5, 5), 1);
                for (int i = 0; i < N; i++)
                {
                    Cv2.Threshold(blur, binary, i * 255 / N, 255, ThresholdTypes.Binary);

                    OpenCvSharp.Point[][] contours;
                    HierarchyIndex[]      hierarchy;
                    Cv2.FindContours(binary, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxTC89KCOS);

                    for (int j = 0; j < contours.Length; j++)
                    {
                        double perimeter           = Cv2.ArcLength(contours[j], true);
                        OpenCvSharp.Point[] result = Cv2.ApproxPolyDP(contours[j], perimeter * 0.02, true);

                        double area   = Cv2.ContourArea(result);
                        bool   convex = Cv2.IsContourConvex(result);
                    }
                }
            }
        }
Exemple #5
0
        public static int GetApprox(Point [] contor)
        {
            double peri = Cv2.ArcLength(contor, true);

            Point [] approx = Cv2.ApproxPolyDP(contor, 0.02 * peri, true);
            return(approx.Count( ));
        }
Exemple #6
0
        private bool findContourOfPuzzle()
        {
            Point[] simple;
            double  maxArea = 0;
            double  area;
            bool    found = false;

            foreach (Point[] contour in contours)
            {
                var    curve = new List <Point>(contour);
                double eps   = Cv2.ArcLength(curve, true) * .08;
                simple = Cv2.ApproxPolyDP(curve, eps, true);
                if (simple.Length == 4 && Cv2.IsContourConvex(simple))
                {
                    area = Cv2.ContourArea(contour);
                    if (area > maxArea)
                    {
                        likelyCandidate = simple;
                        maxArea         = area;
                        found           = true;
                    }
                }
            }
            return(found);
        }
 //边缘检测
 private void ucBtnExt_A2_BtnClick(object sender, EventArgs e)
 {
     //提取苹果轮廓
     Cv2.FindContours(apple_mask, out apple_contours, out apple_hierarchy,
                      RetrievalModes.External, ContourApproximationModes.ApproxNone);
     background_mask = new Mat(fruit_mask.Size(), MatType.CV_8UC1, new Scalar(0));
     //绘制苹果轮廓
     Cv2.DrawContours(background_mask, apple_contours, -1, new Scalar(255), 2,
                      LineTypes.Link8, apple_hierarchy);
     //提取梨子轮廓
     Cv2.FindContours(pear_mask, out pear_contours, out pear_hierarchy, RetrievalModes.External,
                      ContourApproximationModes.ApproxNone);
     //绘制梨子轮廓
     for (int i = 0; i < pear_contours.Length; i++)
     {
         if (Cv2.ArcLength(pear_contours[i], true) > 40)   //轮廓周长大于40时绘制
         {
             Cv2.DrawContours(background_mask, pear_contours, i, new Scalar(255), 2, LineTypes.Link8,
                              pear_hierarchy);
         }
     }
     this.pictureBoxIpl_img.ImageIpl = background_mask;
     //输出日志
     newLog = "[msg] 边缘检测完毕";
 }
 //目标质心坐标点计算
 private void ucBtnExt_A4_BtnClick(object sender, EventArgs e)
 {
     //计算苹果质心
     apple_moment   = Cv2.Moments(apple_contours[0]);
     apple_center.X = (int)(apple_moment.M10 / apple_moment.M00);
     apple_center.Y = (int)(apple_moment.M01 / apple_moment.M00);
     //绘制出来
     Cv2.Circle(background_mask, apple_center, 3, new Scalar(255), -1);
     //计算梨子质心
     for (int i = 0; i < pear_contours.Length; i++)
     {
         if (Cv2.ArcLength(pear_contours[i], true) > 40)   //轮廓周长大于40时计算
         {
             pear_moment   = Cv2.Moments(pear_contours[i]);
             pear_center.X = (int)(pear_moment.M10 / pear_moment.M00);
             pear_center.Y = (int)(pear_moment.M01 / pear_moment.M00);
             //绘制出来
             Cv2.Circle(background_mask, pear_center, 3, new Scalar(255), -1);
         }
     }
     this.pictureBoxIpl_img.ImageIpl = background_mask;
     //输出日志
     newLog = "[msg] 苹果在图像中的质心:(" + apple_center.X.ToString() + ","
              + apple_center.Y.ToString() + "), " + "梨子在图像中的质心:("
              + pear_center.X.ToString() + "," + pear_center.Y.ToString() + ")";
 }
        public override IEnumerable <ContourResult> DetectDocumentContours(Mat image, Mat sourceImage)
        {
            var contours = Cv2
                           .FindContoursAsArray(image, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);

            var results = new List <ContourResult>();

            foreach (var contour in contours)
            {
                var convexHull        = Cv2.ConvexHull(contour);
                var peri              = Cv2.ArcLength(convexHull, true);
                var simplifiedContour = Cv2.ApproxPolyDP(convexHull, _epsilon * peri, true);

                if (simplifiedContour != null)
                {
                    results.Add(new ContourResult
                    {
                        Score  = Score,
                        Points = simplifiedContour
                    });
                }
            }

            return(results);
        }
 //轮廓像素坐标点计算
 private void ucBtnExt_A3_BtnClick(object sender, EventArgs e)
 {
     //输出苹果所有像素坐标点
     for (int i = 0; i < apple_contours[0].Length; i++)
     {
         apple_coordinate += " (" + apple_contours[0][i].X.ToString() + ","
                             + apple_contours[0][i].Y.ToString() + "), ";
     }
     //存储苹果二维坐标点
     ShareData.Apple_contour = apple_contours[0];
     newLog = "[msg] 苹果所有轮廓坐标点:" + apple_coordinate;
     Cv2.WaitKey(200);
     //输出梨子所有像素坐标点
     for (int i = 0; i < pear_contours.Length; i++)
     {
         //轮廓周长大于40时计算
         if (Cv2.ArcLength(pear_contours[i], true) > 40)
         {
             for (int j = 0; j < pear_contours[i].Length; j++)
             {
                 pear_coordinate += " (" + pear_contours[i][j].X.ToString() + ","
                                    + pear_contours[i][j].Y.ToString() + ") ";
             }
             //存储梨子二维坐标点
             ShareData.Pear_contour = pear_contours[i];
         }
     }
     newLog = "[msg] 梨子所有轮廓坐标点:" + pear_coordinate;
 }
Exemple #11
0
        /// <summary>
        /// Crops and Transforms Image to return an image of a card
        /// </summary>
        /// <param name="imageInput"></param>
        /// <returns>Mat[]</returns>
        public Mat GetCardImage(Mat imageInput)
        {
            Mat image = imageInput;

            image = new Mat(image, roi);
            Mat transformedImage = GetTransformedImage(image);
            Mat returnCardImage  = new Mat();

            Point[][]        contours;
            HierarchyIndex[] outputArray;
            //Only external contours... we don't want the textbox or the art of the card
            Cv2.FindContours(transformedImage, out contours, out outputArray, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            //FindContours will give array of contours detected in image. Here we filter to get the contour of a card by...
            foreach (Point[] contour in contours)
            {
                //shaping out the contour
                Point[] contourPoints = Cv2.ApproxPolyDP(contour, .01 * Cv2.ArcLength(contour, true), true);
                //and then checking if it's a rectangle and is big enough to be our card...
                if (contourPoints.Length == 4 && Cv2.ContourArea(contour) > 600)
                {
                    //if it is, apply a perspective transform to get a flat image and return it
                    Point2f[] arrayContourPoints = new Point2f[4];
                    for (int i = 0; i < arrayContourPoints.Length; i++)
                    {
                        arrayContourPoints[i] = contourPoints[i];
                    }
                    var corners = GetCorners(arrayContourPoints);
                    if (corners == null)
                    {
                        returnCardImage = null;
                        break;
                    }
                    int rotation = GetCardRotation(corners);
                    ///The order of the corners matter for the perspective transform. The order differs depending on rotation.
                    if (rotation < 0)
                    {
                        arrayContourPoints[0] = corners["leftCorner"];
                        arrayContourPoints[1] = corners["topCorner"];
                        arrayContourPoints[2] = corners["bottomCorner"];
                        arrayContourPoints[3] = corners["rightCorner"];
                    }
                    else
                    {
                        arrayContourPoints[0] = corners["topCorner"];
                        arrayContourPoints[1] = corners["rightCorner"];
                        arrayContourPoints[2] = corners["leftCorner"];
                        arrayContourPoints[3] = corners["bottomCorner"];
                    }
                    Point2f[] destinationPoints = { new Point(0, 0), new Point(672, 0), new Point(0, 936), new Point(672, 936) };

                    Mat perspective = Cv2.GetPerspectiveTransform(arrayContourPoints, destinationPoints);

                    Cv2.WarpPerspective(image, returnCardImage, perspective, new Size(672, 936));
                    break;
                }
            }
            return(returnCardImage);
        }
Exemple #12
0
        public void ArcLength()
        {
            var arc     = new[] { new Point2f(0, 0), new Point2f(10, 0), new Point2f(10, 10), new Point2f(0, 10), };
            var length1 = Cv2.ArcLength(arc, true);

            Assert.Equal(40, length1);

            var length2 = Cv2.ArcLength(arc, false);

            Assert.Equal(30, length2);
        }
Exemple #13
0
        public Mat MinEnclosing(Mat img)
        {
            Mat    binary = new Mat();
            Mat    morp = new Mat();
            Mat    image = new Mat();
            Mat    dst = img.Clone();
            int    pointX = 0, pointY = 0;
            string text;

            Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3));

            OpenCvSharp.Point[][] contours;
            HierarchyIndex[]      hierarchy;

            Cv2.Threshold(img, binary, 230, 255, ThresholdTypes.Binary);
            Cv2.MorphologyEx(binary, morp, MorphTypes.Close, kernel, new OpenCvSharp.Point(-1, -1), 2);
            Cv2.BitwiseNot(morp, image);

            Cv2.FindContours(image, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxTC89KCOS);

            for (int i = 0; i < contours.Length; i++)
            {
                double perimeter = Cv2.ArcLength(contours[i], true);
                double epsilon   = perimeter * 0.01;

                OpenCvSharp.Point[]   approx      = Cv2.ApproxPolyDP(contours[i], epsilon, true);
                OpenCvSharp.Point[][] draw_approx = new OpenCvSharp.Point[][] { approx };
                Cv2.DrawContours(dst, draw_approx, -1, new Scalar(255, 0, 0), 2, LineTypes.AntiAlias);

                Cv2.MinEnclosingCircle(contours[i], out Point2f center, out float radius);
                Cv2.Circle(dst, new OpenCvSharp.Point(center.X, center.Y), (int)radius, Scalar.Red, 2, LineTypes.AntiAlias);

                pointX += (int)center.X;
                pointY += (int)center.Y;

                for (int j = 0; j < approx.Length; j++)
                {
                    Cv2.Circle(dst, approx[j], 1, new Scalar(0, 0, 255), 3);
                }
            }

            if (contours.Length > 0)
            {
                pointX = pointX / contours.Length;
                pointY = pointY / contours.Length;

                text = pointX.ToString();
                text = text + ":" + pointY.ToString();
                Cv2.PutText(dst, text, new OpenCvSharp.Point(3300, 2700), HersheyFonts.HersheyPlain, 5, Scalar.White, 5);
            }

            return(dst);
        }
Exemple #14
0
        public static OpenCvSharp.Point[] Square(Mat src)
        {
            Mat[] split  = Cv2.Split(src);
            Mat   blur   = new Mat();
            Mat   binary = new Mat();

            OpenCvSharp.Point[] squares = new OpenCvSharp.Point[4];

            int    N   = 10;
            double max = src.Size().Width *src.Size().Height * 0.9;
            double min = src.Size().Width *src.Size().Height * 0.1;

            for (int channel = 0; channel < 3; channel++)
            {
                Cv2.GaussianBlur(split[channel], blur, new OpenCvSharp.Size(5, 5), 1);
                for (int i = 0; i < N; i++)
                {
                    Cv2.Threshold(blur, binary, i * 255 / N, 255, ThresholdTypes.Binary);

                    OpenCvSharp.Point[][] contours;
                    HierarchyIndex[]      hierarchy;
                    Cv2.FindContours(binary, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxTC89KCOS);

                    Mat test = src.Clone();
                    Cv2.DrawContours(test, contours, -1, new Scalar(0, 0, 255), 3);

                    for (int j = 0; j < contours.Length; j++)
                    {
                        double perimeter           = Cv2.ArcLength(contours[j], true);
                        OpenCvSharp.Point[] result = Cv2.ApproxPolyDP(contours[j], perimeter * 0.02, true);

                        double area   = Cv2.ContourArea(result);
                        bool   convex = Cv2.IsContourConvex(result);

                        if (result.Length == 4 && area > min && area < max && convex)
                        {
                            double cos = 0;
                            for (int k = 1; k < 5; k++)
                            {
                                double t = Math.Abs(Angle(result[(k - 1) % 4], result[k % 4], result[(k + 1) % 4]));
                                cos = cos > t ? cos : t;
                            }
                            if (cos < 0.15)
                            {
                                squares = result;
                            }
                        }
                    }
                }
            }
            return(squares);
        }
Exemple #15
0
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            Mat src = new Mat(@"./1.jpg");

            src = src.Resize(new Size(src.Width / 2, src.Height / 2));
            Cv2.ImShow("src", src);

            var binary = BinarizationMat(src);

            Cv2.ImShow("bin", binary);
            var fScreenMat = FindContoursMat(binary, src);

            fScreenMat = new Mat(fScreenMat,
                                 new Rect((int)(fScreenMat.Width * 0.025), (int)(fScreenMat.Height * 0.05),
                                          fScreenMat.Width - (int)(fScreenMat.Width * 0.05), fScreenMat.Height - (int)(fScreenMat.Height * 0.1)));
            Cv2.ImShow("Screen", fScreenMat);

            var m2 = SaturationGain(fScreenMat, 255);

            Cv2.ImShow("SaturationGain", m2);
            Cv2.CvtColor(m2, m2, ColorConversionCodes.BGR2GRAY);
            Mat b2 = m2.Threshold(100, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary);

            Cv2.FindContours(b2, out var contours, out var hierarchy, RetrievalModes.Tree,
                             ContourApproximationModes.ApproxSimple);
            Cv2.ImShow("b2", b2);
            var dst = fScreenMat;

            foreach (var itemPoint in contours)
            {
                Console.WriteLine("_________________");
                var epsilon = 0.01 * Cv2.ArcLength(itemPoint, true);
                var approx  = Cv2.ApproxPolyDP(itemPoint, epsilon, true);
                Console.WriteLine("Approx Angle:" + approx.Length);
                foreach (var item in approx)
                {
                    Console.WriteLine(item.X + " " + item.Y);
                    Cv2.Circle(dst, item.X, item.Y, 5, new Scalar(255, 0, 0), 2, LineTypes.AntiAlias);
                    Cv2.ImShow("dst", dst);
                    //Cv2.WaitKey();
                }
                //foreach (var item in itemPoint) Console.WriteLine(item.X + " " + item.Y);
                //Console.WriteLine("_________________");
            }
            Cv2.DrawContours(dst, contours, -1, Scalar.Green, 3);
            Cv2.ImShow("dst", dst);
            Cv2.WaitKey();
        }
        public static bool CheckRectCorners(Point[] contour)
        {
            var epsilon       = 0.1 * Cv2.ArcLength(contour, true);
            var approximation = Cv2.ApproxPolyDP(contour, epsilon, true);

            var hasFourCorners = approximation.Length == 4;
            var isConvex       = Cv2.IsContourConvex(approximation);

            if (hasFourCorners && isConvex)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #17
0
        //블럭화
        private void button1_Click(object sender, EventArgs e)
        {
            ((DataTable)dataGridView1.DataSource).Rows.Clear(); //Row값만 초기화
            int    counter  = 1;
            Mat    dst      = Threshold.Clone();
            double img_area = MyImage.Width * MyImage.Height;

            OpenCvSharp.Point[][] contours;  //윤곽선의 실제 값
            HierarchyIndex[]      hierarchy; // 윤곽선들의 계층 구조
            Mat preprocess_Value = new Mat();

            //색상 공간 변환
            Cv2.InRange(Threshold, new Scalar(threshold_Value, threshold_Value, threshold_Value),
                        new Scalar(255, 255, 255), preprocess_Value);

            //Cv2.FindContours(원본 배열, 검출된 윤곽선, 계층 구조, 검색 방법, 근사 방법, 오프셋)
            Cv2.FindContours(preprocess_Value, out contours, out hierarchy, RetrievalModes.Tree,
                             ContourApproximationModes.ApproxTC89KCOS);

            foreach (OpenCvSharp.Point[] p in contours)
            {
                double length = Cv2.ArcLength(p, true);                                         //길이
                double area   = Cv2.ContourArea(p, true);                                       //면적
                //if (length < 200 || length > 2000) continue; //길이가 너무 작은 윤관석 삭제
                Rect boundingRect           = Cv2.BoundingRect(p);                              //사각형 계산
                OpenCvSharp.Point[] hull    = Cv2.ConvexHull(p, true);                          //블록
                Moments             moments = Cv2.Moments(p, false);                            //중심점
                Cv2.Rectangle(dst, boundingRect, Scalar.Red, 2);                                //사각형 그리기
                                                                                                //Cv2.FillConvexPoly(dst, hull, Scalar.Red); //내부 채우기
                                                                                                //Cv2.Polylines(dst, new OpenCvSharp.Point[][] { hull }, true, Scalar.Red, 1); //다각형 그리기
                Cv2.DrawContours(dst, new OpenCvSharp.Point[][] { hull }, -1, Scalar.Black, 3); //윤곽석 그리기
                double mean = (boundingRect.Width + boundingRect.Height) / 2;
                table.Rows.Add(" " + counter++,
                               " " + (int)(moments.M10 / moments.M00) + ", " + (int)(moments.M01 / moments.M00),
                               " " + Math.Truncate(length * 10) / 10,
                               " " + Math.Abs(area - img_area),
                               " " + area,
                               " " + Math.Max(boundingRect.Width, boundingRect.Height),
                               " " + Math.Min(boundingRect.Width, boundingRect.Height),
                               " " + mean,
                               boundingRect);
            }
            pictureBox2.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst);
        }
Exemple #18
0
        private Point[] GetContour(Mat edged)
        {
            Point[][]        contours;
            HierarchyIndex[] hierarchyIndexes;
            Cv2.FindContours(edged.Clone(), out contours, out hierarchyIndexes, ContourRetrieval.List, ContourChain.ApproxSimple);
            var area           = edged.Height * edged.Width;
            var sortedContours = contours.Where(c => GetContourArea(c) / area > 0.3).OrderByDescending(GetContourArea);

            foreach (var contour in sortedContours)
            {
                var epsilon = 0.02 * Cv2.ArcLength(contour, true);
                var approx  = Cv2.ApproxPolyDP(contour, epsilon, true);
                if (approx.Length == 4)
                {
                    return(approx);
                }
            }
            return(null);
        }
 //显示目标识别结果
 private void ucBtnExt_A5_BtnClick(object sender, EventArgs e)
 {
     //计算最小外接矩形
     apple_rect = Cv2.BoundingRect(apple_contours[0]);
     for (int i = 0; i < pear_contours.Length; i++)
     {
         if (Cv2.ArcLength(pear_contours[i], true) > 40)   //轮廓周长大于40时绘制
         {
             pear_rect = Cv2.BoundingRect(pear_contours[i]);
         }
     }
     //绘制结果
     beifenImg.CopyTo(resultImage);
     Cv2.Rectangle(resultImage, apple_rect, new Scalar(255, 0, 0), 2);
     Cv2.Rectangle(resultImage, pear_rect, new Scalar(255, 0, 0), 2);
     Cv2.Circle(resultImage, apple_center, 7, new Scalar(0, 0, 0), -1);
     Cv2.Circle(resultImage, pear_center, 7, new Scalar(0, 0, 0), -1);
     this.pictureBoxIpl_img.ImageIpl = resultImage;
     newLog = "[msg] 目标识别成功~";
 }
Exemple #20
0
        static void Main(string[] args)
        {
            Mat src    = Cv2.ImRead("chess.png");
            Mat gray   = new Mat();
            Mat binary = new Mat();
            Mat morp   = new Mat();
            Mat image  = new Mat();
            Mat dst    = src.Clone();

            Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));

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

            Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
            Cv2.Threshold(gray, binary, 230, 255, ThresholdTypes.Binary);
            Cv2.MorphologyEx(binary, morp, MorphTypes.Close, kernel, new Point(-1, -1), 2);
            Cv2.BitwiseNot(morp, image);

            Cv2.FindContours(image, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxTC89KCOS);

            for (int i = 0; i < contours.Length; i++)
            {
                double perimeter = Cv2.ArcLength(contours[i], true);
                double epsilon   = perimeter * 0.01;

                Point[]   approx      = Cv2.ApproxPolyDP(contours[i], epsilon, true);
                Point[][] draw_approx = new Point[][] { approx };
                Cv2.DrawContours(dst, draw_approx, -1, new Scalar(255, 0, 0), 2, LineTypes.AntiAlias);

                for (int j = 0; j < approx.Length; j++)
                {
                    Cv2.Circle(dst, approx[j], 1, new Scalar(0, 0, 255), 3);
                }
            }

            Cv2.ImShow("dst", dst);
            Cv2.WaitKey(0);
            Cv2.DestroyAllWindows();
        }
Exemple #21
0
        public void findTextRegion(Mat dilation)
        {
            // 1. 查找轮廓
            OpenCvSharp.Point[][] contours;
            HierarchyIndex[]      hierarchly;
            Rect biggestContourRect = new Rect();

            Cv2.FindContours(dilation, out contours, out hierarchly, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);

            // 2. 筛选那些面积小的
            int i = 0;

            foreach (OpenCvSharp.Point[] contour in contours)
            {
                double area = Cv2.ContourArea(contour);

                //面积小的都筛选掉
                if (area < 1000)
                {
                    continue;
                }

                //轮廓近似,作用很小
                double epsilon = 0.001 * Cv2.ArcLength(contour, true);

                //找到最小的矩形
                biggestContourRect = Cv2.BoundingRect(contour);

                if (biggestContourRect.Height > (biggestContourRect.Width * 1.2))
                {
                    continue;
                }

                //画线
                mat.Rectangle(biggestContourRect, new Scalar(0, 255, 0), 2);
            }

            pictureBox1.Image = mat.ToBitmap();
            //Cv2.ImShow("img", mat);
        }
    void FindRect(out Point[] corners)
    {
        //頂点をnull(空)で初期化
        corners = null;
        //輪郭を構成する点と階層
        Point[][]        contours;
        HierarchyIndex[] h;
        //輪郭認識
        bin.FindContours(out contours, out h, RetrievalModes.External,
                         ContourApproximationModes.ApproxSimple);
        //面積が最大となる輪郭を処理対象とする
        double maxArea = 0;

        for (int i = 0; i < contours.Length; i++)
        {
            //輪郭の長さを算出
            double length = Cv2.ArcLength(contours[i], true);
            //多角形近似(全周の1%以内の誤差を許容)
            Point[] tmp = Cv2.ApproxPolyDP(contours[i], length * 0.01f, true);

            double area = Cv2.ContourArea(contours[i]);
            if (tmp.Length == 4 && area > maxArea)
            {
                maxArea = area;
                corners = tmp;
            }
        }
        //面積最大の輪郭cornersをbgr上に描画

        /*if (corners != null)
         * {
         *  bgr.DrawContours(new Point[][] { corners }, 0, Scalar.Red, 5);
         *  //各頂点の位置に円を描画
         *  for (int i = 0; i < corners.Length; i++)
         *  {
         *      bgr.Circle(corners[i], 20, Scalar.Blue, 5);
         *  }
         * }*/
    }
Exemple #23
0
        /// <summary>
        /// Filter the contours which was found by Canny algorithm
        /// </summary>
        /// <param name="canny">The result of Canny detector work</param>
        /// <returns>Filtered contours</returns>
        static List <Point[]> FindContoures(Mat canny)
        {
            Point[][]      contoures  = Cv2.FindContoursAsArray(canny, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
            List <Point[]> contoures2 = new List <Point[]>();

            foreach (var cont in contoures)
            {
                if (Math.Abs(Cv2.ContourArea(cont)) < 2)
                {
                    continue;                                       // square
                }
                if (Cv2.ArcLength(cont, true) < 15)
                {
                    continue;                                       // perimeter
                }
                if (cont.Length < 5)
                {
                    continue;                                       // number of pixels in the contour
                }
                contoures2.Add(cont);
            }
            return(contoures2);
        }
Exemple #24
0
        public List <Point2f> GetCorners()
        {
            if (mFrame != null)
            {
                Point[][]        contours  = new Point[][] { };
                HierarchyIndex[] hierarchy = new HierarchyIndex[] { };

                Cv2.FindContours(mFrame, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);

                Point[] rect      = new Point[] { };
                double  maxLength = 0;
                foreach (var item in contours)
                {
                    var perimeter = Cv2.ArcLength(item, true);
                    var approx    = Cv2.ApproxPolyDP(item, 0.015 * perimeter, true);

                    if (approx.Length == 4 && perimeter > maxLength)
                    {
                        maxLength = perimeter;
                        rect      = approx;
                    }
                }

                mResult = new List <Point2f>();
                foreach (var item in rect)
                {
                    mResult.Add(new Point2f(item.X, item.Y));
                }

                OrderPoints();

                return(mResult);
            }

            return(null);
        }
Exemple #25
0
        /// <summary>
        /// The magic is here
        /// </summary>
        private void CalculateOutput()
        {
            Mat matGray = null;

            // instead of regular Grayscale, we use BGR -> HSV and take Hue channel as
            // source
            if (Settings.GrayMode == ScannerSettings.ColorMode.HueGrayscale)
            {
                var   matHSV      = matInput_.CvtColor(ColorConversionCodes.RGB2HSV);
                Mat[] hsvChannels = matHSV.Split();
                matGray = hsvChannels[0];
            }
            // Alternative: just plain BGR -> Grayscale
            else
            {
                matGray = matInput_.CvtColor(ColorConversionCodes.BGR2GRAY);
            }

            // scale down if necessary
            var   matScaled = matGray;
            float sx = 1, sy = 1;

            if (Settings.Scale != 0)
            {
                if (matGray.Width > Settings.Scale)
                {
                    sx = (float)Settings.Scale / matGray.Width;
                }
                if (matGray.Height > Settings.Scale)
                {
                    sy = (float)Settings.Scale / matGray.Height;
                }

                matScaled = matGray.Resize(new Size(Math.Min(matGray.Width, Settings.Scale), Math.Min(matGray.Height, Settings.Scale)));
            }

            // reduce noise
            var matBlur = matScaled;

            if (Settings.NoiseReduction != 0)
            {
                int medianKernel = 11;

                // calculate kernel scale
                double kernelScale = Settings.NoiseReduction;
                if (0 == Settings.Scale)
                {
                    kernelScale *= Math.Max(matInput_.Width, matInput_.Height) / 512.0;
                }

                // apply scale
                medianKernel = (int)(medianKernel * kernelScale + 0.5);
                medianKernel = medianKernel - (medianKernel % 2) + 1;

                if (medianKernel > 1)
                {
                    matBlur = matScaled.MedianBlur(medianKernel);
                }
            }

            // detect edges with our 'adaptive' algorithm that computes bounds automatically with
            // image's mean value
            var matEdges = matBlur.AdaptiveEdges(Settings.EdgesTight);

            // now find contours
            Point[][]        contours;
            HierarchyIndex[] hierarchy;
            Cv2.FindContours(matEdges, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxNone, null);

            // check contours and drop those we consider "noise", all others put into a single huge "key points" map
            // also, detect all almost-rectangular contours with big area and try to determine whether they're exact match
            List <Point>   keyPoints      = new List <Point>();
            List <Point[]> goodCandidates = new List <Point[]>();
            double         referenceArea  = matScaled.Width * matScaled.Height;

            foreach (Point[] contour in contours)
            {
                double length = Cv2.ArcLength(contour, true);

                // drop mini-contours
                if (length >= 25.0)
                {
                    Point[] approx = Cv2.ApproxPolyDP(contour, length * 0.01, true);
                    keyPoints.AddRange(approx);

                    if (approx.Length >= 4 && approx.Length <= 6)
                    {
                        double area = Cv2.ContourArea(approx);
                        if (area / referenceArea >= Settings.ExpectedArea)
                        {
                            goodCandidates.Add(approx);
                        }
                    }
                }
            }

            // compute convex hull, considering we presume having an image of a document on more or less
            // homogeneous background, this accumulated convex hull should be the document bounding contour
            Point[] hull        = Cv2.ConvexHull(keyPoints);
            Point[] hullContour = Cv2.ApproxPolyDP(hull, Cv2.ArcLength(hull, true) * 0.01, true);

            // find best guess for our contour
            Point[] paperContour = GetBestMatchingContour(matScaled.Width * matScaled.Height, goodCandidates, hullContour);
            if (null == paperContour)
            {
                shape_     = null;
                dirty_     = false;
                matOutput_ = matInput_;
                return;
            }

            // exact hit - we have 4 corners
            if (paperContour.Length == 4)
            {
                paperContour = SortCorners(paperContour);
            }
            // some hit: we either have 3 points or > 4 which we can try to make a 4-corner shape
            else if (paperContour.Length > 2)
            {
                // yet contour might contain too much points: along with calculation inaccuracies we might face a
                // bended piece of paper, missing corner etc.
                // the solution is to use bounding box
                RotatedRect bounds      = Cv2.MinAreaRect(paperContour);
                Point2f[]   points      = bounds.Points();
                Point[]     intPoints   = Array.ConvertAll(points, p => new Point(Math.Round(p.X), Math.Round(p.Y)));
                Point[]     fourCorners = SortCorners(intPoints);

                // array.ClosestElement is not efficient but we can live with it since it's quite few
                // elements to search for
                System.Func <Point, Point, double> distance = (Point x, Point y) => Point.Distance(x, y);
                Point[] closest = new Point[4];
                for (int i = 0; i < fourCorners.Length; ++i)
                {
                    closest[i] = paperContour.ClosestElement(fourCorners[i], distance);
                }

                paperContour = closest;
            }

            // scale contour back to input image coordinate space - if necessary
            if (sx != 1 || sy != 1)
            {
                for (int i = 0; i < paperContour.Length; ++i)
                {
                    Point2f pt = paperContour[i];
                    paperContour[i] = new Point2f(pt.X / sx, pt.Y / sy);
                }
            }

            // un-wrap
            var  matUnwrapped        = matInput_;
            bool needConvertionToBGR = true;

            if (paperContour.Length == 4)
            {
                matUnwrapped = matInput_.UnwrapShape(Array.ConvertAll(paperContour, p => new Point2f(p.X, p.Y)));

                // automatic color converter
                bool convertColor = (ScannerSettings.DecolorizationMode.Always == Settings.Decolorization);
                if (ScannerSettings.DecolorizationMode.Automatic == Settings.Decolorization)
                {
                    convertColor = !IsColored(matUnwrapped);
                }

                // perform color conversion to b&w
                if (convertColor)
                {
                    matUnwrapped = matUnwrapped.CvtColor(ColorConversionCodes.BGR2GRAY);

                    // we have some constants for Adaptive, but this can be improved with some 'educated guess' for the constants depending on input image
                    if (ScannerSettings.ScanType.Adaptive == Settings.ColorThreshold)
                    {
                        matUnwrapped = matUnwrapped.AdaptiveThreshold(255, AdaptiveThresholdTypes.MeanC, ThresholdTypes.Binary, 47, 25);
                    }
                    // Otsu doesn't need our help, decent on it's own
                    else
                    {
                        matUnwrapped = matUnwrapped.Threshold(0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);
                    }
                }
                else
                {
                    needConvertionToBGR = false;
                }
            }

            // assign result
            shape_ = paperContour;

            matOutput_ = matUnwrapped;
            if (needConvertionToBGR)
            {
                matOutput_ = matOutput_.CvtColor(ColorConversionCodes.GRAY2BGR);                    // to make it compatible with input texture
            }
            // mark we're good
            dirty_ = false;
        }
Exemple #26
0
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            Mat src = new Mat(@"./t2.png");

            src = src.Resize(new Size(src.Width / 4, src.Height / 4));
            Cv2.ImShow("src", src);

            var binary = BinarizationMat(src);

            Cv2.ImShow("bin", binary);
            var fScreenMat = FindContoursMat(binary, src);

            fScreenMat = new Mat(fScreenMat,
                                 new Rect((int)(fScreenMat.Width * 0.025), (int)(fScreenMat.Height * 0.05),
                                          fScreenMat.Width - (int)(fScreenMat.Width * 0.05), fScreenMat.Height - (int)(fScreenMat.Height * 0.1)));
            Cv2.ImShow("Screen", fScreenMat);

            var m2 = SaturationGain(fScreenMat, 255);

            Cv2.ImShow("SaturationGain", m2);
            Cv2.CvtColor(m2, m2, ColorConversionCodes.BGR2GRAY);
            Mat b2 = m2.Threshold(100, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary);

            Cv2.FindContours(b2, out var contours, out var hierarchy, RetrievalModes.Tree,
                             ContourApproximationModes.ApproxSimple);
            Cv2.ImShow("b2", b2);
            var dst = fScreenMat;

            foreach (var itemPoint in contours)
            {
                Console.WriteLine("_________________");
                var epsilon = 0.0075 * Cv2.ArcLength(itemPoint, true);
                var approx  = Cv2.ApproxPolyDP(itemPoint, epsilon, true);
                if (approx.FirstOrDefault().X == 0 || approx.FirstOrDefault().Y == 0)
                {
                    continue;
                }

                Cv2.DrawContours(dst, new IEnumerable <Point>[] { approx }, -1, Scalar.Green, 3);

                Console.WriteLine("Approx Angle:" + approx.Length);
                if (approx.Length == 3)
                {
                    Cv2.PutText(dst, "Triangle", approx.FirstOrDefault(), HersheyFonts.HersheyComplex, 0.5, Scalar.Red);
                }
                else if (approx.Length == 4)
                {
                    var rect        = Cv2.BoundingRect(approx);
                    var rotatedRect = Cv2.MinAreaRect(approx);
                    var box         = Cv2.BoxPoints(rotatedRect);
                    Console.WriteLine(rotatedRect.Angle);
                    Cv2.PutText(dst, rotatedRect.Angle.ToString("0.0"), approx.LastOrDefault(),
                                HersheyFonts.HersheyComplex, 0.5, Scalar.Yellow);
                    Cv2.Line(dst, new Point(box[2].X, box[2].Y), new Point(box[0].X, box[0].Y), Scalar.White, 2);

                    var aspectRatio = rect.Width / rect.Height;
                    if (aspectRatio >= 0.9 && aspectRatio <= 1.1)
                    {
                        if ((Math.Abs(rotatedRect.Angle) >= 80 && Math.Abs(rotatedRect.Angle) <= 100) ||
                            Math.Abs(rotatedRect.Angle) <= 10)
                        {
                            Cv2.PutText(dst, "Square", approx.FirstOrDefault(), HersheyFonts.HersheyComplex, 0.5,
                                        Scalar.Red);
                        }
                        else
                        {
                            Cv2.PutText(dst, "Diamond", approx.FirstOrDefault(), HersheyFonts.HersheyComplex, 0.5,
                                        Scalar.Red);
                        }
                    }
                    else
                    {
                        Cv2.PutText(dst, "Rectangle", approx.FirstOrDefault(), HersheyFonts.HersheyComplex, 0.5,
                                    Scalar.Red);
                    }
                }
                else if (approx.Length == 5)
                {
                    Cv2.PutText(dst, "Pentagon", approx.FirstOrDefault(), HersheyFonts.HersheyComplex, 0.5, Scalar.Red);
                }
                else if (approx.Length == 10)
                {
                    Cv2.PutText(dst, "Star", approx.FirstOrDefault(), HersheyFonts.HersheyComplex, 0.5, Scalar.Red);
                }
                else if (approx.Length > 10)
                {
                    Cv2.PutText(dst, "Circle", approx.FirstOrDefault(), HersheyFonts.HersheyComplex, 0.5,
                                Scalar.Red);
                }

                foreach (var item in approx)
                {
                    Console.WriteLine(item.X + " " + item.Y);
                    Cv2.Circle(dst, item.X, item.Y, 5, new Scalar(255, 0, 0), 2, LineTypes.AntiAlias);
                    Cv2.ImShow("dst", dst);
                    //Cv2.WaitKey();
                }
                //foreach (var item in itemPoint) Console.WriteLine(item.X + " " + item.Y);
                //Console.WriteLine("_________________");
            }
            Cv2.ImShow("dst", dst);
            Cv2.WaitKey();
        }
Exemple #27
0
        private void LoadImage(string filePath)
        {
            try
            {
                using (Mat image = new Mat(filePath))
                    using (Mat resized = image.Resize(GetTargetSize(image.Size()))) //Scale the image, so we are working with something consistent
                    {
                        AddImage(resized);

                        using (Mat gray = resized.CvtColor(ColorConversionCodes.BGR2GRAY)) //Convert to gray scale since we don't want the color data
                            using (Mat blur = gray.GaussianBlur(new Size(5, 5), 0))        //Smooth the image to eliminate noise
                                using (Mat autoCanny = blur.AutoCanny())                   //Apply canny edge filter to find edges
                                    using (Mat structuringElement = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(9, 9)))
                                    {
                                        AddImage(autoCanny);

                                        //Smooth over small possible breaks in edges
                                        Cv2.Dilate(autoCanny, autoCanny, structuringElement);
                                        AddImage(autoCanny);
                                        Cv2.Erode(autoCanny, autoCanny, structuringElement);
                                        AddImage(autoCanny);

                                        //Change the RetrievalModes to CComp if you want internal polygons too, not just the outer most one.
                                        Point[][] contours = autoCanny.FindContoursAsArray(RetrievalModes.External, ContourApproximationModes.ApproxSimple);

                                        //Draw all of the found polygons for reference
                                        using (Mat allFound = resized.Clone())
                                        {
                                            for (int i = 0; i < contours.Length; i++)
                                            {
                                                Cv2.DrawContours(allFound, contours, i, Scalar.RandomColor(), 2);
                                            }
                                            AddImage(allFound);
                                        }

                                        //Find the largest polygons that four corners
                                        var found = (from contour in contours
                                                     let permimiter = Cv2.ArcLength(contour, true)
                                                                      let approx = Cv2.ApproxPolyDP(contour, 0.04 * permimiter, true)
                                                                                   where approx.Length == 4                     //Rectange
                                                                                   let area = Cv2.ContourArea(approx)
                                                                                              orderby area descending           //We are looking for the biggest thing
                                                                                              select approx).Take(3).ToArray(); //Grabbing three just for comparison

                                        //Colors the found polygons Green->Yellow->Red to indicate best matches.
                                        for (int i = 0; i < found.Length; i++)
                                        {
                                            Scalar color;
                                            switch (i)
                                            {
                                            case 0:
                                                color = Scalar.Green;
                                                break;

                                            case 1:
                                                color = Scalar.Yellow;
                                                break;

                                            case 2:
                                                color = Scalar.Red;
                                                break;

                                            default:
                                                color = Scalar.RandomColor();
                                                break;
                                            }

                                            resized.DrawContours(found, i, color, 3);
                                        }
                                        AddImage(resized);
                                    }
                    }
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.ToString());
            }

            Size GetTargetSize(Size size, int longSize = 512)
            {
                if (size.Width > size.Height)
                {
                    return(new Size(longSize, (int)(longSize * (double)size.Height / size.Width)));
                }
                return(new Size((int)(longSize * (double)size.Width / size.Height), longSize));
            }
        }
Exemple #28
0
        private void Test3(string img, double canny1, double canny2, double blur)
        {
            var tess = new TesseractEngine(@"./wwwroot/tessdata", "eng", EngineMode.LstmOnly);

            byte[] imageData = System.IO.File.ReadAllBytes(@"./wwwroot/images/" + img);
            Mat    img1      = Mat.FromImageData(imageData, ImreadModes.Color);
            //Convert the img1 to grayscale and then filter out the noise
            Mat gray1 = Mat.FromImageData(imageData, ImreadModes.Grayscale) /*.PyrDown().PyrUp()*/;

            //gray1 = gray1.GaussianBlur(new OpenCvSharp.Size(blur, blur), 0);

            //gray1 = gray1.AdaptiveThreshold(255, AdaptiveThresholdTypes.MeanC, ThresholdTypes.BinaryInv, (int)canny1, canny2); // 11,2 ; 75,10 ; 60,255

            gray1 = gray1.GaussianBlur(new Size(blur, blur), 0);

            //gray1 = gray1.Threshold(128, 255, ThresholdTypes.Binary);

            //Canny Edge Detector
            //Image<Gray, Byte> cannyGray = gray1.Canny(20, 50);
            //Image<Bgr, Byte> imageResult = img1.Copy();
            Mat cannyGray = gray1.Canny(canny1, canny2);
            //var cannyGray = gray1;

            // treba aj GaussianBlur, adaptiveThreshold

            Random r = new Random();

            //int lastY = 0;

            Point[][] contours;         //vector<vector<Point>> contours;

            HierarchyIndex[] hierarchy; //vector<Vec4i> hierarchy;
            //int draw = 0;

            Cv2.FindContours(cannyGray, out contours, out hierarchy, mode: RetrievalModes.Tree, method: ContourApproximationModes.ApproxSimple);

            Debug.WriteLine("po�et - " + contours.Length);

            Mat copy = img1.Clone();

            Cv2.DrawContours(copy, contours, -1, Scalar.Orange);
            var j = 0;

            while (j != -1)
            {
                var index = hierarchy[j];
                if (index.Parent != -1)
                {
                    j = index.Next;
                    continue;
                }

                Scalar scalar = Scalar.FromRgb(r.Next(0, 255), r.Next(0, 255), r.Next(0, 255));
                Cv2.DrawContours(copy, contours, j, scalar);

                var     edges      = contours[j];
                Point[] contoursAp = Cv2.ApproxPolyDP(edges, Cv2.ArcLength(edges, true) * 0.01, true);
                //Debug.WriteLine(j + "," + contoursAp.Length);

                /*var rect = Cv2.BoundingRect(edges);
                 * var roi2 = img1.Clone(rect);
                 * roi2.SaveImage("pozri-" + j + ".png");*/

                j = index.Next;
            }

            var m = 0;

            foreach (var c in contours)
            {
                //var rect = Cv2.BoundingRect(c);
                //var roi2 = img1.Clone(rect);
                //roi2.SaveImage("pozri-" + m + ".png");
                m++;
            }


            copy.SaveImage("wwwroot/images/output.png");
        }
        private Mat FindContoursAndDraw(Bitmap originalMap, string objectName, int minArea = 500, int maxArea = 10000)
        {
            //var houghBitmap = HoughTransform(originalMap);
            //var invertedHoughBitmap = InvertImage(houghBitmap);
            Mat originalMat = BitmapConverter.ToMat(originalMap);
            //Mat invertedHoughMat = BitmapConverter.ToMat(invertedHoughBitmap);
            Mat blackWhiteMat = new Mat();
            Mat edgesMat      = new Mat();

            Cv2.CvtColor(originalMat, blackWhiteMat, ColorConversionCodes.BGRA2GRAY);
            if (MapObjectsColors.GetInstance().Tight.Contains(objectName))
            {
                Bitmap edgesMap = BitmapConverter.ToBitmap(blackWhiteMat);
                edgesMap = ImageFilter.SobelFilter(edgesMap, grayscale: true);
                edgesMat = BitmapConverter.ToMat(edgesMap);
                Cv2.CvtColor(edgesMat, edgesMat, ColorConversionCodes.BGRA2GRAY);
            }
            else
            {
                Cv2.Canny(blackWhiteMat, edgesMat, 50, 100);
            }


            OpenCvSharp.Point[][] contours;
            HierarchyIndex[]      hierarchyIndexes;
            Cv2.FindContours(
                edgesMat,
                out contours,
                out hierarchyIndexes,
                mode: RetrievalModes.CComp,
                method: ContourApproximationModes.ApproxSimple);



            var componentCount = 0;
            var contourIndex   = 0;
            var objectDict     = mapObjects.getObjectDictionary();

            if (contours.Length != 0)
            {
                if (objectDict.ContainsKey(objectName))
                {
                    objectDict[objectName] = contours;
                }
                else
                {
                    objectDict.Add(objectName, contours);
                }
                while ((contourIndex >= 0))
                {
                    var contour          = contours[contourIndex];
                    var boundingRect     = Cv2.BoundingRect(contour);
                    var boundingRectArea = boundingRect.Width * boundingRect.Height;
                    var ca  = Cv2.ContourArea(contour) * Convert.ToDouble(scaleBox.SelectedItem) / 100;
                    var cal = Cv2.ArcLength(contour, closed: true) * Convert.ToDouble(scaleBox.SelectedItem) / 100;

                    //if (boundingRectArea > minArea)
                    //{

                    Cv2.PutText(originalMat, $"A:{ca.ToString("#.##")} km2", new OpenCvSharp.Point(boundingRect.X, boundingRect.Y + 10), HersheyFonts.HersheyPlain, 1, Scalar.White, 1);
                    Cv2.PutText(originalMat, $"L:{cal.ToString("#.##")} km", new OpenCvSharp.Point(boundingRect.X, boundingRect.Y + 25), HersheyFonts.HersheyPlain, 1, Scalar.White, 1);


                    //}


                    //Cv2.DrawContours(
                    //    originalMat,
                    //    contours,
                    //    contourIndex,
                    //    color: Scalar.All(componentCount + 1),
                    //    thickness: -1,
                    //    lineType: LineTypes.Link8,
                    //    hierarchy: hierarchyIndexes,
                    //    maxLevel: int.MaxValue);

                    componentCount++;


                    contourIndex = hierarchyIndexes[contourIndex].Next;
                }
            }

            return(originalMat);
        }
        private Dictionary <string, List <ImageObjectParameters> > FragmentObjectsSizeAnalyze(Dictionary <string, bool> presenceObjectsDict)
        {
            var imageBitmap      = new Bitmap(ImageFile.GetInstance().Image);
            var objectParameters = new Dictionary <string, List <ImageObjectParameters> >();

            if (!coordinatesAnalyze.IsEmpty)
            {
                var xstart          = coordinatesAnalyze.X - RectSide / 2;
                var ystart          = coordinatesAnalyze.Y - RectSide / 2;
                var xend            = coordinatesAnalyze.X + RectSide / 2;
                var yend            = coordinatesAnalyze.Y + RectSide / 2;
                var xmin            = xstart > 0 ? xstart : 0;
                var ymin            = ystart > 0 ? ystart : 0;
                var xmax            = xend < Width ? xend : Width;
                var ymax            = yend < Height ? yend : Height;
                var newWidth        = xmax - xmin;
                var newHeight       = ymax - ymin;
                var objectsDict     = mapObjects.getObjectDictionary();
                var colorsObject    = MapObjectsColors.GetInstance();
                var relief          = colorsObject.Relief;
                var tight           = colorsObject.Tight;
                var presenceObjects = presenceObjectsDict.Where(obj => obj.Value).Where(obj => !relief.Contains(obj.Key)).Select(obj => obj.Key).ToList();

                foreach (var objectName in presenceObjects)
                {
                    if (objectsDict.ContainsKey(objectName))
                    {
                        objectParameters.Add(objectName, new List <ImageObjectParameters>());
                        var contours = objectsDict[objectName];
                        foreach (var contour in contours)
                        {
                            var matchContour = contour.Any(point => point.X > xstart && point.X <xend && point.Y> ystart && point.Y < yend);

                            if (matchContour)
                            {
                                var cArea   = Cv2.ContourArea(contour) * Convert.ToDouble(scaleBox.SelectedItem) / 100;
                                var cLength = Cv2.ArcLength(contour, closed: true) * Convert.ToDouble(scaleBox.SelectedItem) / 100;

                                objectParameters[objectName].Add(new ImageObjectParameters {
                                    ArcLength = cLength, Area = cArea
                                });
                            }
                        }
                    }
                }
            }
            else
            {
                MessageBox.Show("Выберите участок карты!", "Информация", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            using (StreamWriter writer = new StreamWriter($@"{ProjectDir}\matchPoints.txt"))
            {
                foreach (var elem in objectParameters)
                {
                    writer.WriteLine(elem.Key);
                    foreach (var item in elem.Value)
                    {
                        writer.WriteLine($"Area = {item.Area}, ArcLength = {item.ArcLength}");
                    }
                }
            }
            return(objectParameters);
        }