使用C#版OpenCV進行圓心求取

OpenCVSharp是OpenCV的.NET wrapper,是一名日本工程師開發的,項目地址爲:https://github.com/shimat/opencvsharp。git

該源碼是 BSD開放協議,BSD開源協議是一個給於使用者很大自由的協議。基本上使用者能夠」隨心所欲」,能夠自由的使用,修改源代碼,也能夠將修改後的代碼做爲開源或者專有軟件再發布或商業化銷售。github

1.OpenCVSharp的下載

能夠直接從上面的github上下載源碼,自行編譯引用;app

也可用vs中的nuget包管理器下載;函數

打開【工具】->【庫程序包管理器】->【管理解決方案的NuGet程序包】,在其中搜索OpenCVSharp,選擇合適的點擊【安裝】(最好安裝最新的)。一直等待完成。工具

個人環境是vs2017,下載以後最好直接拷貝OpenCVSharp系列dll到項目中引用便可。測試

2.擬合圓並求取圓心

本次舉例比較貼近實際,咱們求以下原始圖片的中間部分圓的圓心,選取的圖片故意只留了一半:spa

源碼以下:3d

using OpenCvSharp;

namespace FitCircleDemo
{
    public class CircleFit 
    {
        public  Mat Run(string imgPath)
        {
            //讀取圖片
            //var img = Cv2.ImRead("Data/Image/c1.bmp");
            var img = Cv2.ImRead(imgPath);
            //顯示圖片
            //Cv2.ImShow("Input Image", img);

            //轉換成灰度圖
            Mat gray = img.CvtColor(ColorConversionCodes.BGR2GRAY);
           
            //閾值操做 閾值參數能夠用一些可視化工具來調試獲得
            Mat ThresholdImg = gray.Threshold(11, 255,  ThresholdTypes.Binary);
            Cv2.ImShow("Threshold", ThresholdImg);

            //降噪
            //方法一:高斯變化
            //Mat gaussImg= ThresholdImg.GaussianBlur(new Size(5, 5), 0.8);
            //Cv2.ImShow("GaussianBlur", gaussImg);
            //方法二:中值濾波降噪
            //Mat medianImg = ThresholdImg.MedianBlur(5);
            //Cv2.ImShow("MedianBlur", medianImg);

            //方法三:膨脹+腐蝕
            ////膨脹處理
            //Mat kernel = new Mat(15, 15, MatType.CV_8UC1);
            //Mat DilateImg = ThresholdImg.Dilate(kernel);
            ////腐蝕處理
            //Mat binary = DilateImg.Erode(kernel);
            ////顯示中間結果
            //Cv2.ImShow("Dilate & Erode", binary);
            Mat element = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(3, 3));
            Mat openImg = ThresholdImg.MorphologyEx(MorphTypes.Open, element);
            Cv2.ImShow("Dilate & Erode", openImg);

            //設置感興趣的區域
            int x = 150, y = 100, w = 294, h = 337;
            Rect roi = new Rect(x, y, w, h);
            Mat ROIimg = new Mat(openImg, roi);
            //Cv2.ImShow("ROI Image", ROIimg);

            //尋找圖像輪廓
            Point[][] contours;
            HierarchyIndex[] hierachy;
            Cv2.FindContours(ROIimg, out contours, out hierachy, RetrievalModes.List, ContourApproximationModes.ApproxTC89KCOS);
            //根據找到的輪廓點,擬合橢圓
            for (int i = 0; i < contours.Length; i++)
            {
                //擬合函數必須至少5個點,少於則不擬合
                if (contours[i].Length < 5) continue;
                //橢圓擬合
                var rrt = Cv2.FitEllipse(contours[i]);

                //ROI復原
                rrt.Center.X += x;
                rrt.Center.Y += y;

                //畫橢圓
                Cv2.Ellipse(img, rrt, new Scalar(0, 0, 255), 2, LineTypes.AntiAlias);
                //畫圓心
                Cv2.Circle(img, (int)(rrt.Center.X), (int)(rrt.Center.Y), 4, new Scalar(255, 0, 0), -1, LineTypes.Link8, 0);
            }
            
            Cv2.ImShow("Fit Circle", img);
            return img;
        }
     }
}

 

中間處理過程效果圖以下:調試

分別是閾值分割後,中值濾波後,擬合圓以後code

 

對上圖中第一張進行降噪方法有不少,經測試最有效的是中值濾波(MedianBlur)和腐蝕&膨脹(MorphologyEx)處理

中值濾波基本思想是用像素點鄰域灰度值的中值來代替該像素點的灰度值,讓周圍的像素值接近真實的值從而消除孤立的噪聲點。

高級形態學變換:
開運算:
先腐蝕,再膨脹,可清除一些小東西(亮的),放大局部低亮度的區域
閉運算:
先膨脹,再腐蝕,可清除小黑點
形態學梯度:
膨脹圖與腐蝕圖之差,提取物體邊緣
頂帽:
原圖像-開運算圖,突出原圖像中比周圍亮的區域
黑帽:
閉運算圖-原圖像,突出原圖像中比周圍暗的區域

1.腐蝕
首先說腐蝕,腐蝕是縮小圖像,去除小溝壑細節的一種操做,腐蝕的概念很好理解,可是公式看起來卻很麻煩,我這裏主要說概念。
腐蝕操做須要兩個元素,一個待處理對象A,一個element B,B對A的腐蝕獲得的結果是由A中可以包含整個B的像素點所組成的,以下圖所示:

其中比較關鍵的是B的錨點,就是B的錨點在A中掃描時,A能將B徹底包住的B的錨點所掃描的像素點。

腐蝕的做用:去除圖像中不想要的小細節,好比一張二值圖片中的噪點或者小細節。
符號:⊖ \ominus⊖

2.膨脹
膨脹的須要與腐蝕徹底相同只是他們的做用相反,element B膨脹圖形A的結果是,A和B的並集產生的,以下:

B的錨點在A的邊界進行掃描,A與B的並集就是B對A進行膨脹的結果。

相關文章
相關標籤/搜索