2017-07-08 275 views
10

我正在使用Visual Studio 2015,OpenCV.3和EmguCV.3。 我的代碼如下所示,結果顯示在圖片中。我知道問題是HoughCircles函數的輸入值,但我不知道哪些輸入適合這張圖片。我感謝任何幫助。HoughCircles在OpenCV中未正確檢測到圓圈

   Image<Gray, byte> OriginalImage = new Image<Gray, byte>(Openfile.FileName); 
       Image<Gray, byte> ResizedImage = OriginalImage.Resize(OriginalImage.Width/2, OriginalImage.Height/2, Emgu.CV.CvEnum.Inter.Cubic); 

       //********** Convert Image to Binary 
       Image<Gray, byte> smoothImg = 
       ResizedImage.SmoothGaussian(5); 
       smoothImg._Erode(5); 
       smoothImg._Dilate(5); 
       Image<Gray, byte> BinaryImage = 
       smoothImg.ThresholdBinary(new Gray(20), new Gray(255)); 

       //********** Find Circles 
       Image<Rgb, byte> ROIImgScaledCircles = ROIImgScaled.Convert<Rgb, byte>(); 
       CircleF[] circles = smoothImg.HoughCircles(
        new Gray(180),//cannyThreshold 
        new Gray(60),//circleAccumulatorThreshold 
        2.0, //dp:Resolution of the accumulator used to detect centers of the circles 
        10.0, //min distance 
        10, //min radius 
        128 //max radius 
        )[0]; //Get the circles from the first channel 
       foreach (CircleF cir in circles) 
       { 
        ROIImgScaledCircles.Draw(cir, new Rgb(235, 20, 30), 1); 
       }     
       pbxCircles.Image = ROIImgScaledCircles.ToBitmap(); 

原始圖像:

enter image description here

成立圓:

enter image description here

+0

你能提供原始圖像嗎?我猜你期望2個圈子? –

+0

@SimonMourier我編輯了問題並添加了原始圖像。其實是的,我期待2個圈子。 –

+0

我使用opencvsharp(這非常接近C++/python樣本),而不是emgucv,那對你來說好嗎? –

回答

7

完整形狀的工作,你可能會發現更容易的工作檢測邊緣,然後找到輪廓。下面是一個例子:

Image<Bgr, byte> original = new Image<Bgr, byte>(@"E:\Downloads\original.jpg"); 
    UMat grayscale = new UMat();    
    UMat pyrdown = new UMat(); 
    UMat canny = new UMat(); 

    double cannyThreshold = 128; 

    CvInvoke.CvtColor(original, grayscale, ColorConversion.Bgr2Gray);   
    // remove noise and run edge detection 
    CvInvoke.PyrDown(grayscale, pyrdown); 
    CvInvoke.PyrUp(pyrdown, grayscale); 
    CvInvoke.Canny(grayscale, canny, cannyThreshold, cannyThreshold * 2); 

    Image<Bgr, byte> result = original.Copy(); 
    // find and draw circles 
    VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint(); 
    CvInvoke.FindContours(canny, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple); 
    //CvInvoke.DrawContours(result, contours, -1, new MCvScalar(0, 0, 255)); 
    for (int i = 0; i < contours.Size; i++) 
    { 
     Ellipse ellipse = new Ellipse(CvInvoke.FitEllipse(contours[i])); 
     result.Draw(ellipse, new Bgr(Color.Red), 1); 
    } 

    result.Save(@"E:\Downloads\circles.jpg"); 

這裏的結果,從左至右:

  1. 原始圖像
  2. 模糊圖像(使用pyrdown/pyrup)從Canny邊緣檢測
  3. 結果
  4. 輪廓重構圓

process from the original image to the result

3

這裏是一個解決方案(基於OpenCvSharp,而不是emgucv,這使得C#代碼是非常接近所有OpenCV的代碼,你可以在C找到++或Python,但你可以很容易地將其轉換回emgucv) 。

我已經刪除了腐蝕和擴張步驟(在這種情況下,只是摧毀了原始圖像太多)。

我用什麼是houh圓調用一個循環(改變反比到累加器分辨率),以確保我發現不止一個圈,而不是圈我不感興趣的內容。

int blurSize = 5; 
    using (var src = new Mat("2Okrv.jpg")) 
    using (var gray = src.CvtColor(ColorConversionCodes.BGR2GRAY)) 
    using (var blur = gray.GaussianBlur(new Size(blurSize, blurSize), 0)) 
    using (var dst = src.Clone()) 
    { 
     // this hashset will automatically store all "unique" detected circles 
     // circles are stored modulo some "espilon" value, set to 5 here (half of min size of hough circles below) 
     var allCircles = new HashSet<CircleSegment>(new CircleEqualityComparer { Epsilon = 5 }); 

     // vary inverse ratio of accumulator resolution 
     // depending on image, you may vary start/end/step 
     for (double dp = 1; dp < 5; dp += 0.2) 
     { 
      // we use min dist = 1, to make sure we can detect concentric circles 
      // we use standard values for other parameters (canny, ...) 
      // we use your min max values (the max may be important when dp varies) 
      var circles = Cv2.HoughCircles(blur, HoughMethods.Gradient, dp, 1, 100, 100, 10, 128); 
      foreach (var circle in circles) 
      { 
       allCircles.Add(circle); 
      } 
     } 

     // draw final list of unique circles 
     foreach (var circle in allCircles) 
     { 
      Cv2.Circle(dst, circle.Center, (int)circle.Radius, Scalar.FromRgb(235, 20, 30), 1); 
     } 

     // display images 
     using (new Window("src image", src)) 
     using (new Window("dst image", dst)) 
     { 
      Cv2.WaitKey(); 
     } 
    } 

    public class CircleEqualityComparer : IEqualityComparer<CircleSegment> 
    { 
     public double Epsilon { get; set; } 

     public bool Equals(CircleSegment x, CircleSegment y) => x.Center.DistanceTo(y.Center) <= Epsilon && Math.Abs(x.Radius - y.Radius) <= Epsilon; 

     // bit of a hack... we return a constant so only Equals is used to compare two circles 
     // since we have only few circles that's ok, we don't play with millions... 
     public int GetHashCode(CircleSegment obj) => 0; 
    } 

這裏是結果:

enter image description here