/// <summary>
        ///
        /// </summary>
        /// <param name="image"></param>
        /// <param name="sides"></param>
        /// <returns></returns>
        public static FoundItem[] FindNSidedElement(System.Drawing.Bitmap image, int sides, bool debugMode = false)
        {
            List <FoundItem> itemsFound = new List <FoundItem>();
            bool             closed     = false;

            using (Mat srcColor = image.ToMat())
                using (Mat mOutput = new Mat(srcColor.Rows, srcColor.Cols, MatType.CV_8UC4))
                    using (var grey = srcColor.CvtColor(ColorConversionCodes.BGRA2GRAY))
                        using (var blueMask = srcColor.InRange(new Scalar(204, 72, 63), new Scalar(204, 72, 63)))
                        {
                            //TODO:This may need to be refactored not sure if objects that need to be disposed are missing
                            var src = grey.SetTo(new Scalar(0, 0, 0), blueMask);
                            int maximumTargetWidth    = (int)Math.Round(srcColor.Width * .9, 0);
                            int overAllImageArcLength = src.Width * 2 + src.Height * 2;
                            if (debugMode)
                            {
                                Console.WriteLine($"overAllImageArcLength {overAllImageArcLength}");
                            }
                            srcColor.CopyTo(mOutput);
                            Cv2.FindContours(
                                image: src,
                                contours: out OpenCvSharp.Point[][] contours,
                                hierarchy: out HierarchyIndex[] outputArray,
                                mode: RetrievalModes.Tree,
                                method: ContourApproximationModes.ApproxTC89KCOS);

                            for (int i = 0; i < contours.Length; i++)
                            {
                                var    mat         = contours[i];
                                double distance    = 0.01 * Cv2.ArcLength(mat, closed);
                                var    approx      = Cv2.ApproxPolyDP(mat, distance, closed);
                                double sidesLength = Cv2.ArcLength(approx, closed);

                                if (sidesLength > 1.0 && outputArray[i].Child == -1)
                                {
                                    if (debugMode)
                                    {
                                        Console.WriteLine($"i: {i} mat.Length:{mat.Length} sidesLength: {sidesLength} mat length {Cv2.ArcLength(mat, closed)} distance {distance}");
                                        Console.WriteLine($"outputArray[i].Child:{outputArray[i].Child} outputArray[i].Next:{outputArray[i].Next} outputArray[i].Parent:{outputArray[i].Parent}outputArray[i].Previous: {outputArray[i].Previous}");
                                    }
                                    string additionalDescriptor = "";
                                    Scalar scalar = new Scalar();
                                    scalar = Scalar.Red;
                                    Rect rect = Cv2.BoundingRect(mat);
                                    if (mat.Length == sides && rect.Width <= maximumTargetWidth)
                                    {
                                        itemsFound.Add(new FoundItem()
                                        {
                                            Arc    = mat,
                                            Width  = rect.Width,
                                            Height = rect.Height
                                        });
                                        additionalDescriptor = "Target";
                                        scalar = Scalar.Pink;
                                        if (debugMode)
                                        {
                                            Console.WriteLine("Target Found");
                                        }
                                    }
                                    if (debugMode)
                                    {
                                        Cv2.DrawContours(
                                            mOutput,
                                            contours,
                                            contourIdx: i,
                                            color: scalar,
                                            thickness: 2,
                                            lineType: LineTypes.Link8,
                                            hierarchy: outputArray,
                                            maxLevel: 0);
                                        Point middle = new Point();
                                        middle.X = mat[0].X + 10;
                                        middle.Y = mat[0].Y + 30;
                                        Cv2.PutText(mOutput, $"{i} {additionalDescriptor}", middle, HersheyFonts.HersheyPlain, 1.0, Scalar.Black, 2);
                                    }
                                }
                            }
                            if (debugMode)
                            {
                                srcColor.SaveImage(@"c:\drop\source.png");
                                mOutput.SaveImage(@"c:\drop\moutput.png");
                                src.SaveImage(@"c:\drop\greyscale.png");
                                using (new Window("Contour Source", srcColor))
                                    using (new Window("Contours Found", mOutput))
                                        using (new Window("Modified grey scale", src))
                                            Cv2.WaitKey();
                            }
                            src.Dispose();
                            return(itemsFound.ToArray());
                        }
        }
