簡體   English   中英

如何使用emgu cv擺脫不必要的行

[英]How to get rid of unnecessary lines with emgu cv

我正在嘗試使用 Emgu CV 檢測橢圓形水滴的輪廓。 我寫了輪廓檢測的代碼:

    public List<int> GetDiameters()
    {
        string inputFile = @"path.jpg";

        Image<Bgr, byte> imageInput = new Image<Bgr, byte>(inputFile);

        Image<Gray, byte> grayImage = imageInput.Convert<Gray, byte>();

        Image<Gray, byte> bluredImage = grayImage;
        CvInvoke.MedianBlur(grayImage, bluredImage, 9);

        Image<Gray, byte> edgedImage = bluredImage;
        CvInvoke.Canny(bluredImage, edgedImage, 50, 5);

        Image<Gray, byte> closedImage = edgedImage;           
        Mat kernel = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Ellipse, new System.Drawing.Size { Height = 100, Width = 250}, new System.Drawing.Point(-1, -1)); 
        CvInvoke.MorphologyEx(edgedImage, closedImage, Emgu.CV.CvEnum.MorphOp.Close, kernel, new System.Drawing.Point(-1, -1), 0, Emgu.CV.CvEnum.BorderType.Replicate, new MCvScalar());
       System.Drawing.Point(100, 250), 10000, Emgu.CV.CvEnum.BorderType.Default, new MCvScalar()

        Image<Gray, byte> contoursImage = closedImage;
        Image<Bgr, byte> imageOut = imageInput;
        VectorOfVectorOfPoint rescontours1 = new VectorOfVectorOfPoint();
        using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
        {
            CvInvoke.FindContours(contoursImage, contours, null, Emgu.CV.CvEnum.RetrType.List,
                Emgu.CV.CvEnum.ChainApproxMethod.LinkRuns);
            MCvScalar color = new MCvScalar(0, 0, 255);

            int count = contours.Size;
            for (int i = 0; i < count; i++)
            {
                using (VectorOfPoint contour = contours[i])
                    using (VectorOfPoint approxContour = new VectorOfPoint())
                    {
                        CvInvoke.ApproxPolyDP(contour, approxContour,
                            0.01 * CvInvoke.ArcLength(contour, true), true);

                        var area = CvInvoke.ContourArea(contour);

                    if (area > 0 && approxContour.Size > 10)
                    {
                        rescontours1.Push(approxContour);
                    }

                        CvInvoke.DrawContours(imageOut, rescontours1, -1, color, 2);
                    }                   
            }
        }          
    }

到目前為止的結果:

在此處輸入圖片說明

我認為近似值有問題。 如何去除內部線條,閉合外部輪廓?

我可能需要更多信息來准確定位您的問題,但這可能與您的中位數模糊有關。 我會看看你是否足夠模糊以至於 EmguCV 的東西模糊足夠你可以進行邊緣檢測。 您可以使用的另一種方法是 Dilate。 嘗試撥打您的 Canny 邊緣檢測,看看是否有更好的結果。

編輯

這是下面的代碼

    public List<int> GetDiameters()
    {
        //List to hold output diameters
        List<int> diametors = new List<int>();

        //File path to where the image is located
        string inputFile = @"C:\Users\jones\Desktop\Image Folder\water.JPG";

        //Read in the image and store it as a mat object
        Mat img = CvInvoke.Imread(inputFile, Emgu.CV.CvEnum.ImreadModes.AnyColor);

        //Mat object that will hold the output of the gaussian blur
        Mat gaussianBlur = new Mat();

        //Blur the image
        CvInvoke.GaussianBlur(img, gaussianBlur, new System.Drawing.Size(21, 21), 20, 20, Emgu.CV.CvEnum.BorderType.Default);

        //Mat object that will hold the output of the canny
        Mat canny = new Mat();

        //Canny the image
        CvInvoke.Canny(gaussianBlur, canny, 40, 40);

        //Mat object that will hold the output of the dilate
        Mat dilate = new Mat();

        //Dilate the canny image
        CvInvoke.Dilate(canny, dilate, null, new System.Drawing.Point(-1, -1), 6, Emgu.CV.CvEnum.BorderType.Default, new MCvScalar(0, 0, 0));

        //Vector that will hold all found contours
        VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();

        //Find the contours and draw them on the image
        CvInvoke.FindContours(dilate, contours, null, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
        CvInvoke.DrawContours(img, contours, -1, new MCvScalar(255, 0, 0), 5, Emgu.CV.CvEnum.LineType.FourConnected);

        //Variables to hold relevent info on what is the biggest contour
        int biggest = 0;
        int index = 0;

        //Find the biggest contour
        for (int i = 0; i < contours.Size; i++)
        {
            if (contours.Size > biggest)
            {
                biggest = contours.Size;
                index = i;
            }
        }

        //Once all contours have been looped over, add the biggest contour's index to the list
        diametors.Add(index);

        //Return the list
        return diametors;
    }

您要做的第一件事是模糊圖像。 在此處輸入圖片說明

然后你精明的形象。 在此處輸入圖片說明

然后擴大圖像,使最終輸出輪廓更均勻。 在此處輸入圖片說明

然后你就可以找到輪廓。 在此處輸入圖片說明

我知道最終的輪廓比水滴大一點,但這是我能想到的最好的。 您可能會擺弄一些設置和上面的代碼,以使結果更清晰一些。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM