2015-07-05 7 views
6

Derzeit entwickle ich eine App, die Kreise von Fotos erkennen wird. Ich habe es geschafft, einen Code dafür zu schreiben, aber es macht entweder falsche Negative oder falsche Positive, wenn ich ein bisschen vom PC-Bildschirm entfernt bin. Wie kann ich das Ergebnis verbessern? Ich meine, es gibt viele Apps, die kleine und unklare Kreise erkennen.Android OpenCV Verbesserte Erkennungsqualität

[Update]

I mit Werten in GaussianBlur und HoughCircles bin Hantieren. Ändern Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 2, 2); zu Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 9, 9); und doppelte param1 = 70, param2 = 72; zu double param1 = 50, param2 = 52; verbessern das Ergebnis, aber nicht genug.

  Mat mat = new Mat(bitmap.getWidth(), bitmap.getHeight(), 
        CvType.CV_8UC1); 
      Mat grayMat = new Mat(bitmap.getWidth(), bitmap.getHeight(), 
        CvType.CV_8UC1); 

      Utils.bitmapToMat(bitmap, mat); 

      int colorChannels = (mat.channels() == 3) ? Imgproc.COLOR_BGR2GRAY 
        : ((mat.channels() == 4) ? Imgproc.COLOR_BGRA2GRAY : 1); 

      Imgproc.cvtColor(mat, grayMat, colorChannels); 


      Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 2, 2); 

      // accumulator value 
      double dp = 1.2d; 
      // minimum distance between the center coordinates of detected circles in pixels 
      double minDist = 100; 


      int minRadius = 0, maxRadius = 0; 

      double param1 = 70, param2 = 72; 


      Mat circles = new Mat(bitmap.getWidth(), 
        bitmap.getHeight(), CvType.CV_8UC1); 


      Imgproc.HoughCircles(grayMat, circles, 
        Imgproc.CV_HOUGH_GRADIENT, dp, minDist, param1, 
        param2, minRadius, maxRadius); 


      int numberOfCircles = 9; 

      if (numberOfCircles > circles.cols()){ 
       numberOfCircles = circles.cols(); 
      } 


      for (int i=0; i<numberOfCircles; i++) { 



       double[] circleCoordinates = circles.get(0, i); 



       if(circleCoordinates == null){ 
       break; 
       } 



       int x = (int) circleCoordinates[0], y = (int) circleCoordinates[1]; 

       Point center = new Point(x, y); 
       android.graphics.Point centerC = new android.graphics.Point(x, y); 

       int radius = (int) circleCoordinates[2]; 



       Core.circle(mat, center, radius, new Scalar(0, 
         255, 0), 4); 


       Core.rectangle(mat, new Point(x - 5, y - 5), 
         new Point(x + 5, y + 5), 
         new Scalar(0, 128, 255), -1); 

Vielen Dank im Voraus.

Im Moment verwende ich diese A-förmigen Punkte, um den Code zu testen, aber ich möchte noch kleinere Kreise auf dem Foto erkennen. enter image description here

+0

Haben Sie verschiedene Sätze von Parametern für param1 und param2 ausprobiert? –

+0

Nein. Ich nicht. Wie sollte ich versuchen, sie zu ändern? Param 2 erhöhen? –

+0

Meine erste Schätzung wäre, Param2 zu verringern. Sie werden noch ein paar falsch positive Ergebnisse haben, aber ich nehme an, dass es einfacher ist, mit falschen positiven Ergebnissen umzugehen als mit falschen negativen. Zweitens versuchen Sie Param1 zu verringern. Dies erhöht die Empfindlichkeit des Canny-Kantendetektors, was bei der Suche nach Kreisen, die nicht scharf vom Hintergrund abheben, nützlich sein kann. –

Antwort

0

Ich denke, wenn Sie nur weiße Kreise erkennen möchten, müssen Sie die Farberkennung implementieren. Nicht nur wird es die Erkennungsqualität erheblich verbessern, sondern auch viele falsche Positive und Negative entfernen. Die Verwendung der Farberkennung ist ziemlich einfach, da sie bereits in OpenCV vorhanden ist. Verwenden Sie dazu Core.inRange Funktion. Sie können mehr darüber finden here. Aber wahrscheinlich das Beste für Sie wäre this Tutorial folgen. Es wurde in Python geschrieben, aber es ist verständlich und Sie müssen nur ein paar Zeilen ändern, damit es für Android funktioniert. Hoffe, das hilft :)

+0

Hey, danke für die ausführliche Antwort! Wenn Sie in Kommentare schauen, werden Sie sehen, dass ich die gleiche Lösung für die Frage gefunden habe. Seufz, wenn du nur wenige Tage zuvor geantwortet hast ... –

+0

Bedeutet das, dass ich keine Belohnung bekomme? T-T –

+0

Nein, ich denke du verdienst es immer noch. Danke noch einmal. –

0

Im Allgemeinen machen param1 und param2 kleiner wird die Schwelle zum Erkennen Kreise entspannen, so wird es mehr Fehlalarme [einen Kreis Erkennen, wo keine ist] und weniger falsch-negative Ergebnisse [nicht einen Kreis Erfassen, wo es ein].

Param2 legt den Schwellenwert für die Kreiserkennung fest. Wenn die Anzahl kleiner ist, werden mehr Kreise im Allgemeinen erkannt.

Param1 legt die Empfindlichkeitsschwelle für den Canny-Kantendetektor fest. Wenn die Anzahl kleiner ist, werden eher schwächere Kreise erkannt als mit einer größeren Zahl.

Wie bei allem in Computer Vision oder Machine Learning, wenn es nicht zuverlässig funktioniert und Sie nicht wissen warum, versuchen Sie einige Parameter zu ändern. :-D

Der Absturz, wenn weniger als neun Kreise vorhanden sind, ergibt sich aus der Festschreibung der Anzahl der Kreise auf neun. Wenn weniger als neun Kreise vorhanden sind, versucht das Programm, über die Grenzen des Mat-Arrays hinaus zuzugreifen.

Ich habe momentan kein System, um OpenCV zu testen, aber ich kann Code schreiben. Mein einziger Vorbehalt ist, dass Sie circles.rows anstelle von circles.cols benötigen könnten. Edit: auch, Kreise ist null, wenn es 0 Einträge hat.

int numberOfCircles = 9; 
if (circles == null) numberOfCircles = 0; 
else if (numberOfCircles > circles.cols) numberOfCircles = circles.cols; 

for (int i=0; i<numberOfCircles; i++) { 
    double[] circleCoordinates = circles.get(0, i); 
    ... 
+0

Dieser Code half. Teilweise. Jetzt stürzt die App nicht ab, wenn ich 1 bis x Kreise habe. Wenn die Zahl 0 ist - crash. –

+0

Was ist die Fehlermeldung? –

+0

Schauen Sie sich die Frage an –

0

Versuchen Sie es.

+0

Danke für die Antwort, aber ich denke, ich habe das - ich habe Farberkennung implementiert. –

+0

@OleksandrFirsov Also, was ist das Problem? –

+1

Ich habe es gelöst –