Suche…


Syntax

  • CascadeClassifier cascade = neuer CascadeClassifier ("cascade.xml"); // Erstellt einen Kaskadenklassifizierer aus cascade.xml
  • Mat image = Imgcodecs.imread ("image.png"); // Konvertiert image.png in ein Mat (Matrix) -Objekt
  • MatOfRect-Erkennungen = new MatOfRect (); // Erstellt eine leere MatOfRect-Datei (Matrix of Rectangles), die als Ausgabe für unsere Erkennungsklassen verwendet wird
  • detections.toArray (); // Gibt ein Array von Rect-Objekten zurück, das wiederholt werden kann
  • Imgproc.rectangle (Bild, neuer Punkt (rect.x, rect.y), neuer Punkt (rect.x + rect.width, rect.y + rect.height), neuer Skalar (0, 255, 0)); // Zeichnet ein grün umrahmtes Rechteck von den x- und y-Positionen des ersten Punkts bis zum x- und y-Ort des zweiten Punkts auf das Mat-Objekt "image". "rect" ist ein Rect-Objekt, das normalerweise von detections.toArray () bereitgestellt wird. Verwendet die Point-Klasse von OpenCV.
  • Imgcodecs.imwrite ("output.png", Bild); // schreibt das modifizierte Mat-Objekt "image" in die "output.png"
  • CascadeClassifier.detectMultiScale (Bild, Erkennungen); // Erkennt ein beliebiges Objekt im Mat-Objekt "image" und gibt die Erkennungen im MatOfRect-Objekt "Erkennungen" aus
  • CascadeClassifier.detectMultiScale (Bild, Erkennungen, scaleFactor , minNeighbors , Flags , minSize , maxSize ); // Führt eine Erkennung mit zusätzlichen Parametern durch. Details siehe unten.
  • Imgproc.ellipse (Bild, Mittelpunkt, Achsen , 0, 0, 360, neuer Skalar (255, 0, 255), Dicke , Linientyp , 0); Zeichnet // eine Ellipse auf das Bild , an dem Punkt , center . Verwendet die Point-Klasse von OpenCV.

Parameter

Parameter Einzelheiten
Skalierungsfaktor Um wie viel die Bildgröße bei jedem Bildmaßstab reduziert wird. Voreinstellung = 1.1
MinNeighbors Wie viele Nachbarn sollte ein Kandidatenrechteck haben, bevor Sie es als erkanntes Objekt auswählen. Voreinstellung = 4
Flaggen Alte Flaggen In den meisten Fällen sollte dies auf 0 . Voreinstellung = 0
minSize Mindestgröße eines Kandidatenrechtecks. Hierbei wird die Size OpenCV verwendet. Kann verwendet werden, um die Erkennungszeit und die CPU-Auslastung zu verringern sowie Fehlalarme zu reduzieren.
maximale Größe Maximale Größe eines Kandidatenrechtecks. Hierbei wird die Size OpenCV verwendet. Kann verwendet werden, um die Erkennungszeit und die CPU-Auslastung zu verringern sowie Fehlalarme zu reduzieren.
Achsen Verwendet die Größenklasse von OpenCV. Definiert die Breite und Höhe der Ellipse.
Dicke Strichstärke in Pixeln.
lineType Hat verschiedene Parameter. 0 ist die durchgezogene Linie, 8 ist für eine Leitung mit 8 Verbindungen, 4 für eine Leitung mit 4 Verbindungen und CV_AA für eine CV_AA Leitung. Voreinstellung = 8

Ein statisches Bild erhalten, Elemente darin erkennen und die Ergebnisse ausgeben.

Bitte beachten Sie, dass dieses Beispiel OpenCV 3.1 verwendet.

import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;

public class Classifier {
    private CascadeClassifier diceCascade = new
        CascadeClassifier("res/newMethod/diceCascade.xml");
    private Mat image;
    private String loc = "path/to/image.png";
    private String output = "path/to/output.png";

    public void detImg() {
    
        Mat image = Imgcodecs.imread(loc); // Reads the image
    
        MatOfRect diceDetections = new MatOfRect(); // Output container
        diceCascade.detectMultiScale(image, diceDetections); // Performs the detection
    
        // Draw a bounding box around each detection.
        for (Rect rect : diceDetections.toArray()) {
            Imgproc.rectangle(image, new Point(rect.x, rect.y),
                new Point(rect.x + rect.width, rect.y + rect.height),
                new Scalar(0, 255, 0));
        }
    
        // Save the visualized detection.
        Imgcodecs.imwrite(output, image);
    
    }
}