Exemple #2
0
        public async void Contours(SoftwareBitmap input, SoftwareBitmap output, Algorithm algorithm)
        {
            if (algorithm.AlgorithmName == "Contours")
            {
                using Mat mInput  = SoftwareBitmap2Mat(input);
                using Mat mOutput = new Mat(mInput.Rows, mInput.Cols, MatType.CV_8UC4);
                mInput.CopyTo(mOutput);
                using Mat gray  = mInput.CvtColor(ColorConversionCodes.BGRA2GRAY);
                using Mat edges = gray.Canny((double)algorithm.AlgorithmProperties[6].CurrentValue, (double)algorithm.AlgorithmProperties[7].CurrentValue);

                Cv2.FindContours(
                    image: edges,
                    contours: out OpenCvSharp.Point[][] contours,
                    hierarchy: out HierarchyIndex[] outputArray,
                    mode: (RetrievalModes)algorithm.AlgorithmProperties[0].CurrentValue,
                    method: (ContourApproximationModes)algorithm.AlgorithmProperties[1].CurrentValue,
                    offset: (Point)algorithm.AlgorithmProperties[2].CurrentValue);

                int maxLen = 0;
                int maxIdx = -1;

                for (int i = 0; i < contours.Length; i++)
                {
                    if (contours[i].Length > maxLen)
                    {
                        maxIdx = i;
                        maxLen = contours[i].Length;
                    }

                    if (contours[i].Length > (int)algorithm.AlgorithmProperties[8].CurrentValue)
                    {
                        Cv2.DrawContours(
                            mOutput,
                            contours,
                            contourIdx: i,
                            color: (Scalar)algorithm.AlgorithmProperties[3].CurrentValue,
                            thickness: (int)algorithm.AlgorithmProperties[4].CurrentValue,
                            lineType: (LineTypes)algorithm.AlgorithmProperties[5].CurrentValue,
                            hierarchy: outputArray,
                            maxLevel: 0);
                    }
                }
                if (maxIdx != -1)
                {
                    var res = Cv2.ApproxPolyDP(contours[maxIdx], 1, true);
                    //Cv2.DrawContours(
                    //    mOutput,
                    //    contours,
                    //    maxIdx,
                    //    (Scalar)algorithm.algorithmProperties[3].CurrentValue,
                    //    (int)algorithm.algorithmProperties[4].CurrentValue,
                    //    (LineTypes)algorithm.algorithmProperties[5].CurrentValue,
                    //    outputArray,
                    //    0);
                    ////return Cv2.ContourArea(res);
                }

                Mat2SoftwareBitmap(mOutput, output);

                // Must run on UI thread.  The winrt container also needs to be set.
                if (App.container != null)
                {
                    await App.container.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    {
                        Cv2.ImShow("Contours", mOutput);
                    });
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// 对外函数,用于识别一个图片 detect one frame
        /// </summary>
        /// <param name="frame">一个彩色图片; a RGB picture</param>
        /// <returns>一个ArrayList,包含结果;results of detections</returns>
        public ArrayList detect(Mat frame)
        {
            Mat gray = new Mat();

            Cv2.CvtColor(frame, gray, ColorConversionCodes.RGB2GRAY);
            Mat dst   = new Mat();
            Mat gauss = new Mat();

            Cv2.GaussianBlur(gray, gauss, new Size(3, 3), this.sigma);
            switch (this.threshold)
            {
            case "canny":
                Cv2.Canny(gauss, dst, 150, 400, 3);
                break;

            case "adaptive":
                Cv2.AdaptiveThreshold(gauss, dst, 255, AdaptiveThresholdTypes.GaussianC, ThresholdTypes.BinaryInv, 9, 5);
                break;

            default:
                Cv2.Canny(gauss, dst, 150, 400, 3);
                break;
            }

            Point[][]        contours;
            HierarchyIndex[] hierarchy;
            Cv2.FindContours(dst, out contours, out hierarchy, OpenCvSharp.RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, null);
            if (this.debug == true)
            {
                Mat copyimg = new Mat();
                frame.CopyTo(copyimg);
                copyimg.DrawContours(contours, -1, new Scalar(0, 255, 0));
                using (new Window("contours image", copyimg))
                {
                    Cv2.WaitKey();
                }
            }
            ArrayList hulls = new ArrayList();
            ArrayList quads = new ArrayList();

            for (int i = 0; i < contours.Length; i++)
            {
                var contour = contours[i];//取出多边形 get polygon
                if (contour.Length >= 4 && hierarchy[i].Previous < 0)
                {
                    var area = Cv2.ContourArea(contour);//求多边形面积 get contour`s area
                    if (area > this.minarea)
                    {
                        var hull = Cv2.ConvexHull(contour);//求出凸包 get hull
                        if ((area / Cv2.ContourArea(hull)) > 0.8)
                        {
                            hulls.Add(hull);
                            var quad = Cv2.ApproxPolyDP(hull, 9, true);//根据凸包计算出四边形 get quad
                            if (quad.Length == 4)
                            {
                                var areaqued = Cv2.ContourArea(quad);
                                var areahull = Cv2.ContourArea(hull);
                                if (areaqued / areahull > 0.8 && areahull >= areaqued)
                                {
                                    quads.Add(quad);
                                }
                            }
                        }
                    }
                }
            }
            if (this.debug == true)
            {
                Mat copyimg = new Mat();
                frame.CopyTo(copyimg);
                foreach (Point[] item in quads)
                {
                    Point[][] temp = new Point[1][];
                    temp[0] = item;
                    copyimg.DrawContours(temp, -1, new Scalar(0, 255, 0));
                }
                using (new Window("contours image", copyimg))
                {
                    Cv2.WaitKey();
                }
                Console.WriteLine("quads count" + quads.Count);
            }

            ArrayList detections  = new ArrayList();
            ArrayList points      = new ArrayList();
            ArrayList whitepoints = new ArrayList();

            //进行点quad点的提取
            foreach (Point[] quad in quads)
            {
                int       dd         = this.tagFamily.getBlackBorder() * 2 + this.tagFamily.getEdge();
                ArrayList blackvalue = new ArrayList();
                ArrayList whitevalue = new ArrayList();

                for (int iy = 0; iy < dd; iy++)
                {
                    for (int ix = 0; ix < dd; ix++)
                    {
                        double x           = (ix + 0.5) / (dd * 1.0);
                        double y           = (iy + 0.5) / (dd * 1.0);
                        var    polatepoint = _interpolate(quad, new Point2d(x, y));
                        points.Add(polatepoint);
                        var value = gray.At <byte>(polatepoint.X, polatepoint.Y);
                        if ((iy == 0 || iy == dd - 1) || (ix == 0 || ix == dd - 1))
                        {
                            blackvalue.Add(value);
                        }
                        else if ((iy == 1 || iy == dd - 2) || (ix == 1 || ix == dd - 2))
                        {
                            whitevalue.Add(value);
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
                long tagcode   = 0;
                var  threshold = 0.5 * (_average(blackvalue) + _average(whitevalue));
                for (int iy = 0; iy < dd; iy++)
                {
                    for (int ix = 0; ix < dd; ix++)
                    {
                        if ((iy == 0 || iy == dd - 1) || (ix == 0 || ix == dd - 1))
                        {
                            continue;
                        }
                        double newx      = (ix + 0.5) / dd * 1.0;
                        double newy      = (iy + 0.5) / dd * 1.0;
                        Point  point     = _interpolate(quad, new Point2d(newx, newy));
                        int    grayvalue = gray.At <byte>(point.X, point.Y);
                        tagcode = tagcode << 1;
                        if (grayvalue > threshold)
                        {
                            tagcode |= 1;
                            whitepoints.Add(point);
                        }
                    }
                }

                Detector decoderesult = this.tagFamily._decode(tagcode);
                if (decoderesult.good == true)
                {
                    decoderesult.addPoint(quad);
                    detections.Add(decoderesult);
                }
            }
            if (this.debug == true)
            {
                Mat copyimg = new Mat();
                frame.CopyTo(copyimg);
                foreach (Point item in points)
                {
                    Point tpoint = new Point(item.Y, item.X);
                    copyimg.Circle(tpoint, 1, new Scalar(0, 0, 255));
                }
                using (new Window("quad", copyimg))
                {
                    Cv2.WaitKey();
                }

                Mat copyimg2 = new Mat();
                frame.CopyTo(copyimg2);
                foreach (Point item in whitepoints)
                {
                    Point tpoint = new Point(item.Y, item.X);
                    copyimg2.Circle(tpoint, 1, new Scalar(0, 0, 255));
                }
                using (new Window("quad", copyimg2))
                {
                    Cv2.WaitKey();
                }
            }
            return(detections);
        }
        static void Main(string[] args)
        {
            var afWindow = new Window("Annotated Frame");
            var cdWindow = new Window("Contour Delta");

            VideoCapture capture = new VideoCapture("rtsp://10.0.0.104:554/1/h264major");

            int         frameIndex = 0;
            Mat         lastFrame  = new Mat();
            VideoWriter writer     = null;

            while (capture.IsOpened())
            {
                Mat frame = new Mat();

                if (!capture.Read(frame))
                {
                    break;
                }

                Mat grayFrame, dilatedFrame, edges, deltaCopyFrame = new Mat();
                Mat deltaFrame = new Mat();

                try
                {
                    frame = frame.Resize(new Size(0, 0), 0.33, 0.33);
                }
                catch (Exception e)
                {
                }
                grayFrame = frame.CvtColor(ColorConversionCodes.BGR2GRAY);
                grayFrame = grayFrame.GaussianBlur(new Size(21, 21), 0);

                if (frameIndex == 0)
                {
                    frameIndex++;

                    afWindow.Move(0, 0);
                    cdWindow.Move(0, grayFrame.Size().Height);

                    string fileName = "C:\\temp\\capture.avi";

                    string fcc = capture.FourCC;
                    double fps = capture.Get(CaptureProperty.Fps);

                    Size frameSize = new Size(grayFrame.Size().Width, grayFrame.Size().Height);

                    writer = new VideoWriter(fileName, fcc, fps, frameSize);
                    Console.Out.WriteLine("Frame Size = " + grayFrame.Size().Width + " x " + grayFrame.Size().Height);

                    if (!writer.IsOpened())
                    {
                        Console.Out.WriteLine("Error Opening Video File For Write");
                        return;
                    }

                    lastFrame = grayFrame;
                    continue;
                }
                else if (frameIndex % 50 == 0)
                {
                    frameIndex = 0;
                    lastFrame  = grayFrame;
                }

                frameIndex++;

                Cv2.Absdiff(lastFrame, grayFrame, deltaFrame);
                Cv2.Threshold(deltaFrame, deltaFrame, 50, 255, ThresholdTypes.Binary);

                int iterations = 2;
                Cv2.Dilate(deltaFrame, deltaFrame, new Mat(), new Point(), iterations);

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

                Cv2.FindContours(deltaFrame, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple, new Point(0, 0));

                var            countorsPoly = new Point[contours.Length][];
                List <Rect>    boundRect    = new List <Rect>();
                List <Point2f> center       = new List <Point2f>();
                List <float>   radius       = new List <float>();

                for (int i = 0; i < contours.Length; i++)
                {
                    countorsPoly[i] = Cv2.ApproxPolyDP(contours[i], 3, true);
                    if (countorsPoly.Length != 0)
                    {
                        boundRect.Insert(i, Cv2.BoundingRect(countorsPoly[i]));
                        Cv2.MinEnclosingCircle(countorsPoly[i], out Point2f centerObj, out float radiusObj);
                        center.Insert(i, centerObj);
                        radius.Insert(i, radiusObj);
                    }
                }

                for (int i = 0; i < contours.Length; i++)
                {
                    if (countorsPoly.Length != 0)
                    {
                        Scalar color = new Scalar(54, 67, 244);
                        //Cv2.DrawContours(frame, countorsPoly, i, color, 1, LineTypes.Link8, new HierarchyIndex[] { }, 0, new Point());
                        Cv2.Rectangle(frame, boundRect[i].TopLeft, boundRect[i].BottomRight, color, 2, LineTypes.Link8, 0);
                        //Cv2.Circle(frame, (int)center[i].X, (int)center[i].Y, (int)radius[i], color, 2, LineTypes.Link8, 0);
                    }
                }

                afWindow.ShowImage(frame);
                cdWindow.ShowImage(deltaFrame);

                writer.Write(frame);

                switch (Cv2.WaitKey(1))
                {
                case 27:
                    capture.Release();
                    writer.Release();
                    return;
                }
            }
        }
        //MyMSER
        static List <Point[][]> My_MSER(int my_delta, int my_minArea, int my_maxArea, double my_maxVariation, Mat img, ref Mat img_rgb, int big_flag)
        {
            //img.SaveImage("img_detected.jpg");

            List <Point[][]> final_area = new List <Point[][]>();

            Point[][] contours;
            Rect[]    bboxes;
            MSER      mser = MSER.Create(delta: my_delta, minArea: my_minArea, maxArea: my_maxArea, maxVariation: my_maxVariation);

            mser.DetectRegions(img, out contours, out bboxes);

            //====================================Local Majority Vote

            // to speed up, create four shift image first
            var shift_mat = set_shift_image(ref img);

            Mat[] neighbor_img = new Mat[4];
            for (int i = 0; i < 4; i++)
            {
                neighbor_img[i] = new Mat();
                var imageCenter = new Point2f(img.Cols / 2f, img.Rows / 2f);
                var rotationMat = Cv2.GetRotationMatrix2D(imageCenter, 100, 1.3);
                Cv2.WarpAffine(img, neighbor_img[i], shift_mat[i], img.Size());
                //neighbor_img[i].SaveImage("./shift_image" + i + ".jpg");
            }

            //for each contour, apply local majority vote
            foreach (Point[] now_contour in contours)
            {
                OpenCvSharp.Point[][] temp = new Point[1][];

                Point[] Convex_hull = Cv2.ConvexHull(now_contour);
                Point[] Approx      = Cv2.ApproxPolyDP(now_contour, 0.5, true);

                RotatedRect rotateRect = Cv2.MinAreaRect(Approx);
                //Debug
                //Console.WriteLine(Cv2.ContourArea(Approx)+" "+ rotateRect.Size.Height / rotateRect.Size.Width+ " "+rotateRect.Size.Width / rotateRect.Size.Height);

                if (Cv2.ContourArea(Approx) > 10000 || (Cv2.ContourArea(Approx) < stop1_inner_defect_size_min || ((rotateRect.Size.Height / rotateRect.Size.Width)) > stop1_arclength_area_ratio || ((rotateRect.Size.Width / rotateRect.Size.Height)) > stop1_arclength_area_ratio))
                {
                    continue;
                }

                //======================intensity in the area
                temp[0] = Approx;
                double mean_in_area_temp = 0, min_in_area_temp = 0;
                Mat    mask_img_temp = Mat.Zeros(img.Size(), MatType.CV_8UC1);
                Cv2.DrawContours(mask_img_temp, temp, -1, 255, thickness: -1);//notice the difference between temp = Approx and Convex_hull
                mean_in_area_temp = img.Mean(mask_img_temp)[0];
                img.MinMaxLoc(out min_in_area_temp, out _, out _, out _, mask_img_temp);
                //Console.WriteLine(min_in_area_temp + " " + mean_in_area_temp);
                if (min_in_area_temp > 100 || mean_in_area_temp > 130)
                {
                    continue;
                }

                // Convex hull
                temp[0] = Approx;
                if (big_flag == 0)//small area: local majority vote
                {
                    //Cv2.Polylines(img_rgb, temp, true, new Scalar(0, 0, 255), 1);
                    //inside the area
                    double mean_in_area = 0, min_in_area = 0;
                    Mat    mask_img = Mat.Zeros(img.Size(), MatType.CV_8UC1);
                    Cv2.DrawContours(mask_img, temp, -1, 255, thickness: -1);//notice the difference between temp = Approx and Convex_hull
                    mean_in_area = img.Mean(mask_img)[0];
                    img.MinMaxLoc(out min_in_area, out _, out _, out _, mask_img);

                    //Console.WriteLine(min_in_area + " " + mean_in_area);

                    //test

                    /*
                     * Mat mask2 = img.LessThan(230);
                     * for (int i = 0; i < img.Cols; i++) {
                     *  for (int j = 0; j < img.Rows; j++)
                     *      if(mask2.At<bool>(i, j)==false)
                     *          Console.Write(mask2.At<bool>(i,j)+ " ");
                     *
                     *  Console.Write("\n");
                     *
                     * }
                     */
                    //neighbor
                    double[] mean_neighbor = { 255, 255, 255, 255 };
                    double[] min_neighbor  = { 255, 255, 255, 255 };
                    for (int i = 0; i < 4; i++)
                    {
                        //先把 img > 230 的變成 0,再餵進 shift 裡面
                        //先把 mask 乘上另一個mask(>230的mask)
                        //Mat mask_neighbor_img = neighbor_img[i].GreaterThan(0);
                        //Console.WriteLine(mask_neighbor_img.At<int>(0,1));
                        // create final mask
                        Mat mask2 = neighbor_img[i].LessThan(225).ToMat();
                        mask2.ConvertTo(mask2, MatType.CV_8U, 1.0 / 255.0);

                        Mat mask_final = Mat.Zeros(img.Size(), MatType.CV_8UC1);
                        mask_img.CopyTo(mask_final, mask2);

                        //mask_final.SaveImage("./mask" + i + ".jpg");

                        mean_neighbor[i] = neighbor_img[i].Mean(mask_final)[0];
                        //compute min:
                        //neighbor_img[i].MinMaxLoc(out min_neighbor[i], out _, out _, out _, mask_img);
                        //Console.WriteLine(min_neighbor[i] + " " + mean_neighbor[i]);
                    }
                    int vote = 0;
                    for (int i = 0; i < 4; i++)
                    {
                        if (mean_in_area > mean_neighbor[i])
                        {
                            vote++;
                        }
                    }
                    if (vote > 2 || min_in_area > 100 || mean_in_area > 130)
                    {
                        //Debug
                        //Console.WriteLine(vote + " " + min_in_area + " ", min_in_area);
                        continue;
                    }
                    else
                    {
                        //Cv2.Polylines(img_rgb, temp, true, new Scalar(0, 0, 255), 1);
                        //Console.WriteLine("--");
                        final_area.Add(temp);
                    }
                }
                else
                {
                    //Console.WriteLine("--");
                    //Cv2.Polylines(img_rgb, temp, true, new Scalar(0, 0, 255), 1);
                    final_area.Add(temp);
                }
            }
            Console.WriteLine(final_area.Count);
            return(final_area);
        }
    public List <Contorno> Procesar(Mat matImagenFuente, Texture2D[] texturesObserve = null)
    {
        var contornos = new List <Contorno>();

        Iniciar();

        var escalaReduccionImagen = 1f;

        if (matImagenFuente.Width > SizeLimit || matImagenFuente.Height > SizeLimit)
        {
            escalaReduccionImagen = Mathf.Min(SizeLimit / matImagenFuente.Width, SizeLimit / matImagenFuente.Height);
            Cv2.Resize(matImagenFuente, matImagenLowRes, new Size(matImagenFuente.Width * escalaReduccionImagen, matImagenFuente.Height * escalaReduccionImagen));
        }
        else
        {
            Cv2.Resize(matImagenFuente, matImagenLowRes, matImagenFuente.Size());
        }

        Cv2.CvtColor(matImagenLowRes, matImagenLowRes, ColorConversionCodes.RGB2GRAY);
        if (UsarCanny)
        {
            Cv2.Canny(matImagenLowRes, matBin, CannyBajo, CannyAlto, ApertureCanny, CannyL2);
        }
        else
        {
            Cv2.Threshold(matImagenLowRes, matBin, Threshold, 255, ThreshType);
        }
        if (CannyDilate)
        {
            Cv2.Dilate(matBin, matBin, matClean);
        }
        if (CannyErode)
        {
            Cv2.Erode(matBin, matBin, matClean);
        }
        //borde extra por las dudas si hay ruido en lso bordes
        Cv2.Rectangle(matBin, new Point(0, 0), new Point(matBin.Width, matBin.Height), new Scalar(0), Border);
        if (texturesObserve != null)
        {
            texturesObserve[0] = OpenCvSharp.Unity.MatToTexture(matBin, texturesObserve[0]);
        }

        Point[][]        puntos;
        HierarchyIndex[] jerarquia;
        Cv2.FindContours(matBin, out puntos, out jerarquia, RetrievalModes.Tree, ContourApproximationModes.ApproxTC89KCOS);

        if (EpsilonDeAproximacion != ConfigExtraerContornoFlor.EpsilonDeAproximacion.NoAproximar)
        {
            var epsilon = ValorDeEpsilon;
            for (int i = 0, n = puntos.Length; i < n; i++)
            {
                if (EpsilonDeAproximacion == ConfigExtraerContornoFlor.EpsilonDeAproximacion.EpsilonRelativoArcLen)
                {
                    epsilon *= Cv2.ArcLength(puntos[i], true);
                }
                puntos[i] = Cv2.ApproxPolyDP(puntos[i], epsilon, true);
                epsilon   = ValorDeEpsilon;
            }
        }

        if (jerarquia.Length == 0)
        {
            return(null);
        }
        contornos = OrdenarContornosEvitandoCanny(puntos, jerarquia, 0, contornos);

        if (texturesObserve != null)
        {
            Cv2.CvtColor(matImagenLowRes, matImagenLowRes, ColorConversionCodes.GRAY2RGB);

            foreach (var cont in contornos)
            {
                var dibujar = new[] { cont.vertices.Select(v => new Point(v.x, v.y)) };
                Cv2.DrawContours(matImagenLowRes, dibujar, -1, new Scalar(cont.color.b * 255, cont.color.g * 255, cont.color.r * 255), Mathf.CeilToInt(Mathf.Min(matImagenLowRes.Width * 0.005f, 1)));

                dibujar = cont.contornosInternos.Select(c => c.vertices.Select(v => new Point(v.x, v.y))).ToArray();
                Cv2.DrawContours(matImagenLowRes, dibujar, -1, new Scalar(cont.color.b * 100, cont.color.g * 100, cont.color.r * 100), Mathf.CeilToInt(Mathf.Min(matImagenLowRes.Width * 0.005f, 1)));
            }
            texturesObserve[1] = OpenCvSharp.Unity.MatToTexture(matImagenLowRes, texturesObserve[1]);
        }

        return(contornos);
    }
Exemple #7
0
        /// <summary>
        /// Takes blobs information based on colors in <see cref="hsv"/> list and then sends the info through UDP.
        /// </summary>
        /// <param name="sourceImage">Image in Mat format.</param>
        /// <returns>Image in Mat format.</returns>
        private Mat Renderer(Mat sourceImage)
        {
            Mat dstNoisy = src;
            Mat dstClear = new Mat();
            Mat dst      = new Mat();
            Mat element  = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(2 * MorphValue + 1, 2 * MorphValue + 1));

            Cv2.Blur(dstNoisy, dstClear, new Size(9, 9));

            Cv2.CvtColor(dstClear, dst, ColorConversionCodes.BGR2HSV); // Convert BGR to HSV.

            Mat dstThreshed = new Mat();
            Mat dstPreview  = new Mat();

            if (hsv.Count > 0)
            {
                int  blobCount = 1;
                bool theFirst  = true;

                foreach (int[] scal in hsv)
                {
                    if (theFirst)
                    {
                        Cv2.InRange(dst, new Scalar(scal[0] - 10, scal[1], scal[3]), new Scalar(scal[0] + 10, scal[2], scal[4]), dstPreview);
                        theFirst = false;
                    }
                    else
                    {
                        Mat dstPreview2 = new Mat();
                        Cv2.InRange(dst, new Scalar(scal[0] - 10, scal[1], scal[3]), new Scalar(scal[0] + 10, scal[2], scal[4]), dstPreview2);
                        Cv2.AddWeighted(dstThreshed, 1.0, dstPreview2, 1.0, 0.0, dstPreview);
                    }
                    Cv2.InRange(dst, new Scalar(scal[0] - 10, scal[1], scal[3]), new Scalar(scal[0] + 10, scal[2], scal[4]), dstThreshed);

                    // Morphologic transformation to close the gaps inside the blob.
                    Cv2.MorphologyEx(src: dstThreshed,
                                     dst: dstThreshed,
                                     op: MorphTypes.Close,
                                     element: element
                                     );

                    blobDetection.Label(dstThreshed);
                    blobDetection.FilterByArea(MinBlobArea, MaxBlobArea);
                    blobDetection.RenderBlobs(dstThreshed, src);
                    CircleSegment[] circles = Cv2.HoughCircles(dstThreshed, HoughMethods.Gradient, 1, dstThreshed.Rows / 8);

                    // Creates all udp datagrams----------------------------------------------------
                    if (blobDetection.Count != 0)
                    {
                        for (int i = 0; i < blobDetection.Count; i++)
                        {
                            int processKey = blobDetection.ElementAt(i).Key;
                            udpDatagram_1 = "[$]tracking|id=" + data_id + "|label=" + blobCount + "|[$$]" + deviceName + ",[$$$]mesh,sample,";
                            for (int j = 0; j < blobDetection[processKey].Contour.ConvertToPolygon().Simplify(1).Count; j++)
                            {
                                if (orientation)
                                {
                                    udpDatagram_1 += Math.Round((float)blobDetection[processKey].Contour.ConvertToPolygon().Simplify(1).ElementAt(j).X / dst.Cols, 4).ToString().Replace(',', '.');
                                    udpDatagram_1 += "," + (1 - Math.Round((float)blobDetection[processKey].Contour.ConvertToPolygon().Simplify(1).ElementAt(j).Y / dst.Rows, 4)).ToString().Replace(',', '.');
                                    udpDatagram_1 += ",";
                                }
                                else
                                {
                                    udpDatagram_1 += (1 - Math.Round((float)blobDetection[processKey].Contour.ConvertToPolygon().Simplify(1).ElementAt(j).X / dst.Cols, 4)).ToString().Replace(',', '.');
                                    udpDatagram_1 += "," + Math.Round((float)blobDetection[processKey].Contour.ConvertToPolygon().Simplify(1).ElementAt(j).Y / dst.Rows, 4).ToString().Replace(',', '.');
                                    udpDatagram_1 += ",";
                                }
                            }
                            udpDatagram_1 += ";";
                            udpDatagram_2  = "[$]tracking|id=" + data_id + "|label=" + blobCount + "|[$$]" + deviceName + ",[$$$]area,";
                            udpDatagram_2 += "value," + blobDetection[processKey].Contour.ConvertToPolygon().Simplify(1).Area().ToString().Replace(',', '.') + ";";
                            udpDatagram_3  = "[$]tracking|id=" + data_id + "|label=" + blobCount + "|[$$]" + deviceName + ",[$$$]place,";
                            if (orientation)
                            {
                                udpDatagram_3 += "position," + (Math.Round(blobDetection[processKey].Centroid.X / dst.Cols, 3)).ToString().Replace(',', '.') + "," + (Math.Round(1 - (blobDetection[processKey].Centroid.Y / dst.Rows), 3)).ToString().Replace(',', '.') + ";";
                            }
                            else
                            {
                                udpDatagram_3 += "position," + (Math.Round(1 - (blobDetection[processKey].Centroid.X / dst.Cols), 3)).ToString().Replace(',', '.') + "," + (Math.Round(blobDetection[processKey].Centroid.Y / dst.Rows, 3)).ToString().Replace(',', '.') + ";";
                            }
                            udpDatagram_4  = "[$]tracking|id=" + data_id + "|label=" + blobCount + "|[$$]" + deviceName + ",[$$$]color,";
                            udpDatagram_4 += "hsv," + scal[0] + "-" + (scal[1] + scal[2]) / 2 + "-" + (scal[3] + scal[4]) / 2 + ";";

                            //Geometry
                            udpDatagram_5 = "[$]tracking|id=" + data_id + "|label=" + blobCount + "|[$$]" + deviceName + ",[$$$]form,geometry,";
                            CvContourPolygon poly          = blobDetection[processKey].Contour.ConvertToPolygon();
                            double           epsilon       = 0.04 * Cv2.ArcLength(poly, true);
                            Point[]          counterResult = Cv2.ApproxPolyDP(poly, epsilon, closed: true);
                            int    contourSimple_counter   = counterResult.Length;
                            string geometry = "";
                            switch (contourSimple_counter)
                            {
                            case 3:
                                geometry = "triangle";
                                break;

                            case 4:
                                Rect  rect        = Cv2.BoundingRect(poly);
                                float aspectRatio = 0;
                                if (rect.Y != 0)
                                {
                                    aspectRatio = rect.X / rect.Y;
                                }
                                if (aspectRatio >= 0.95 && aspectRatio <= 1.05)
                                {
                                    geometry = "square";
                                }
                                else
                                {
                                    geometry = "rectangle";
                                }
                                break;

                            default:
                                geometry = "unidentified" + contourSimple_counter;
                                break;
                            }
                            udpDatagram_5 += geometry + ";";
                            if (BlobLabel)
                            {
                                Cv2.PutText(src, geometry, blobDetection[processKey].Centroid, HersheyFonts.HersheySimplex, 0.5, new Scalar(0, 255, 0), 2);
                                Cv2.PutText(src, "[" + scal[0] + ", " + ((scal[1] + scal[2]) / 2) + ", " + ((scal[3] + scal[4]) / 2) + "]", new Point(blobDetection[processKey].Centroid.X, blobDetection[processKey].Centroid.Y + 20), HersheyFonts.HersheySimplex, 0.45, new Scalar(0, 255, 0), 2);
                            }
                            udpDatagram_6  = "[$]tracking|id=" + data_id + "|label=" + blobCount + "|[$$]" + deviceName + ",[$$$]perimeter,value,";
                            udpDatagram_6 += blobDetection[processKey].Contour.Perimeter().ToString().Replace(',', '.') + ";";

                            // UDP sender---------------------------------------------------------------------
                            try
                            {
                                byte[] sendBytes_1 = Encoding.ASCII.GetBytes(udpDatagram_1);
                                byte[] sendBytes_2 = Encoding.ASCII.GetBytes(udpDatagram_2);
                                byte[] sendBytes_3 = Encoding.ASCII.GetBytes(udpDatagram_3);
                                byte[] sendBytes_4 = Encoding.ASCII.GetBytes(udpDatagram_4);
                                byte[] sendBytes_5 = Encoding.ASCII.GetBytes(udpDatagram_5);
                                byte[] sendBytes_6 = Encoding.ASCII.GetBytes(udpDatagram_6);
                                udpClient.Send(sendBytes_1, sendBytes_1.Length, IP_udp, Port_udp);
                                udpClient.Send(sendBytes_2, sendBytes_2.Length, IP_udp, Port_udp);
                                udpClient.Send(sendBytes_3, sendBytes_3.Length, IP_udp, Port_udp);
                                udpClient.Send(sendBytes_4, sendBytes_4.Length, IP_udp, Port_udp);
                                udpClient.Send(sendBytes_5, sendBytes_5.Length, IP_udp, Port_udp);
                                udpClient.Send(sendBytes_6, sendBytes_6.Length, IP_udp, Port_udp);
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e.ToString());
                            }
                            udpDatagram_1 = "";
                            udpDatagram_2 = "";
                            udpDatagram_3 = "";
                            udpDatagram_4 = "";
                            blobCount++;
                        }
                    }
                }
                blobCount = 1;
            }

            // Same morphologic transformation but this time for the output image.
            Cv2.MorphologyEx(src: dstPreview,
                             dst: dstPreview,
                             op: MorphTypes.Close,
                             element: element
                             );

            return(dstPreview);
        }
        private void detectShapeCandidates(ref Bitmap bitmap, Boolean saveShapes)
        {
            Debug.WriteLine("Running OpenCV");
            string      myPhotos = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            Mat         colorMat = BitmapConverter.ToMat(bitmap);
            MatOfDouble mu       = new MatOfDouble();
            MatOfDouble sigma    = new MatOfDouble();

            Cv2.MeanStdDev(colorMat, mu, sigma);
            double mean = mu.GetArray(0, 0)[0];

            mu.Dispose();
            sigma.Dispose();

            Mat greyMat = new Mat();

            Cv2.CvtColor(colorMat, greyMat, ColorConversion.BgraToGray, 0);
            greyMat = greyMat.GaussianBlur(new OpenCvSharp.CPlusPlus.Size(1, 1), 5, 5, BorderType.Default);
            greyMat = greyMat.Canny(0.5 * mean, 1.2 * mean, 3, true);

            Mat contourMat = new Mat(greyMat.Size(), colorMat.Type());

            greyMat.CopyTo(contourMat);
            var contours = contourMat.FindContoursAsArray(ContourRetrieval.List, ContourChain.ApproxSimple);

            for (int j = 0; j < contours.Length; j++)
            {
                var poly = Cv2.ApproxPolyDP(contours[j], 0.01 * Cv2.ArcLength(contours[j], true), true);
                int num  = poly.Length;

                if (num >= 4 && num < 20)
                {
                    var color = Scalar.Blue;
                    var rect  = Cv2.BoundingRect(poly);

                    if (rect.Height < 20 || rect.Width < 20)
                    {
                        continue;
                    }
                    if (saveShapes)
                    {
                        string path = Path.Combine(myPhotos, "shape_samples");
                        path = Path.Combine(path, "shape_sample_" + Path.GetRandomFileName() + ".png");
                        var matRect = new OpenCvSharp.CPlusPlus.Rect(0, 0, greyMat.Width, greyMat.Height);
                        rect.Inflate((int)(rect.Width * 0.1), (int)(rect.Height * 0.1));
                        rect = rect.Intersect(matRect);
                        Mat shapeMat = greyMat.SubMat(rect);
                        var size     = new OpenCvSharp.CPlusPlus.Size(128, 128);
                        shapeMat = shapeMat.Resize(size);
                        Bitmap shape = shapeMat.ToBitmap();
                        shape.Save(path);
                        shape.Dispose();
                        shapeMat.Dispose();
                        continue;
                    }
                    Cv2.Rectangle(colorMat, rect, color, 2);
                }
            }


            bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(colorMat);
            colorMat.Dispose();
            greyMat.Dispose();
            contourMat.Dispose();
        }
Exemple #9
0
        private string getOMRString(OpenCvSharp.Point wh)
        {
            String[] chars = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" };
            String   res   = "";

            const int SMALL_OBJECT_MIN_AREA = 12;
            const int SMALL_OBJECT_THREADHOLD = 7;
            Mat       src, gray, binary, canny;

            src    = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmapPerspective);
            gray   = new Mat();
            binary = new Mat();
            canny  = new Mat();

            Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
            Cv2.Threshold(gray, binary, 150, 255, ThresholdTypes.Binary);
            Cv2.Canny(binary, canny, 0, 0, 3);

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

            List <OpenCvSharp.Point> smallObjectList = new List <OpenCvSharp.Point>();
            List <int> yList = new List <int>();
            List <OpenCvSharp.Point[]> rectObjectList = new List <OpenCvSharp.Point[]>();

            foreach (OpenCvSharp.Point[] p in contours)
            {
                double length = Cv2.ArcLength(p, true);
                double area   = Cv2.ContourArea(p, true);

                if (length < 100 && area < 1000 || p.Length < 5)
                {
                    continue;
                }

                OpenCvSharp.Point[] hull = Cv2.ConvexHull(p, true);
                OpenCvSharp.Point[] pp   = Cv2.ApproxPolyDP(p, 0.02 * length, true);
                if (pp.Length > SMALL_OBJECT_THREADHOLD && Math.Abs(area) < SMALL_OBJECT_MIN_AREA)
                {
                    OpenCvSharp.Point ppCenter = Util.getCenterPoint(pp);
                    smallObjectList.Add(ppCenter);

                    bool isExist = false;
                    foreach (int y in yList)
                    {
                        if (Math.Abs(y - ppCenter.Y) < SMALL_OBJECT_MIN_AREA * 2)
                        {
                            isExist = true;
                        }
                    }
                    if (isExist == false)
                    {
                        yList.Add(ppCenter.Y);
                    }
                }
            }

            int minExamineeRectX      = 0;
            int maxExamineeRectX      = wh.X;
            int maxExamineeRectY      = wh.Y;
            int widthExamineeRectItem = (maxExamineeRectX - minExamineeRectX) / 6;


            try
            {
                for (int i = 0; i < 6; i++)
                {
                    int minIndex = 0, minCount = int.MaxValue;
                    for (int k = 0; k < 10; k++)
                    {
                        int x = minExamineeRectX + widthExamineeRectItem * i + widthExamineeRectItem / 2;
                        int y = yList[k];
                        OpenCvSharp.Rect rect = new OpenCvSharp.Rect(x - 12, y - 12, 24, 24); // x, y, width, height

                        Mat matCircle    = binary.SubMat(rect);
                        int nonzeroCount = Cv2.CountNonZero(matCircle);
                        matCircle.Dispose();

                        if (nonzeroCount < minCount)
                        {
                            minCount = nonzeroCount;
                            minIndex = 9 - k;
                        }
                    }
                    if (i == 0)
                    {
                        res = chars[minIndex];
                    }
                    else
                    {
                        res += minIndex;
                    }
                    //Console.WriteLine("i" + i + " index:" + minIndex);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                res = null;
            }
            finally
            {
                if (bitmapPerspective != null)
                {
                    bitmapPerspective.Dispose();
                }
            }


            return(res);
        }
Exemple #10
0
        public Window1()
        {
            InitializeComponent();

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

            Cv2.ImShow("src", src);
            //src = src.Resize(new Size(src.Width / 2, src.Height / 2));
            for (var y = 0; y < src.Height; y++)
            {
                for (var x = 0; x < src.Width; x++)
                {
                    var color = src.Get <Vec3b>(y, x);
                    //if (color.Item2 < 175)
                    if (color.Item2 < 225)
                    {
                        color.Item0 = 255;
                        color.Item1 = 0;
                        color.Item2 = 0;
                    }
                    src.Set(y, x, color);
                }
            }
            Cv2.ImShow("fade", src);
            Mat gray   = new Mat();
            Mat binary = new Mat();

            Cv2.CvtColor(src, gray, ColorConversionCodes.RGB2GRAY);
            gray = gray.GaussianBlur(new Size(5, 5), 0);
            gray = gray.Blur(new Size(5, 5));
            gray = gray.BoxFilter(-1, new Size(10, 10), normalize: true);
            Cv2.ImShow("gray", gray);
            Cv2.Threshold(gray, binary, 100, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary);
            var element = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));

            binary = binary.Erode(element);
            binary = binary.MorphologyEx(MorphTypes.Close, element);
            Cv2.ImShow("bin", binary);
            //var line = binary.Canny(100, 200);
            //Cv2.ImShow("line", line);
            //Cv2.WaitKey();
            //建立轮廓接受数组
            Point[][]        contours;
            HierarchyIndex[] hierarchy;
            Cv2.FindContours(binary, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxTC89KCOS);
            //最小外接矩形接收数组
            MessageBox.Show(contours.Length.ToString());
            RotatedRect[] rotateRect    = new RotatedRect[contours.Length];
            Point[][]     contours_poly = new Point[contours.Length][];
            for (int i = 0; i < contours.Length; i++)
            {
                contours_poly[i] = Cv2.ApproxPolyDP(contours[i], 30, true); //返回凸包,单线长大于30过滤

                rotateRect[i] = Cv2.MinAreaRect(contours_poly[i]);          //最小外接矩形集合

                Point2f[] pot = new Point2f[4];                             //新建点集合接收点集合

                //for (int i = 0; i < rotateRect.Length; i++)
                //{
                var angle = rotateRect[i].Angle; //矩形角度
                pot = rotateRect[i].Points();    //矩形的4个角
                var line1 = Math.Sqrt((pot[0].X - pot[1].X) * (pot[0].X - pot[1].X) + (pot[0].Y - pot[1].Y) * (pot[0].Y - pot[1].Y));
                var line2 = Math.Sqrt((pot[0].X - pot[3].X) * (pot[0].X - pot[3].X) + (pot[0].Y - pot[3].Y) * (pot[0].Y - pot[3].Y));
                if (line1 * line2 < 1000)//过滤,太小的矩形直接pass
                {
                    continue;
                }
                if (line1 > line2)//依据实际情况进行判断
                {
                    angle += 90;
                }

                Mat Roi = new Mat(src.Size(), MatType.CV_8UC3);
                Roi.SetTo(0);//全黑
                //Cv2.DrawContours(binary, contours, -1, Scalar.White, -1);//在二值图像中圈出轮廓区域并染白
                Cv2.DrawContours(binary, contours, -1, Scalar.White, 1);
                Cv2.ImShow("bin", binary);
                src.CopyTo(Roi, binary);//将原图通过mask抠图到Roi
                Cv2.ImShow("Roi", Roi);
                Mat afterRotato = new Mat(src.Size(), MatType.CV_8UC3);
                afterRotato.SetTo(0);
                Point2f center = rotateRect[i].Center;
                Mat     M      = Cv2.GetRotationMatrix2D(center, angle, 1);                                   //计算变换矩阵
                Cv2.WarpAffine(Roi, afterRotato, M, Roi.Size(), InterpolationFlags.Linear, BorderTypes.Wrap); //得到变换后的图像,滤除其他信息
                Cv2.ImShow("旋转后", afterRotato);



                Mat bin2 = new Mat();
                Cv2.ImShow("after", afterRotato);
                Cv2.CvtColor(afterRotato, bin2, ColorConversionCodes.RGB2GRAY);
                Cv2.Threshold(bin2, bin2, 50, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);
                Point[][]        con;
                HierarchyIndex[] temp;//接收矫正后的轮廓信息
                Cv2.FindContours(bin2, out con, out temp, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
                for (int j = 0; j < con.Length; j++)
                {
                    Rect rect = Cv2.BoundingRect(con[j]); //直接使用矫正矩形,因为矫正后不需要再旋转
                    if (rect.Height * rect.Width < 8000)  //过滤干扰信息
                    {
                        continue;
                    }
                    Mat dstImg = new Mat(afterRotato, rect);
                    dstImg = dstImg.CvtColor(ColorConversionCodes.RGB2GRAY);
                    dstImg = dstImg.Threshold(50, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary);
                    Cv2.BitwiseNot(dstImg, dstImg, new Mat());
                    dstImg = new Mat(dstImg, new Rect(100, 100, dstImg.Width - 200, dstImg.Height - 200));
                    Cv2.ImShow("dst", dstImg);
                    dstImg.SaveImage("dst1.jpg");

                    var engine     = new TesseractEngine("./tessdata", "eng", EngineMode.Default);
                    var resProcess = engine.Process(Pix.LoadTiffFromMemory(dstImg.ToBytes(".tiff")));
                    MessageBox.Show(resProcess.GetText());

                    ////string name = "dst" + i;//主要看调试的时候有几个结果
                    //dstImg = dstImg.CvtColor(ColorConversionCodes.RGB2GRAY);
                    //dstImg = dstImg.Threshold(10, 255, ThresholdTypes.Otsu);
                    //Cv2.ImShow("chan", dstImg.Canny(100, 200));

                    //dstImg.FindContours(out var con1, out var hie1, RetrievalModes.External,
                    //    ContourApproximationModes.ApproxNone);
                    //dstImg.DrawContours(con1, -1, Scalar.Green, 3);
                    //Cv2.ImShow("dst2", dstImg);
                }
            }
            Cv2.WaitKey();
            Console.ReadLine();
        }
        static void Stop4_Detect(Mat Src, int fileindex, string filename)
        {
            Mat vis_rgb = Src.CvtColor(ColorConversionCodes.GRAY2RGB);

            int    OK_NG_Flag = 0;
            int    stop4_black_defect_area_min = 220;
            int    stop4_black_defect_area_max = 20000;
            double stop4_arclength_area_ratio  = 0.35;
            int    stop4_ignore_radius         = 5;

            //==================================================find real oring===============================================
            Point[][]        contours;
            HierarchyIndex[] hierarchly;
            Mat thresh1 = Src.Threshold(240, 255, ThresholdTypes.Binary);

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

            // find final circle
            List <Point[]> contours_final = new List <Point[]>();
            List <Point[]> approx_list    = new List <Point[]>();

            foreach (Point[] contour_now in contours)
            {
                if (Cv2.ContourArea(contour_now) > 300000 && Cv2.ContourArea(contour_now) < 800000)
                {
                    contours_final.Add(contour_now);
                    Point[] approx = Cv2.ApproxPolyDP(contour_now, 0.5, true);
                    approx_list.Add(approx);
                }
            }
            //==================================================outer contour - inner contour=====================================
            // variable
            OpenCvSharp.Point[][] temp = new Point[1][];


            // inner contour
            Mat inner_contour_img = Mat.Zeros(Src.Size(), MatType.CV_8UC1);

            Point[] inner_contour = Cv2.ConvexHull(approx_list[1]);
            temp[0] = inner_contour;
            Cv2.DrawContours(inner_contour_img, temp, -1, 255, -1);

            // outer contour
            Mat outer_contour_img  = Mat.Zeros(Src.Size(), MatType.CV_8UC1);
            Mat outer_contour_img2 = new Mat(Src.Size(), MatType.CV_8UC1, new Scalar(255));//initilize Mat with the value 255

            temp[0] = approx_list[0];
            Cv2.DrawContours(outer_contour_img, temp, -1, 255, -1);
            //outer contour2 in order to make mask area = 255
            Cv2.DrawContours(outer_contour_img2, temp, -1, 0, -1);
            //outer - inner
            Mat diff_mask  = outer_contour_img - inner_contour_img;
            Mat diff_mask2 = inner_contour_img + outer_contour_img2;

            Mat image = Mat.Zeros(Src.Size(), MatType.CV_8UC1);

            Src.CopyTo(image, diff_mask);
            //in order to make mask area = 255
            image = image + diff_mask2;

            //=======================circle ignore=========================
            Point2f center;
            float   radius;
            Mat     circle_mask = new Mat(Src.Size(), MatType.CV_8UC1, new Scalar(255));

            Cv2.MinEnclosingCircle(approx_list[0], out center, out radius);
            Cv2.Circle(circle_mask, (OpenCvSharp.Point)center, (int)(radius - stop4_ignore_radius), 0, thickness: -1);
            circle_mask.CopyTo(image, circle_mask);
            //image.SaveImage("./mask.jpg");
            //================================use threshold to find defect==========================================
            Point[][]        contours2;
            HierarchyIndex[] hierarchly2;
            Mat thresh2 = image.Threshold(95, 255, ThresholdTypes.BinaryInv);
            //thresh2.SaveImage("./thresh2.jpg");
            Mat kernel = Mat.Ones(7, 7, MatType.CV_8UC1);//改變凹角大小

            thresh2 = thresh2.MorphologyEx(MorphTypes.Dilate, kernel);
            //thresh2.SaveImage("./thresh2_Dilate.jpg");
            Cv2.FindContours(thresh2, out contours2, out hierarchly2, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);



            foreach (OpenCvSharp.Point[] contour_now in contours2)
            {
                if (Cv2.ContourArea(contour_now) > stop4_black_defect_area_min &&
                    Cv2.ContourArea(contour_now) < 20000 &&
                    Cv2.ContourArea(contour_now) < stop4_black_defect_area_max &&
                    (Cv2.ArcLength(contour_now, true) / Cv2.ContourArea(contour_now)) < stop4_arclength_area_ratio)
                {
                    //Console.WriteLine("Arc Length: " + (Cv2.ArcLength(contour_now, true) + " Area: " + Cv2.ContourArea(contour_now))+" Length/Area:" +(Cv2.ArcLength(contour_now, true) / Cv2.ContourArea(contour_now)));
                    OpenCvSharp.Point[] approx = Cv2.ApproxPolyDP(contour_now, 0.000, true);
                    temp[0] = approx;
                    Cv2.Polylines(vis_rgb, temp, true, new Scalar(0, 0, 255), 1);
                    OK_NG_Flag = 1;
                }
            }
            if (OK_NG_Flag == 0)
            {
                Console.WriteLine("OK");
            }
            else
            {
                Console.WriteLine("NG");
            }
            //vis_rgb.SaveImage("./result.jpg");
            vis_rgb.SaveImage("./result/test" + filename);
        }
    public void find_polygon(int polygon_type, double threadhold, Point[][] contours, Mat result_mat)
    {
        int idx, i;

        Point[] poly       = new Point[100];
        Point   center_pos = new Point();

        center_pos.X = 0;
        center_pos.Y = 0;

        for (idx = 0; idx < contours.Length; idx++)
        {
            poly = Cv2.ApproxPolyDP(contours[idx], 10, true);
            if (polygon_type == 10000)
            {
                int left = 10000, right = -10000, top = 10000, bottom = -10000;
                for (i = 0; i < poly.Length; i++)
                {
                    if (left > poly[i].X)
                    {
                        left = poly[i].X;
                    }
                    if (right < poly[i].X)
                    {
                        right = poly[i].X;
                    }
                    if (top > poly[i].Y)
                    {
                        top = poly[i].Y;
                    }
                    if (bottom < poly[i].Y)
                    {
                        bottom = poly[i].Y;
                    }

                    center_pos.X += poly[i].X;
                    center_pos.Y += poly[i].Y;
                    Cv2.Line(result_mat, poly[i], poly[(i + 1) % poly.Length], Scalar.Blue, 2);
                }

                if (right - left > 30)
                {
                    center_pos.X = (left + right) / 2;
                    center_pos.Y = (top + bottom) / 2;

                    bool bfound = false;
                    foreach (Polygon_T s in polygon_array)
                    {
                        if (center_pos.X > 0 && center_pos.Y > 0)
                        {
                            double dist = Math.Sqrt((center_pos.X - s.center_pos.X) *
                                                    (center_pos.X - s.center_pos.X) +
                                                    (center_pos.Y - s.center_pos.Y) *
                                                    (center_pos.Y - s.center_pos.Y));
                            if (dist < threadhold)
                            {
                                bfound = true;
                            }
                        }
                    }

                    if (bfound == false)
                    {
                        Polygon_T p = new Polygon_T();
                        p.center_pos = center_pos;
                        p.gt         = GraphicType.GT_Polygon;

                        polygon_array.Add(p);

                        Cv2.Circle(result_mat, center_pos, 5, Scalar.Red, 2);
                    }
                }
            }
            else
            {
                if (poly.Length == polygon_type)
                {
                    int left = 10000, right = -10000, top = 10000, bottom = -10000;
                    for (i = 0; i < poly.Length; i++)
                    {
                        if (left > poly[i].X)
                        {
                            left = poly[i].X;
                        }
                        if (right < poly[i].X)
                        {
                            right = poly[i].X;
                        }
                        if (top > poly[i].Y)
                        {
                            top = poly[i].Y;
                        }
                        if (bottom < poly[i].Y)
                        {
                            bottom = poly[i].Y;
                        }

                        center_pos.X += poly[i].X;
                        center_pos.Y += poly[i].Y;
                        Cv2.Line(result_mat, poly[i], poly[(i + 1) % poly.Length], Scalar.Blue, 2);
                    }

                    center_pos.X = (left + right) / 2;
                    center_pos.Y = (top + bottom) / 2;

                    bool bfound = false;
                    foreach (Polygon_T s in polygon_array)
                    {
                        if (center_pos.X > 0 && center_pos.Y > 0)
                        {
                            double dist = Math.Sqrt((center_pos.X - s.center_pos.X) *
                                                    (center_pos.X - s.center_pos.X) +
                                                    (center_pos.Y - s.center_pos.Y) *
                                                    (center_pos.Y - s.center_pos.Y));
                            if (dist < threadhold)
                            {
                                bfound = true;
                            }
                        }
                    }

                    if (bfound == false)
                    {
                        Polygon_T p = new Polygon_T();
                        p.center_pos = center_pos;
                        if (polygon_type == 3)
                        {
                            p.gt = GraphicType.GT_Triangularity;
                        }
                        if (polygon_type == 4)
                        {
                            p.gt = GraphicType.GT_Rectangle;
                        }

                        polygon_array.Add(p);

                        Cv2.Circle(result_mat, center_pos, 5, Scalar.Red, 2);
                    }
                }
            }
        }
    }
Exemple #13
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 #14
0
        public static List <Unit> FindUnits(Img img)
        {
            var src     = img.ToMat().Clone();
            var blurred = src.GaussianBlur(new OpenCvSharp.Size(3, 3), 0);
            var gray    = blurred.ToGray();
            var canny   = gray.Canny(30, 100);

            CvPoint[][]      contours;
            HierarchyIndex[] hierarchy;
            canny.FindContours(out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);

            var list = new List <FindUnitIconMatTempInfo>();

            for (var i = 0; i < contours.Length; i++)
            {
                var contour   = contours[i];
                var borderLen = Cv2.ArcLength(contour, true);
                var approx    = Cv2.ApproxPolyDP(contour, 0.02 * borderLen, true);
                if (approx.Length == 4 && Cv2.IsContourConvex(approx))
                {
                    if (borderLen > 100 && IsSquare(approx))
                    {
                        list.Add(new FindUnitIconMatTempInfo()
                        {
                            Index        = i,
                            BorderLength = borderLen,
                            Points       = approx,
                            CenterPoint  = GetCenterPoint(approx),
                        });
                    }
                }
            }
            if (list.Count == 0)
            {
                return(new List <Unit>());
            }

            list.Sort((a, b) =>
            {
                return(a.BorderLength.CompareTo(b.BorderLength));
            });
            var listList = new List <List <FindUnitIconMatTempInfo> >();
            var tempList = new List <FindUnitIconMatTempInfo>()
            {
                list[0]
            };

            for (var i = 1; i < list.Count; i++)
            {
                var ratio = list[i].BorderLength / list[i - 1].BorderLength;
                if (ratio > 1.1)
                {
                    listList.Add(tempList);
                    tempList = new List <FindUnitIconMatTempInfo>();
                }
                tempList.Add(list[i]);
            }
            listList.Add(tempList);
            var maxCount     = listList.Max(x => x.Count);
            var maxCountList = listList.Where(x => x.Count == maxCount).FirstOrDefault();

            //根据FindContours的索引重新排序
            maxCountList.Sort((a, b) =>
            {
                return(a.Index.CompareTo(b.Index));
            });

            //过滤掉重复的
            var centerPointList = new List <CvPoint>();

            tempList = new List <FindUnitIconMatTempInfo>();
            var hasSame = new Func <CvPoint, bool>((point) =>
            {
                foreach (var pt in centerPointList)
                {
                    if (Math.Abs(point.X - pt.X) < 10 && Math.Abs(point.Y - pt.Y) < 10)
                    {
                        return(true);
                    }
                }
                return(false);
            });

            foreach (var item in maxCountList)
            {
                var center = item.CenterPoint;
                if (!hasSame(center))
                {
                    tempList.Add(item);
                    centerPointList.Add(center);
                }
            }
            maxCountList = tempList;

            var iconSources = new List <Img>();

            for (var i = 0; i < maxCountList.Count; i++)
            {
                var item   = maxCountList[i];
                var wid    = item.BorderLength * 0.25 * 1.1;
                var center = item.CenterPoint;
                var rect   = new Rect(center - new CvPoint(wid / 2, wid / 2), new CvSize(wid, wid));
                var mat    = new Mat(src, rect);
                iconSources.Add(new Img(mat));
                //Cv2.ImShow(i.ToString(), mat);
            }

            var averBorderLen = maxCountList.Average(x => x.BorderLength);
            var r             = FindUnits(iconSources, averBorderLen * 0.25);

            r.Reverse();
            return(r);
        }
Exemple #15
0
        private Bitmap CreateObjectMaskMelee(Bitmap image, out Mat image_mask,
                                             out double mask_length, out double mask_area, out double mask_width, out double mask_height,
                                             out double mask_pvheight, bool useKthresholdLab = false)
        {
            Bitmap dst = null;

            image_mask  = null;
            mask_length = mask_area = mask_width = mask_height = mask_pvheight = 0;

            try
            {
                Mat src = BitmapConverter.ToMat(image);

                Mat src_kirsch = BitmapConverter.ToMat(image.KirschFilter());

                Mat kirsch_gray = new Mat();
                Cv2.CvtColor(src_kirsch, kirsch_gray, ColorConversionCodes.RGB2GRAY);

                Mat kirsch_threshold = new Mat();
                if (!useKthresholdLab)
                {
                    Cv2.Threshold(kirsch_gray, kirsch_threshold, kThreshold, 255, ThresholdTypes.Binary);
                }
                else
                {
                    Cv2.Threshold(kirsch_gray, kirsch_threshold, kThresholdLab, 255, ThresholdTypes.Binary);
                }

                Mat[] contours;
                List <OpenCvSharp.Point> hierarchy;
                List <Mat> hulls;
                Mat        morph_element = Cv2.GetStructuringElement(MorphShapes.Ellipse, new OpenCvSharp.Size(2, 2), new OpenCvSharp.Point(1, 1));

                #region morphology

                Mat kirsch_threshold_copy = new Mat();
                kirsch_threshold.CopyTo(kirsch_threshold_copy);

                int hullCount = 0, numLoops = 0;
                do
                {
                    numLoops++;

                    Mat kirsch_morph = kirsch_threshold_copy.MorphologyEx(MorphTypes.Gradient, morph_element);

                    hierarchy = new List <OpenCvSharp.Point>();
                    Cv2.FindContours(kirsch_morph, out contours, OutputArray.Create(hierarchy),
                                     RetrievalModes.External, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point(0, 0));

                    hulls = new List <Mat>();
                    for (int j = 0; j < contours.Length; j++)
                    {
                        Mat hull = new Mat();
                        Cv2.ConvexHull(contours[j], hull);
                        hulls.Add(hull);
                    }

                    Mat drawing = Mat.Zeros(src.Size(), MatType.CV_8UC1);
                    Cv2.DrawContours(drawing, hulls, -1, Scalar.White);

                    if (hulls.Count != hullCount && numLoops < 100)
                    {
                        hullCount             = hulls.Count;
                        kirsch_threshold_copy = drawing;
                    }
                    else
                    {
                        break;
                    }
                } while (true);

                #endregion

                if (numLoops >= 100)
                {
                    throw new Exception("Could not find hull");
                }

                #region bestHull
                //try and filter out dust near to stone

                double largestArea = hulls.Max(m => Cv2.ContourArea(m));
                var    bestHulls   = hulls.Where(m => Cv2.ContourArea(m) == largestArea).ToList();

                Mat hulls_mask = Mat.Zeros(src.Size(), MatType.CV_8UC1);
                Cv2.DrawContours(hulls_mask, bestHulls, -1, Scalar.White, -1);

                //hulls_mask is the convex hull of main outline excluding nearby dust
                Cv2.Threshold(kirsch_gray, kirsch_threshold, hullThreshold, 255, ThresholdTypes.Binary);
                Mat kirsch_mask = Mat.Zeros(kirsch_threshold.Size(), kirsch_threshold.Type());
                kirsch_threshold.CopyTo(kirsch_mask, hulls_mask);

                #endregion

                hierarchy = new List <OpenCvSharp.Point>();;
                Cv2.FindContours(kirsch_mask, out contours, OutputArray.Create(hierarchy),
                                 RetrievalModes.External, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point(0, 0));

                List <OpenCvSharp.Point> points = new List <OpenCvSharp.Point>();
                foreach (Mat contour in contours)
                {
                    int m2Count            = (contour.Rows % 2 > 0) ? contour.Rows + 1 : contour.Rows;
                    OpenCvSharp.Point[] p2 = new OpenCvSharp.Point[m2Count];
                    contour.GetArray(0, 0, p2);
                    Array.Resize(ref p2, contour.Rows);

                    points.AddRange(p2.ToList());
                }
                Mat finalHull = new Mat();
                Cv2.ConvexHull(InputArray.Create(points), finalHull);


                List <Mat> finalHulls = new List <Mat>();
                finalHulls.Add(finalHull);
                Cv2.DrawContours(src, finalHulls, -1, new Scalar(128, 0, 128, 255), 2);

                hulls_mask = Mat.Zeros(src.Size(), MatType.CV_8UC1);
                Cv2.DrawContours(hulls_mask, finalHulls, -1, Scalar.White, -1);
                image_mask = hulls_mask;

                #region bounding

                Mat poly = new Mat();
                Cv2.ApproxPolyDP(finalHull, poly, 3, true);
                Rect boundaryRect = Cv2.BoundingRect(poly);
                mask_width  = boundaryRect.Width;
                mask_height = boundaryRect.Height;
                mask_area   = Cv2.ContourArea(poly);
                mask_length = Cv2.ArcLength(finalHull, true);

                List <OpenCvSharp.Point> finalPoints = new List <OpenCvSharp.Point>();
                int m1Count            = (finalHull.Rows % 2 > 0) ? finalHull.Rows + 1 : finalHull.Rows;
                OpenCvSharp.Point[] p1 = new OpenCvSharp.Point[m1Count];
                finalHull.GetArray(0, 0, p1);
                Array.Resize(ref p1, finalHull.Rows);
                finalPoints.AddRange(p1.ToList());

                double y_min   = boundaryRect.Bottom;
                double y_x_min = finalPoints.Where(p => p.X == boundaryRect.Left).ToList()[0].Y;
                double y_x_max = finalPoints.Where(p => p.X == boundaryRect.Right).ToList()[0].Y;

                mask_pvheight = ((double)y_x_max + (double)y_x_min) / 2 - (double)y_min;

                #endregion

                //dst = BitmapConverter.ToBitmap(src);
                using (var ms = src.ToMemoryStream())
                {
                    dst = (Bitmap)Image.FromStream(ms);
                }

                try
                {
                    if (saveMaskDataPath.Length > 0)
                    {
                        StringBuilder sb = new StringBuilder();
                        sb.AppendLine("mask_length,mask_area,mask_width,mask_height,mask_pvheight");
                        sb.AppendLine(mask_length + "," + mask_area + "," + mask_width + "," + mask_height + "," + mask_pvheight);
                        image_mask.SaveImage(saveMaskDataPath + @"\image_mask.jpg");
                        File.WriteAllText(saveMaskDataPath + @"\mask_vals.csv", sb.ToString());
                    }
                }
                catch
                {
                }
            }
            catch
            {
                dst = null;
            }

            return(dst);
        }
        /// <summary>
        /// 2値化
        /// </summary>
        /// <param name="picture">Image画像データ</param>
        /// <returns>
        ///     成功時:Imageデータ
        ///     失敗時:null
        /// </returns>
        public List <Image> Binarization(Image picture)
        {
            List <Image> img = new List <Image>();

            try
            {
                //元画像(Image)データをMatデータにする。
                Mat Moto = new Mat();
                Moto = BitmapConverter.ToMat((Bitmap)picture);

                //グレースケール
                Mat Gray = new Mat();
                Cv2.CvtColor(Moto, Gray, ColorConversionCodes.BGRA2GRAY);

                //2値化
                Mat Binari = Gray.Threshold(0.0, 255.0, ThresholdTypes.Binary | ThresholdTypes.Otsu);

                //輪郭検出
                OpenCvSharp.Point[][] edgesArray = Binari.Clone().FindContoursAsArray(RetrievalModes.List, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point(0, 0));

                //輪郭ごとに処理を加える
                foreach (OpenCvSharp.Point[] item1 in edgesArray)
                {
                    //直線近似にする
                    OpenCvSharp.Point[] normalizedEdges = Cv2.ApproxPolyDP(item1, 10, true);

                    //近似結果から四角のみを対象
                    if (normalizedEdges.Count() == 4)
                    {
                        //輪郭が内接する四角形を作り、長辺に合わせて正方形にしておく
                        Rect rect = Cv2.BoundingRect(normalizedEdges);
                        if (rect.Width < rect.Height)
                        {
                            rect.Width = rect.Height;
                        }
                        else if (rect.Height < rect.Width)
                        {
                            rect.Height = rect.Width;
                        }

                        //四角形のサイズが一定の範囲以外は無視する
                        if ((Moto.Width * 0.1) < rect.Width && (Moto.Width * 0.6) > rect.Width &&
                            (Moto.Width * 0.1) < rect.Height && (Moto.Width * 0.6) > rect.Height)
                        {
                            //見つけた輪郭を、上記にて作った正方形に補正するための行列を作り、元画像に補正をかける。
                            //補正準備(補正元の輪郭)
                            List <Point2f> srcEdges = new List <Point2f>();
                            foreach (OpenCvSharp.Point edge in normalizedEdges)
                            {
                                srcEdges.Add(new Point2f(edge.X, edge.Y));
                            }
                            srcEdges.Add(new Point2f(normalizedEdges[0].X, normalizedEdges[0].Y));

                            //補正準備(補正先の輪郭)
                            List <Point2f> dstEdges = new List <Point2f>();
                            dstEdges.Add(new Point2f(rect.X, rect.Y));
                            dstEdges.Add(new Point2f(rect.X + rect.Width, rect.Y));
                            dstEdges.Add(new Point2f(rect.X + rect.Width, rect.Y + rect.Height));
                            dstEdges.Add(new Point2f(rect.X, rect.Y + rect.Height));
                            dstEdges.Add(new Point2f(rect.X, rect.Y));

                            //変換行列の作成
                            Mat t = Cv2.GetPerspectiveTransform(srcEdges, dstEdges);

                            //元画像に補正をかける
                            Mat mat = Gray;
                            mat = mat.WarpPerspective(t, new OpenCvSharp.Size(mat.Width, mat.Height));

                            //画像をリストへ追加
                            img.Add(BitmapConverter.ToBitmap(mat));
                        }
                    }
                }

                if (img.Count == 0)
                {
                    img = null;
                }
            }
            catch (Exception ex)
            {
                img = null;
                throw ex;
            }

            return(img);
        }
Exemple #17
0
        private Bitmap CreateObjectMaskNew(Bitmap image, out Mat image_mask,
                                           out double mask_length, out double mask_area, out double mask_width, out double mask_height,
                                           out double mask_pvheight, double kThresh, double hThresh, double canny1, double canny2,
                                           out Mat image_mask_spc, out double mask2_area, int brightAreaThreshold = -1, int darkAreaThreshold = -1)
        {
            Bitmap dst = null;

            image_mask     = null;
            image_mask_spc = null;
            mask_length    = mask_area = mask_width = mask_height = mask_pvheight = mask2_area = 0;

            try
            {
                Mat src = BitmapConverter.ToMat(image);

                Mat src_kirsch = BitmapConverter.ToMat(image.KirschFilter());

                Mat kirsch_gray = new Mat();
                Cv2.CvtColor(src_kirsch, kirsch_gray, ColorConversionCodes.RGB2GRAY);

                Mat kirsch_threshold = new Mat();
                Cv2.Threshold(kirsch_gray, kirsch_threshold, kThresh, 255, ThresholdTypes.Binary);


                Mat[] contours;
                List <OpenCvSharp.Point> hierarchy;
                List <Mat> hulls;
                Mat        morph_element = Cv2.GetStructuringElement(MorphShapes.Ellipse, new OpenCvSharp.Size(2, 2), new OpenCvSharp.Point(1, 1));

                #region morphology

                Mat kirsch_threshold_copy = new Mat();
                kirsch_threshold.CopyTo(kirsch_threshold_copy);

                int hullCount = 0, numLoops = 0;
                do
                {
                    numLoops++;

                    Mat kirsch_morph = kirsch_threshold_copy.MorphologyEx(MorphTypes.Gradient, morph_element);

                    hierarchy = new List <OpenCvSharp.Point>();
                    Cv2.FindContours(kirsch_morph, out contours, OutputArray.Create(hierarchy),
                                     RetrievalModes.External, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point(0, 0));

                    hulls = new List <Mat>();
                    for (int j = 0; j < contours.Length; j++)
                    {
                        Mat hull = new Mat();
                        Cv2.ConvexHull(contours[j], hull);
                        hulls.Add(hull);
                    }

                    Mat drawing = Mat.Zeros(src.Size(), MatType.CV_8UC1);
                    Cv2.DrawContours(drawing, hulls, -1, Scalar.White);

                    if (hulls.Count != hullCount && numLoops < 100)
                    {
                        hullCount             = hulls.Count;
                        kirsch_threshold_copy = drawing;
                    }
                    else
                    {
                        break;
                    }
                } while (true);

                #endregion

                if (numLoops >= 100)
                {
                    throw new Exception("Could not find hull");
                }

                #region bestHull
                //try and filter out dust near to stone

                double largestArea = hulls.Max(m => Cv2.ContourArea(m));
                var    bestHulls   = hulls.Where(m => Cv2.ContourArea(m) == largestArea).ToList();

                Mat hulls_mask = Mat.Zeros(src.Size(), MatType.CV_8UC1);
                Cv2.DrawContours(hulls_mask, bestHulls, -1, Scalar.White, -1);

                //hulls_mask is the convex hull of outline, now look for clefts
                Cv2.Threshold(kirsch_gray, kirsch_threshold, hThresh, 255, ThresholdTypes.Binary);
                Mat kirsch_mask = Mat.Zeros(kirsch_threshold.Size(), kirsch_threshold.Type());
                kirsch_threshold.CopyTo(kirsch_mask, hulls_mask);

                Mat kirsch_mask_canny = new Mat();
                Cv2.Canny(kirsch_mask, kirsch_mask_canny, canny1, canny2, 3);

                morph_element = Cv2.GetStructuringElement(MorphShapes.Ellipse, new OpenCvSharp.Size(5, 5), new OpenCvSharp.Point(2, 2));
                Mat kirsch_filled = new Mat();
                Cv2.Dilate(kirsch_mask_canny, kirsch_filled, morph_element);
                Cv2.Dilate(kirsch_filled, kirsch_filled, morph_element);
                Cv2.Erode(kirsch_filled, kirsch_filled, morph_element);
                Cv2.Erode(kirsch_filled, kirsch_filled, morph_element);

                hierarchy = new List <OpenCvSharp.Point>();;
                Cv2.FindContours(kirsch_filled, out contours, OutputArray.Create(hierarchy),
                                 RetrievalModes.External, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point(0, 0));

                #endregion

                hulls_mask = Mat.Zeros(src.Size(), MatType.CV_8UC1);
                Cv2.DrawContours(hulls_mask, contours, -1, Scalar.White, -1);

                Cv2.Erode(hulls_mask, hulls_mask, morph_element);
                Cv2.Erode(hulls_mask, hulls_mask, morph_element);

                image_mask = hulls_mask;

                //remove bright areas
                if ((brightAreaThreshold > -1) || (darkAreaThreshold > -1))
                {
                    Mat src_mask       = new Mat();
                    Mat hulls_mask_spc = hulls_mask.Clone();
                    src.CopyTo(src_mask, hulls_mask_spc);
                    Mat gray = new Mat();

                    Cv2.CvtColor(src_mask, gray, ColorConversionCodes.BGR2GRAY);
                    if (brightAreaThreshold > -1)
                    {
                        Mat bright = new Mat();
                        Cv2.Threshold(gray, bright, brightAreaThreshold, 255, ThresholdTypes.BinaryInv);
                        Cv2.ImWrite(@"C:\gColorFancy\Image\bright.jpg", bright);
                        Mat t = new Mat();
                        hulls_mask_spc.CopyTo(t, bright);
                        hulls_mask_spc = t.Clone();
                    }
                    if (darkAreaThreshold > -1)
                    {
                        Mat dark = new Mat();
                        Cv2.Threshold(gray, dark, darkAreaThreshold, 255, ThresholdTypes.Binary);
                        Cv2.ImWrite(@"C:\gColorFancy\Image\dark.jpg", dark);
                        Mat t = new Mat();
                        hulls_mask_spc.CopyTo(t, dark);
                        hulls_mask_spc = t.Clone();
                    }

                    image_mask_spc = hulls_mask_spc;

                    var hierarchy2 = new List <OpenCvSharp.Point>();;
                    Cv2.FindContours(hulls_mask_spc, out contours, OutputArray.Create(hierarchy2),
                                     RetrievalModes.External, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point(0, 0));

                    largestArea = contours.Max(m => Cv2.ContourArea(m));
                    Mat finalHullSpc = contours.Where(m => Cv2.ContourArea(m) == largestArea).ToList()[0];

                    if (ConvexHullOnMask)
                    {
                        Mat hull = new Mat();
                        Cv2.ConvexHull(finalHullSpc, hull);
                        Mat polySpc = new Mat();
                        Cv2.ApproxPolyDP(hull, polySpc, 3, true);
                        mask2_area = Cv2.ContourArea(polySpc);
                    }
                    else
                    {
                        mask2_area = largestArea;
                    }
                }
                ///////////////////////////

                hierarchy = new List <OpenCvSharp.Point>();;
                Cv2.FindContours(hulls_mask, out contours, OutputArray.Create(hierarchy),
                                 RetrievalModes.External, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point(0, 0));

                largestArea = contours.Max(m => Cv2.ContourArea(m));
                Mat finalHull = contours.Where(m => Cv2.ContourArea(m) == largestArea).ToList()[0];

                if (ConvexHullOnMask)
                {
                    var hull = new Mat();
                    Cv2.ConvexHull(finalHull, hull);
                    finalHull = hull;
                }
                List <Mat> finalHulls = new List <Mat>();
                finalHulls.Add(finalHull);
                Cv2.DrawContours(src, finalHulls, -1, new Scalar(128, 0, 128, 255), 3);

                #region bounding

                Mat poly = new Mat();
                Cv2.ApproxPolyDP(finalHull, poly, 3, true);
                Rect boundaryRect = Cv2.BoundingRect(poly);
                mask_width  = boundaryRect.Width;
                mask_height = boundaryRect.Height;
                if (ConvexHullOnMask)
                {
                    mask_area = Cv2.ContourArea(poly);
                }
                else
                {
                    mask_area = largestArea;
                }
                mask_length = Cv2.ArcLength(finalHull, true);

                List <OpenCvSharp.Point> finalPoints = new List <OpenCvSharp.Point>();
                int m1Count            = (finalHull.Rows % 2 > 0) ? finalHull.Rows + 1 : finalHull.Rows;
                OpenCvSharp.Point[] p1 = new OpenCvSharp.Point[m1Count];
                finalHull.GetArray(0, 0, p1);
                Array.Resize(ref p1, finalHull.Rows);
                finalPoints.AddRange(p1.ToList());

                double y_min   = boundaryRect.Bottom;
                double y_x_min = finalPoints.Where(p => p.X == boundaryRect.Left).ToList()[0].Y;
                double y_x_max = finalPoints.Where(p => p.X == boundaryRect.Right).ToList()[0].Y;

                mask_pvheight = ((double)y_x_max + (double)y_x_min) / 2 - (double)y_min;

                #endregion

                //dst = BitmapConverter.ToBitmap(src);
                using (var ms = src.ToMemoryStream())
                {
                    dst = (Bitmap)Image.FromStream(ms);
                }

                try
                {
                    if (saveMaskDataPath.Length > 0)
                    {
                        //StringBuilder sb = new StringBuilder();
                        //sb.AppendLine("mask_length,mask_area,mask_width,mask_height,mask_pvheight");
                        //sb.AppendLine(mask_length + "," + mask_area + "," + mask_width + "," + mask_height + "," + mask_pvheight);
                        image_mask.SaveImage(saveMaskDataPath + @"\image_mask.jpg");
                        if (image_mask_spc != null)
                        {
                            image_mask_spc.SaveImage(saveMaskDataPath + @"\image_mask_spc.jpg");
                        }
                        BitmapConverter.ToMat(image).SaveImage(saveMaskDataPath + @"\src.jpg");
                        //File.WriteAllText(saveMaskDataPath + @"\mask_vals.csv", sb.ToString());
                        //File.AppendAllText(saveMaskDataPath + @"\exception.txt", DateTime.Now + ":" + av.Message);
                        //File.AppendAllText(saveMaskDataPath + @"\exception.txt", DateTime.Now + ":" + av.StackTrace);
                        //File.AppendAllText(saveMaskDataPath + @"\exception.txt", DateTime.Now + ":" + av.Source);
                    }
                }
                catch
                {
                }
            }
            catch (Exception ex)
            {
                dst = null;
            }

            return(dst);
        }
Exemple #18
0
        Point2d[] FindTemp(OpenCvSharp.Point[] contours)
        {
            //tempCount = contours.Length;

            //Cv2.PutText(frame_out, tempCount.ToString(), new OpenCvSharp.Point(20, 20),
            //HersheyFonts.HersheyDuplex, 0.5, new Scalar(255, 255, 0));

            OpenCvSharp.Point[] approxedRow;
            OpenCvSharp.Point[] approxed = new OpenCvSharp.Point[4];

            approxedRow = Cv2.ApproxPolyDP(contours, 4, false);

            if (approxedRow.Length > 4)
            {
                int[] indexDel = new int[20];
                int   k        = -1;

                for (int i = 0; i < approxedRow.Length; i++)
                {
                    int pl = i + 1;
                    int mi = i - 1;

                    if (mi == -1)
                    {
                        mi = approxedRow.Length - 1;
                    }

                    if (pl == approxedRow.Length)
                    {
                        pl = 0;
                    }

                    if ((Math.Abs(approxedRow[pl].Y - approxedRow[i].Y) < 30) &&
                        (Math.Abs(approxedRow[mi].Y - approxedRow[i].Y) < 30))
                    {
                        k++;
                        indexDel[k] = i;
                    }
                }

                int n = -1;

                for (int i = 0; i < approxedRow.Length; i++)
                {
                    if (Array.IndexOf(indexDel, i) == -1)
                    {
                        n++;
                        approxed[n] = approxedRow[i];
                    }
                }
            }
            else
            {
                approxed[0] = approxedRow[0];
                approxed[1] = approxedRow[1];
                approxed[2] = approxedRow[2];
                approxed[3] = approxedRow[3];
            }

            //тут мы расставляем точки по местам

            Point2d[] pointsList = new Point2d[4];

            IEnumerable <Point2d> points = new List <Point2d>();

            Point2d[] pointsShow = new Point2d[4];

            for (int p = 0; p < 4; p++)
            {
                int    indexL = 0;
                double maxL   = 0;

                for (int q = 0; q < 4; q++)
                {
                    if (p != q)
                    {
                        double l = Math.Sqrt(Math.Pow(approxed[p].X - approxed[q].X, 2) + Math.Pow(approxed[p].Y - approxed[q].Y, 2));
                        if (maxL < l)
                        {
                            maxL   = l;
                            indexL = q;
                        }
                    }
                }

                if ((approxed[indexL].X - approxed[p].X < 0) && (approxed[indexL].Y - approxed[p].Y > 0))
                {
                    pointsList[0] = approxed[p];
                    pointsShow[0] = approxed[p];
                }
                if ((approxed[indexL].X - approxed[p].X > 0) && (approxed[indexL].Y - approxed[p].Y > 0))
                {
                    pointsList[1] = approxed[p];
                    pointsShow[1] = approxed[p];
                }
                if ((approxed[indexL].X - approxed[p].X > 0) && (approxed[indexL].Y - approxed[p].Y < 0))
                {
                    pointsList[2] = approxed[p];
                    pointsShow[2] = approxed[p];
                }
                if ((approxed[indexL].X - approxed[p].X < 0) && (approxed[indexL].Y - approxed[p].Y < 0))
                {
                    pointsList[3] = approxed[p];
                    pointsShow[3] = approxed[p];
                }
            }

            points = pointsList;

            for (int i = 0; i < 4; i++)
            {
                Cv2.PutText(frame_out, Convert.ToString(i), new OpenCvSharp.Point(Convert.ToInt32(pointsShow[i].X), Convert.ToInt32(pointsShow[i].Y)),
                            HersheyFonts.HersheyDuplex, 0.3, new Scalar(0, 255, 0));
            }

            return(pointsList);
        }
Exemple #19
0
        private void detectShapeCandidates(ref Bitmap bitmap, Boolean saveShapes)
        {
            string      myPhotos = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            Mat         colorMat = BitmapConverter.ToMat(bitmap);
            MatOfDouble mu       = new MatOfDouble();
            MatOfDouble sigma    = new MatOfDouble();

            Cv2.MeanStdDev(colorMat, mu, sigma);
            double mean = mu.GetArray(0, 0)[0];

            mu.Dispose();
            sigma.Dispose();

            Mat greyMat = new Mat();

            Cv2.CvtColor(colorMat, greyMat, ColorConversion.BgraToGray, 0);
            greyMat = greyMat.GaussianBlur(new OpenCvSharp.CPlusPlus.Size(1, 1), 5, 5, BorderType.Default);
            greyMat = greyMat.Canny(0.5 * mean, 1.2 * mean, 3, true);

            Mat contourMat = new Mat(greyMat.Size(), colorMat.Type());

            greyMat.CopyTo(contourMat);
            var contours = contourMat.FindContoursAsArray(ContourRetrieval.List, ContourChain.ApproxSimple);

            this.controls.Clear();
            for (int j = 0; j < contours.Length; j++)
            {
                var poly = Cv2.ApproxPolyDP(contours[j], 0.01 * Cv2.ArcLength(contours[j], true), true);
                int num  = poly.Length;

                if (num >= 4 && num < 20)
                {
                    var color = Scalar.Blue;
                    var rect  = Cv2.BoundingRect(poly);

                    if (rect.Height < 20 || rect.Width < 20)
                    {
                        continue;
                    }
                    if (saveShapes)
                    {
                        string path = Path.Combine(myPhotos, "shape_samples");
                        path = Path.Combine(path, "shape_sample_" + Path.GetRandomFileName() + ".png");
                        Mat    shapeMat = preprocessShape(rect, greyMat);
                        Bitmap shape    = shapeMat.ToBitmap();
                        shape.Save(path);
                        shape.Dispose();
                        shapeMat.Dispose();
                        continue;
                    }
                    if (shapeSVM != null)
                    {
                        Mat   shapeMat   = preprocessShape(rect, greyMat);
                        float shapeClass = classifyShape(shapeMat, shapeSVM);
                        if (shapeClass >= 0)
                        {
                            Shape shape = null;
                            switch ((int)shapeClass)
                            {
                            case 0:
                                color = Scalar.Red;
                                shape = new Shape(Shape.ShapeType.SQUARE, rect);
                                break;

                            case 1:
                                color = Scalar.Yellow;
                                shape = new Shape(Shape.ShapeType.CIRCLE, rect);
                                break;

                            case 2:
                                color = Scalar.Green;
                                shape = new Shape(Shape.ShapeType.SLIDER, rect);
                                break;
                            }
                            Cv2.Rectangle(colorMat, rect, color, 2);
                            this.controls.Add(shape);
                        }
                        shapeMat.Dispose();
                    }
                    else
                    {
                        Cv2.Rectangle(colorMat, rect, color, 2);
                    }
                }
            }
            bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(colorMat);
            colorMat.Dispose();
            greyMat.Dispose();
            contourMat.Dispose();
        }
        //mask the inner part of circle
        static List <Point[]> Mask_innercicle(ref Mat img)
        {
            Mat img_gaussian = Mat.Zeros(img.Size(), MatType.CV_8UC1);

            Cv2.GaussianBlur(img, img_gaussian, new OpenCvSharp.Size(21, 21), 0, 0);

            Mat thresh1 = img_gaussian.Threshold(180, 255, ThresholdTypes.Binary);

            thresh1.SaveImage("threshold.jpg");

            Point[][]        contours;
            HierarchyIndex[] hierarchly;
            Cv2.FindContours(thresh1, out contours, out hierarchly, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple);

            // find final circle
            List <Point[]> contours_final = new List <Point[]>();

            foreach (OpenCvSharp.Point[] contour_now in contours)
            {
                if (Cv2.ContourArea(contour_now) > 1000000 && Cv2.ContourArea(contour_now) < 2500000)
                {
                    contours_final.Add(contour_now);
                }
            }

            ///OpenCvSharp.Point[][] temp = new Point[1][];//for draw on image

            Point[] contours_approx_innercircle;
            var     contour_innercircle = contours_final[1];
            //temp[0] = contour_now;

            Point2f center;
            float   radius;

            //Cv2.DrawContours(vis_rgb, temp, -1, Scalar.Green, thickness: -1);
            contours_approx_innercircle = Cv2.ApproxPolyDP(contour_innercircle, 0.001, true);//speedup
            Cv2.MinEnclosingCircle(contours_approx_innercircle, out center, out radius);
            //Cv2.Circle(img, (Point)center, (int)radius+ stop1_inner_circle_radius, 255, thickness: -1);
            //Cv2.Circle(vis_rgb, (Point)center, (int)radius, Scalar.White, thickness: -1);

            //==================================================outer contour - inner contour=====================================
            // variable
            OpenCvSharp.Point[][] temp = new Point[1][];


            // inner contour
            Mat inner_contour_img = Mat.Zeros(img.Size(), MatType.CV_8UC1);

            //Point[] inner_contour = Cv2.ConvexHull(contours_final[1]);
            temp[0] = contours_final[1];
            //Cv2.DrawContours(inner_contour_img, temp, -1, 255, -1);
            Cv2.DrawContours(inner_contour_img, temp, -1, 255, -1);
            //Cv2.Circle(inner_contour_img, (Point)center, (int)radius + stop1_inner_circle_radius, 255, thickness: -1);

            // outer contour
            Mat outer_contour_img  = Mat.Zeros(img.Size(), MatType.CV_8UC1);
            Mat outer_contour_img2 = new Mat(img.Size(), MatType.CV_8UC1, new Scalar(255));//initilize Mat with the value 255

            temp[0] = contours_final[0];
            Cv2.DrawContours(outer_contour_img, temp, -1, 255, -1);
            //outer contour2 in order to make mask area = 255
            Cv2.DrawContours(outer_contour_img2, temp, -1, 0, -1);
            //outer - inner
            Mat diff_mask  = outer_contour_img - inner_contour_img;
            Mat diff_mask2 = inner_contour_img + outer_contour_img2;

            Mat image = Mat.Zeros(img.Size(), MatType.CV_8UC1);

            img.CopyTo(image, diff_mask);
            //in order to make mask area = 255
            img = image + diff_mask2;


            return(contours_final);
        }
Exemple #21
0
    private static void SegmentationCannyFilledPolygons(Camera camera, out List <Point2f> v_center, out List <float> v_radius)
    {
        RenderTexture activeRenderTexture = RenderTexture.active;

        RenderTexture.active = camera.targetTexture;
        camera.Render();
        Texture2D currentFrame = new Texture2D(camera.targetTexture.width, camera.targetTexture.height);

        currentFrame.ReadPixels(new UnityEngine.Rect(0, 0, camera.targetTexture.width, camera.targetTexture.height), 0, 0);
        currentFrame.Apply();
        RenderTexture.active = activeRenderTexture;
        Mat image = OpenCvSharp.Unity.TextureToMat(currentFrame);

        UnityEngine.Object.Destroy(currentFrame);
        Mat grayImage = new Mat();

        Cv2.CvtColor(image, grayImage, ColorConversionCodes.BGR2GRAY);
        Cv2.EqualizeHist(grayImage, grayImage);
        Cv2.GaussianBlur(grayImage, grayImage, new Size(9, 9), 2, 2);

        Mat edgesImage = new Mat();

        Cv2.Canny(grayImage, edgesImage, 40, 20);
        Point[][]        contours_canny;
        HierarchyIndex[] hierarchy_canny;

        Cv2.FindContours(edgesImage, out contours_canny, out hierarchy_canny, RetrievalModes.List, ContourApproximationModes.ApproxSimple, null);

        Mat img_all_contours_and_filled = Mat.Zeros(edgesImage.Height, edgesImage.Width, MatType.CV_8UC1);
        Mat img_all_contours            = Mat.Zeros(edgesImage.Height, edgesImage.Width, MatType.CV_8UC1);

        for (int j = 0; j < contours_canny.Length; j++)
        {
            Scalar color = new Scalar(255, 255, 255);
            Cv2.DrawContours(img_all_contours_and_filled, contours_canny, j, color, -1, LineTypes.Link8, hierarchy_canny);
            Cv2.DrawContours(img_all_contours, contours_canny, j, color, 1, LineTypes.Link8, hierarchy_canny);
        }
        Mat img_only_closed_contours = new Mat();

        Cv2.Absdiff(img_all_contours_and_filled, img_all_contours, img_only_closed_contours);

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

        Cv2.FindContours(img_only_closed_contours, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxTC89L1, null);

        Point[][]          contours_poly   = new Point[contours.Length][];
        OpenCvSharp.Rect[] boundRect       = new OpenCvSharp.Rect[contours.Length];
        List <Point2f>     contours_center = new List <Point2f> {
        };
        List <float> contours_radius       = new List <float> {
        };

        int i_contour = 0;

        foreach (Point[] contour in contours)
        {
            Point2f contour_center;
            float   contour_radius;

            contours_poly[i_contour] = Cv2.ApproxPolyDP(contour, 3, true);
            Cv2.MinEnclosingCircle(contours_poly[i_contour], out contour_center, out contour_radius);
            //currentFrame = DrawCircle(currentFrame, (int)contour_center.X, (int)contour_center.Y, (int)contour_radius);

            contours_center.Add(contour_center);
            contours_radius.Add(contour_radius);
            i_contour++;
        }

        v_center = contours_center;
        v_radius = contours_radius;

        //TextureToPNG(currentFrame);
    }
        private void LoadImage(string filePath)
        {
            //using (Mat mat1 = Mat.Zeros(2048, 1536, MatType.CV_8UC1))
            //using (Mat mat2 = Mat.Zeros(2048, 1536, MatType.CV_8UC1))
            //using (var intersection = new Mat(2048, 1536, MatType.CV_8UC1))
            //using (var union = new Mat(2048, 1536, MatType.CV_8UC1))
            //{
            //    mat1.FillPoly(new[] { new[]
            //    {
            //        new Point(565, 267),
            //        new Point(1210, 207),
            //        new Point(1275, 1720),
            //        new Point(568, 1688)
            //    } }, Scalar.All(255));
            //    AddImage(mat1);
            //    mat2.FillPoly(new[] { new[]
            //    {
            //        new Point(564, 268),
            //        new Point(1208, 208),
            //        new Point(1272, 1716),
            //        new Point(572, 1688)
            //    } }, Scalar.All(255));
            //    AddImage(mat2);
            //    Cv2.BitwiseAnd(mat1, mat2, intersection);
            //    int intersectionPixels = Cv2.CountNonZero(intersection);
            //    AddImage(intersection);
            //    Cv2.BitwiseOr(mat1, mat2, union);
            //    int unionPixels = Cv2.CountNonZero(union);
            //    AddImage(union);
            //    double iou = (double) intersectionPixels / unionPixels;
            //}
            //
            //return;

            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.BGRA2GRAY))                            //Convert to gray scale since we don't want the color data
                            using (Mat blur = gray.GaussianBlur(new Size(5, 5), 0, borderType: BorderTypes.Replicate)) //Smooth the image to eliminate noise
                                using (Mat autoCanny = blur.AutoCanny(0.75))                                           //Apply canny edge filter to find edges
                                {
                                    AddImage(blur);
                                    AddImage(autoCanny);

                                    Point[][] contours = autoCanny.FindContoursAsArray(RetrievalModes.List, ContourApproximationModes.ApproxSimple);

                                    //Just get the external hull of the contours
                                    for (int i = 0; i < contours.Length; i++)
                                    {
                                        contours[i] = Cv2.ConvexHull(contours[i]);
                                    }

                                    //Draw all of the found polygons. This is just 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.02 * permimiter, true)
                                                                               where IsValidRectangle(approx, 0.2)
                                                                               let area = Cv2.ContourArea(contour)
                                                                                          orderby area descending            //We are looking for the biggest thing
                                                                                          select contour).Take(3).ToArray(); //Grabbing three just for comparison

                                    //Colors the found polygons Green->Yellow->Red to indicate best matches.
                                    for (int i = found.Length - 1; i >= 0; 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());
            }

            bool IsValidRectangle(Point[] contour, double minimum)
            {
                if (contour.Length != 4)
                {
                    return(false);
                }
                double side1 = GetLength(contour[0], contour[1]);
                double side2 = GetLength(contour[1], contour[2]);
                double side3 = GetLength(contour[2], contour[3]);
                double side4 = GetLength(contour[3], contour[0]);

                if (Math.Abs(side1 - side3) / Math.Max(side1, side3) > minimum)
                {
                    return(false);
                }
                if (Math.Abs(side2 - side4) / Math.Max(side2, side4) > minimum)
                {
                    return(false);
                }

                return(true);

                double GetLength(Point p1, Point p2) => Math.Abs(p1.X - p2.X) + Math.Abs(p1.Y - p2.Y);
            }

            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 #23
