2017-07-08 13 views
10

Używam Visual Studio 2015, OpenCV.3 i EmguCV.3. Mój kod przedstawiony poniżej, a wynik jest pokazany na obrazku. Wiem, że problem jest wartości wejściowych funkcji HoughCircles, ale nie wiem, które dane wejściowe są odpowiednie dla tego obrazu. Doceniam każdą pomoc.HoughCircles Nie wykrywa kół prawidłowo w 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(); 

Obraz oryginału:

enter image description here

założenia Koła:

enter image description here

+0

Czy możesz podać oryginalny obraz? Sądzę, że spodziewasz się 2 kółek? –

+0

@SimonMourier Edytowałem pytanie i dodałem oryginalny obraz. Właściwie tak, spodziewam się 2 kółek. –

+0

Używam opencvsharp (który jest bardzo blisko C++/python próbek), nie emgucv, czy to dla ciebie ok? –

Odpowiedz

7

Praca z pełnych kształtach, może się okazać, że łatwiej pracować wykrywać krawędzie, a następnie znaleźć kontury. Oto przykład:

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"); 

oto wynik, od lewej do prawej:

  1. Oryginalny obraz
  2. zamazany obraz (przy użyciu pyrdown/pyrup)
  3. Wynik z detekcją obrotny krawędzi
  4. Zrekonstruowane koła z konturów

process from the original image to the result

3

Oto rozwiązanie (oparte na OpenCvSharp, a nie na emgucv, który pozwala kod C#, aby być bardzo blisko do wszystkich kod OpenCV, które można znaleźć w C++ lub Python, ale można łatwo przekonwertować go z powrotem do emgucv) .

Usunąłem krok Erode i Dilate (które w tym przypadku po prostu zniszczą oryginalny obraz za bardzo).

Co Kiedyś to pętla na rozmowach houh okręgu (zmieniając stosunek odwrotny do uchwały dla akumulatora) w celu zapewnienia wykryć więcej niż jedno kółko, a nie koła nie jestem zainteresowany.

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; 
    } 

Tutaj to wynik:

enter image description here