Das von diceDetections.toArray() zurückgegebene diceDetections.toArray() Rect[] kann wiederholt werden. Jedes Rect im Array hat vier Haupteigenschaften: x , y , width und height . x und y definieren die linke obere Position des Rechtecks. width und height ein int der Breite und Höhe des Rechtecks ​​zurück. Dies wird verwendet, wenn Rechtecke auf Bilder gezeichnet werden. Die minimal erforderlichen Parameter der Funktion Imgproc.rectangle lauten wie folgt:

Imgproc.rectangle(Mat image, Point start, Point end, Scalar color);

Beide Point werden für die Positionen der oberen linken Ecke und der rechten unteren Ecke verwendet. Diese Positionen sind für das als ersten Parameter bereitgestellte Bild absolut und nicht für einander. Daher müssen Sie sowohl die x als auch die y Position des Rechtecks ​​zusätzlich zur width oder height hinzufügen, um den end richtig zu definieren.

Beachten Sie, dass die in diesen Parametern verwendete Point Klasse nicht die Point Klasse der Standardbibliothek von Java ist. Sie müssen stattdessen die Point Klasse von OpenCV importieren!

Bilder von einem Videogerät erkennen

In diesem Beispiel wird die VideoCapture Klasse vorgestellt, in der wir ein Bild von einer Webcam aufnehmen und in einem Bild speichern.

import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;

public class Classifier {
    private CascadeClassifier diceCascade = new
        CascadeClassifier("res/newMethod/diceCascade.xml");
    private Mat image;
    private String loc = "path/to/image.png";
    private String output = "path/to/output.png";
    private VideoCapture vc = new VideoCapture();

    public void detImg() {
        vc.open(0); // Opens the video stream

        Mat image = new Mat(); // Creates an empty matrix
        vc.read(image); // Reads the image from the video stream and
            writes it to the image matrix.
    
        MatOfRect diceDetections = new MatOfRect(); // Output container
        diceCascade.detectMultiScale(image, diceDetections); // Performs the detection
    
        // Draw a bounding box around each detection.
        for (Rect rect : diceDetections.toArray()) {
            Imgproc.rectangle(image, new Point(rect.x, rect.y),
                new Point(rect.x + rect.width, rect.y + rect.height),
                new Scalar(0, 255, 0));
        }
    
        // Save the visualized detection.
        Imgcodecs.imwrite(output, image);

        vc.release(); // Closes the stream.
    
    }
}

Konvertieren eines Mat-Objekts in ein BufferedImage-Objekt

Dieses Beispiel von Daniel Baggio stammt direkt aus dieser StackExchange-Antwort , wurde jedoch aus Gründen der Übersichtlichkeit erneut veröffentlicht.

Diese Klasse nimmt ein Mat-Objekt und gibt das BufferedImage-Objekt zurück, das von den Bibliotheken javax.swing verwendet wird. Dies kann von einem Graphics Objekt zum Zeichnen des Bildes verwendet werden.

private BufferedImage toBufferedImage(Mat m) {
    if (!m.empty()) {
        int type = BufferedImage.TYPE_BYTE_GRAY;
        if (m.channels() > 1) {
            type = BufferedImage.TYPE_3BYTE_BGR;
        }
        int bufferSize = m.channels() * m.cols() * m.rows();
        byte[] b = new byte[bufferSize];
        m.get(0, 0, b); // get all the pixels
        BufferedImage image = new BufferedImage(m.cols(), m.rows(), type);
        final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        System.arraycopy(b, 0, targetPixels, 0, b.length);
        return image;
    }
    
    return null;
}

Erkennungen in Erkennungen

In diesem Beispiel werden Würfel und die schwarzen Punkte auf den Würfeln (den Pips) als Objekt verwendet. Da das Beispiel ziemlich lang ist, ist es zunächst wichtig, einige Schlüsselbegriffe zu erklären, um das Beispiel zu verstehen.

Grundlegendes zum ersten Beispiel: "Ein statisches Bild abrufen, Elemente darin erkennen und die Ergebnisse ausgeben." Für das Verständnis dieses Beispiels ist es besonders wichtig, wie OpenCV Rechtecke zeichnet.

Schauen Sie sich das folgende Bild an:

Geben Sie hier die Bildbeschreibung ein