0
        static void Main(string[] args)
        {
            UdpClient   client = new UdpClient();
            List <byte> data   = new List <byte>();

            int x2 = 0;
            int y2 = 0;
            int a2 = 0;

            HttpCamera skyCam = new HttpCamera("HTTPCam", "http://192.168.1.121:1181/stream.mjpg");

            MjpegServer mjpeg = new MjpegServer("MjpegServer", 9000);

            mjpeg.Source = skyCam;

            CvSink skySink = new CvSink("Sky");

            skySink.Source  = mjpeg.Source;
            skySink.Enabled = true;

            CvSource    cvSource1     = new CvSource("Source 1", PixelFormat.Mjpeg, 1920, 1080, 30);
            MjpegServer source1Server = new MjpegServer("Source 1 server", 9001);

            source1Server.Source = cvSource1;

            CvSource    cvSource2     = new CvSource("Source 2", PixelFormat.Mjpeg, 1920, 1080, 30);
            MjpegServer inRangeServer = new MjpegServer("Source 2 server", 9002);

            inRangeServer.Source = cvSource2;


            cvSource2.CreateProperty("HLow", PropertyKind.Integer, 0, 180, 1, 75, 75);
            cvSource2.CreateProperty("HHigh", PropertyKind.Integer, 0, 180, 1, 80, 80);

            cvSource2.CreateProperty("SLow", PropertyKind.Integer, 0, 255, 1, 21, 21);
            cvSource2.CreateProperty("SHigh", PropertyKind.Integer, 0, 255, 1, 255, 255);

            cvSource2.CreateProperty("VLow", PropertyKind.Integer, 0, 255, 1, 131, 131);
            cvSource2.CreateProperty("VHigh", PropertyKind.Integer, 0, 255, 1, 255, 255);

            //IPEndPoint EP = new IPEndPoint(IPAddress.Any, 0);
            //UdpClient reciever = new UdpClient(9003, AddressFamily.InterNetwork);

            //while (true)
            //{
            //    byte[] received = reciever.Receive(ref EP);
            //    Console.Write("{ ");
            //    for (int i = 0; i < received.Length; i++)
            //    {
            //        Console.Write($"{received[i]}{(i < received.Length - 1 ? "," : "")}");
            //    }
            //    Console.WriteLine($" }} (from: {EP})");
            //}

            Mat input       = new Mat();
            Mat hsv         = new Mat();
            Mat inRange     = new Mat();
            Mat inRangeCopy = new Mat();

            double angle1 = 0;
            double angle2 = 0;

            Stopwatch sw = new Stopwatch();

            while (true)
            {
                sw.Restart();
                if (skySink.GrabFrame(input) == 0)
                {
                    continue;
                }



                //Cv2.Resize(input, input, new Size(640, 360));

                Cv2.CvtColor(input, hsv, ColorConversionCodes.BGR2HSV);

                int hlow  = cvSource2.GetProperty("HLow").Get();
                int hhigh = cvSource2.GetProperty("HHigh").Get();
                int slow  = cvSource2.GetProperty("SLow").Get();
                int shigh = cvSource2.GetProperty("SHigh").Get();
                int vlow  = cvSource2.GetProperty("VLow").Get();
                int vhigh = cvSource2.GetProperty("VHigh").Get();

                Cv2.InRange(hsv, new Scalar(hlow, slow, vlow), new Scalar(hhigh, shigh, vhigh), inRange);

                inRange.CopyTo(inRangeCopy);
                Point[][]      contours   = Cv2.FindContoursAsArray(inRangeCopy, RetrievalModes.List, ContourApproximationModes.ApproxTC89KCOS);
                List <int>     averages   = new List <int>();
                List <Point[]> polyPoints = new List <Point[]>();


                foreach (var contour in contours)
                {
                    Point[] hull = Cv2.ConvexHull(contour);

                    Point[] poly = Cv2.ApproxPolyDP(hull, 5, true);
                    if (poly.Length == 3)
                    {
                        if (Cv2.ContourArea(hull) < 580)
                        {
                            #region OtherTriangle
                            if (Cv2.ContourArea(hull) < 520)
                            {
                                continue;
                            }
                            double yAv = 0;
                            double xAv = 0;
                            int    ct  = 0;
                            for (int i = 0; i < poly.Length; i++)
                            {
                                ct++;
                                xAv += poly[i].X;
                                yAv += poly[i].Y;
                            }

                            double zO = poly[0].DistanceTo(poly[1]);
                            double oT = poly[1].DistanceTo(poly[2]);
                            double tZ = poly[2].DistanceTo(poly[0]);

                            double op  = 0;
                            double adj = 0;
                            bool   rQ  = false;

                            if (zO < oT && zO < tZ)
                            {
                                Point p = new Point((poly[0].X + poly[1].X) / 2, (poly[0].Y + poly[1].Y) / 2);
                                input.Line(p, poly[2], Scalar.White, 2);
                                op  = poly[2].Y - p.Y;
                                adj = poly[2].X - p.X;
                                if (adj >= 0)
                                {
                                    rQ = true;
                                }
                            }
                            else if (oT < zO && oT < tZ)
                            {
                                Point p = new Point((poly[1].X + poly[2].X) / 2, (poly[1].Y + poly[2].Y) / 2);
                                input.Line(p, poly[0], Scalar.White, 2);
                                op  = poly[0].Y - p.Y;
                                adj = poly[0].X - p.X;
                                if (adj >= 0)
                                {
                                    rQ = true;
                                }
                            }
                            else
                            {
                                Point p = new Point((poly[2].X + poly[0].X) / 2, (poly[2].Y + poly[0].Y) / 2);
                                input.Line(p, poly[1], Scalar.White, 2);
                                op  = poly[1].Y - p.Y;
                                adj = poly[1].X - p.X;
                                if (adj >= 0)
                                {
                                    rQ = true;
                                }
                            }

                            xAv /= ct;
                            yAv /= ct;

                            x2 = (int)(xAv * 100);
                            y2 = (int)(yAv * 100);
                            a2 = (int)((Math.Atan(op / adj) * 180 / Math.PI));
                            if (rQ)
                            {
                                a2 = a2 + 270;
                                rQ = false;
                            }
                            else
                            {
                                a2 += 90;
                            }
                            #endregion

                            continue;
                        }
                        double yAverage = 0;
                        double xAverage = 0;
                        int    count    = 0;
                        for (int i = 0; i < poly.Length; i++)
                        {
                            count++;
                            xAverage += poly[i].X;
                            yAverage += poly[i].Y;
                        }

                        double zeroOne = poly[0].DistanceTo(poly[1]);
                        double oneTwo  = poly[1].DistanceTo(poly[2]);
                        double twoZero = poly[2].DistanceTo(poly[0]);

                        double opposite       = 0;
                        double adjacent       = 0;
                        bool   rightQuadrants = false;

                        if (zeroOne < oneTwo && zeroOne < twoZero)
                        {
                            Point p = new Point((poly[0].X + poly[1].X) / 2, (poly[0].Y + poly[1].Y) / 2);
                            input.Line(p, poly[2], Scalar.White, 2);
                            opposite = poly[2].Y - p.Y;
                            adjacent = poly[2].X - p.X;
                            if (adjacent >= 0)
                            {
                                rightQuadrants = true;
                            }
                        }
                        else if (oneTwo < zeroOne && oneTwo < twoZero)
                        {
                            Point p = new Point((poly[1].X + poly[2].X) / 2, (poly[1].Y + poly[2].Y) / 2);
                            input.Line(p, poly[0], Scalar.White, 2);
                            opposite = poly[0].Y - p.Y;
                            adjacent = poly[0].X - p.X;
                            if (adjacent >= 0)
                            {
                                rightQuadrants = true;
                            }
                        }
                        else
                        {
                            Point p = new Point((poly[2].X + poly[0].X) / 2, (poly[2].Y + poly[0].Y) / 2);
                            input.Line(p, poly[1], Scalar.White, 2);
                            opposite = poly[1].Y - p.Y;
                            adjacent = poly[1].X - p.X;
                            if (adjacent >= 0)
                            {
                                rightQuadrants = true;
                            }
                        }

                        xAverage /= count;
                        yAverage /= count;

                        int x     = (int)(xAverage * 100);
                        int y     = (int)(yAverage * 100);
                        int angle = (int)((Math.Atan(opposite / adjacent) * 180 / Math.PI));
                        if (rightQuadrants)
                        {
                            angle          = angle + 270;
                            rightQuadrants = false;
                        }
                        else
                        {
                            angle += 90;
                        }
                        //Console.WriteLine(angle);
                        AddData(x, data);
                        AddData(y, data);
                        AddData(angle, data);
                    }
                    else if (poly.Length == 4)
                    {
                        if (Cv2.ContourArea(hull) < 300)
                        {
                            continue;
                        }
                        polyPoints.Add(poly);
                        Rect  boundingRect = Cv2.BoundingRect(poly);
                        Point centerPoint  = new Point(boundingRect.X + boundingRect.Width / 2, boundingRect.Y + boundingRect.Height / 2);

                        if (boundingRect.X < 540)
                        {
                            Cv2.Circle(input, centerPoint, 10, Scalar.AliceBlue);
                            Point difference = centerPoint - new Point(421, 372);

                            angle1 = Math.Atan2(difference.X, difference.Y) * 180 / Math.PI;
                        }
                        else
                        {
                            Cv2.Circle(input, centerPoint, 10, Scalar.HotPink);
                            Point difference = centerPoint - new Point(876, 369);

                            angle2 = Math.Atan2(difference.X, difference.Y) * 180 / Math.PI;
                        }
                    }
                }
                input.PutText("Angle1: " + angle1.ToString(), new Point(421, 400), HersheyFonts.HersheyComplex, 0.5f, Scalar.AliceBlue);


                input.PutText("Angle2: " + angle2.ToString(), new Point(876, 400), HersheyFonts.HersheyComplex, 0.5f, Scalar.HotPink);
                Cv2.Circle(input, new Point(421, 372), 1, Scalar.AliceBlue);
                Cv2.Circle(input, new Point(876, 369), 1, Scalar.AliceBlue);

                AddData((int)Math.Round(angle1, 0), data);
                AddData((int)Math.Round(angle2, 0), data);
                AddData(x2, data);
                AddData(y2, data);
                AddData(a2, data);

                input.DrawContours(polyPoints, -1, Scalar.Blue, -1);
                cvSource1.PutFrame(input);
                cvSource2.PutFrame(inRange);
                client.Send(data.ToArray(), data.Count, new IPEndPoint(IPAddress.Loopback, 9003));
                data.Clear();
                Console.WriteLine(sw.Elapsed);
                //Thread.Sleep(20);
            }
        }