Wir werden die Subimaging-Methode verwenden, bei der wir einen erkannten Bereich als Basis für weitere Erkennungen verwenden. Dies ist nur möglich, wenn sich ein Objekt immer in einem anderen Objekt befindet, das wir erkennen können, z. B. mit unseren Würfeln. Diese Methode hat mehrere Vorteile:

  • Anstatt das gesamte Bild zu scannen, müssen wir nur den Bereich scannen, in dem sich das Objekt befindet.
  • Entfernt die Möglichkeit von Fehlalarmen außerhalb des Erkennungsbereichs.

Wir machen dies, indem wir zuerst einen Kaskadenklassifizierer-Scan über das gesamte Bild anwenden, um ein MatOfRect Objekt zu erhalten, das unsere großen Objekte (in diesem Fall Dice) enthält. Wir iterieren dann über das Rect[] Array, das von der toArray() Funktion aus dem MatOfRect Objekt MatOfRect wird. Dieses Rect Objekt wird beim Erstellen eines temporären Mat Objekts verwendet, das vom Originalbild auf die Eigenschaften des Rect Objekts ( x, y, width, height ) "abgeschnitten" wird. Dort können wir dann das temporäre Mat Objekt erkennen. Mit anderen Worten, wir weisen den Klassifizierer an, stattdessen nur Erfassungen an den Würfelteilen des Bildes durchzuführen, und wir geben die Position jedes Würfels an, indem wir die Rect Objekte verwenden, die wir bei der Durchführung einer Erkennung für das gesamte Bild erhalten haben.

Die Rect Objekte (Pips) haben jedoch ihre Eigenschaften im Verhältnis zu ihren Würfeln und nicht zum Bild selbst. Um dieses Problem zu lösen, wenn wir zum eigentlichen Bild zeichnen Rechtecken wollen die Kerne der Standorte zeigen, fügen wir beide dice.x und dice.y zum Point .

import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;

public class Classifier {

    private CascadeClassifier diceCascade =
        new CascadeClassifier("res/newMethod/diceCascade.xml");
    private CascadeClassifier pipCascade =
        new CascadeClassifier("res/newMethod/pipCascade6.xml");
    private VideoCapture vc = new VideoCapture();
    private Mat image;

    public void openVC(int index) {
        vc.open(index);
    }

    public void closeVC() {
        vc.close();
    }

    public Mat getNextImage() {
        image = new Mat();
        vc.read(image); // Sets the matrix to the current livestream frame.
        
        MatOfRect diceDetections = new MatOfRect(); // Output container
    
        // See syntax for explainations on addition parameters
        diceCascade.detectMultiScale(image, diceDetections, 1.1, 4, 0, new Size(20, 20),
            new Size(38, 38));
        
        // Iterates for every Dice ROI
        for (int i = 0; i < diceDetections.toArray().length; i++) {
            Rect diceRect = diceDetections.toArray()[i];
            
            // Draws rectangles around our detected ROI
            Point startingPoint = new Point(diceRect.x, diceRect.y);
            Point endingPoint = new Point(diceRect.x + diceRect.width,
                diceRect.y + diceRect.height);
            Imgproc.rectangle(image, startingPoint, endingPoint, new Scalar(255, 255, 0));
            
            MatOfRect pipDetections = new MatOfRect();
            
            pipCascade.detectMultiScale(image.submat(diceRect), pipDetections, 1.01, 4, 0,
                new Size(2, 2), new Size(10, 10));
            
            // Gets the number of detected pips and draws a cricle around the ROI
            for (int y = 0; y < pipDetections.toArray().length; y++) {
                // Provides the relative position of the pips to the dice ROI
                Rect pipRect = pipDetections.toArray()[y];
                
                // See syntax explaination
                // Draws a circle around our pips
                Point center = new Point(diceRect.x + pipRect.x + pipRect.width / 2,
                    diceRect.y + pipRect.y + pipRect.height / 2);
                Imgproc.ellipse(image, center, new Size(pipRect.width / 2, pipRect.height / 2),
                     0, 0, 360, new Scalar(255, 0, 255), 1, 0, 0);
            }
        }
        
        return image;
    }
}

Die Funktion getNextImage() gibt ein Mat Objekt zurück, das zusammen mit den anderen veröffentlichten Beispielen ständig aufgerufen und in ein BufferImage konvertiert werden BufferImage , um einen Livestream anzuzeigen, der Erkennungen anzeigt.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow