Ricerca…


Sintassi

  • CascadeClassifier cascade = new CascadeClassifier ("cascade.xml"); // Crea un classificatore a cascata da cascade.xml
  • Immagine mat = Imgcodecs.imread ("image.png"); // Converte image.png in un oggetto Mat (Matrix)
  • MatOfRect rilevamenti = nuovo MatOfRect (); // Crea un file MatOfRect (Matrix of Rectangles) vuoto, utilizzato come output per le nostre classi di rilevamento
  • detections.toArray (); // Restituisce una matrice di oggetti Rect che possono essere ripetuti
  • Imgproc.rectangle (immagine, nuovo punto (rect.x, rect.y), nuovo punto (rect.x + rect.width, rect.y + rect.height), nuovo scalare (0, 255, 0)); // Disegna un rettangolo con contorno verde dalle posizioni xey del primo punto alla posizione xey del secondo punto su "immagine" dell'oggetto Mat. "rect" è un oggetto Rect, solitamente fornito da detectings.toArray (). Utilizza la classe Point di OpenCV.
  • Imgcodecs.imwrite ("output.png", image); // Scrive l'oggetto Mat modificato "image" in "output.png"
  • CascadeClassifier.detectMultiScale (immagine, rilevamenti); // Rileva qualsiasi oggetto nell'oggetto Mat "image" e restituisce i rilevamenti nell'oggetto MatOfRect "rilevamenti"
  • CascadeClassifier.detectMultiScale (immagine, rilevazioni, scaleFactor, minNeighbors, bandiere, minSize, maxSize); // Esegue un rilevamento con parametri aggiuntivi. Vedi i dettagli di seguito.
  • Imgproc.ellipse (immagine, centro, assi , 0, 0, 360, nuovo scalare (255, 0, 255), spessore , lineType , 0); // Disegna un'ellisse sull'immagine al center del punto. Utilizza la classe Point di OpenCV.

Parametri

Parametro Dettagli
fattore di scala Quanto è ridotta la dimensione dell'immagine a ciascuna scala dell'immagine. Impostazione predefinita = 1.1
minNeighbors Quanti vicini deve avere un rettangolo candidato prima di selezionarlo come oggetto rilevato. Impostazione predefinita = 4
bandiere Bandiere legacy. Nella maggior parte dei casi, dovrebbe essere impostato su 0 . Impostazione predefinita = 0
minSize Dimensione minima che può essere un rettangolo candidato. Questo usa la classe Size di OpenCV. Può essere utilizzato per ridurre il tempo di rilevamento e l'utilizzo della CPU, nonché per ridurre i falsi positivi.
maxSize Dimensione massima che può essere un rettangolo candidato. Questo usa la classe Size di OpenCV. Può essere utilizzato per ridurre il tempo di rilevamento e l'utilizzo della CPU, nonché per ridurre i falsi positivi.
assi Usa la classe Size di OpenCV. Definisce la larghezza e l'altezza dell'ellisse.
spessore Spessore della linea, in pixel.
modello di linea Ha vari parametri 0 è la linea continua, 8 è per una linea a 8, 4 è per una linea a 4 e CV_AA è per una linea antialias. Impostazione predefinita = 8

Ottenere un'immagine statica, rilevare elementi su di esso e produrre risultati.

Si prega di notare che questo esempio utilizza OpenCV 3.1.

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

Il Rect[] restituito da diceDetections.toArray() può essere ripetuto. Ogni Rect all'interno dell'array avrà quattro proprietà principali: x , y , width e height . x ed y definisce la posizione in alto a sinistra del rettangolo, e width e height restituisce un int della larghezza e l'altezza del rettangolo. Questo è usato quando si disegnano rettangoli sulle immagini. I Imgproc.rectangle minimi richiesti Imgproc.rectangle funzione Imgproc.rectangle sono i seguenti:

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

Entrambi i Point vengono utilizzati per le posizioni dell'angolo superiore sinistro e dell'angolo inferiore destro. Queste posizioni sono sia assolute all'immagine fornita come primo parametro, che non l'una all'altra. Pertanto, è necessario aggiungere la posizione x o y del rettangolo oltre alla width o height per definire correttamente il Punto end .

Si noti che la classe Point utilizzata in questi parametri non è la classe Point della libreria standard di Java. Devi invece importare la classe Point di OpenCV!

Rilevazione di immagini da un dispositivo video

Questo esempio introduce la classe VideoCapture , in cui viene utilizzata per scattare un'immagine da una webcam e salvarla su un'immagine.

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

Convertire un oggetto Mat in un oggetto BufferedImage

Questo esempio di Daniel Baggio è stato preso direttamente da questa risposta StackExchange , ma è stato ripubblicato per visibilità.

Questa classe accetta un oggetto Mat e restituisce l'oggetto BufferedImage utilizzato dalle librerie javax.swing . Questo può essere usato da un oggetto Graphics per disegnare l'immagine.

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

Rilevamenti all'interno dei rilevamenti

Questo esempio usa i dadi e le macchie nere sui dadi (i semi) come oggetto. Dato che l'esempio è piuttosto lungo, la prima spiegazione di alcuni concetti chiave è fondamentale per comprendere l'esempio.

Capire il primo esempio, "Ottenere un'immagine statica, rilevare elementi su di esso e produrre i risultati." è fondamentale per comprendere questo esempio, in particolare come OpenCV disegna rettangoli.

Dai un'occhiata alla seguente immagine:

inserisci la descrizione dell'immagine qui

Useremo il metodo di sottomissione, in cui utilizziamo un'area rilevata come base per l'applicazione di ulteriori rilevazioni. Questo è possibile solo se un oggetto sarà sempre all'interno di un altro oggetto che possiamo rilevare, come i nostri semi sui nostri dadi. Questo metodo ha diversi vantaggi:

  • Invece di scansionare l'intera immagine, abbiamo solo bisogno di scansionare l'area in cui sappiamo che l'oggetto sarà dentro.
  • Rimuove qualsiasi possibilità di falsi positivi al di fuori dell'area di rilevamento.

Facciamo questo applicando prima una scansione di classificatore a cascata sull'intera immagine per darci un oggetto MatOfRect contenente i nostri oggetti di grandi dimensioni (dadi, in questo caso). Quindi toArray() l' toArray() sull'array Rect[] fornito dalla funzione toArray() dall'oggetto MatOfRect . Questo oggetto Rect viene utilizzato nella creazione di un oggetto Mat temporaneo che viene "ritagliato" alle proprietà dell'oggetto Rect ( x, y, width, height ) dall'immagine originale, dove possiamo quindi eseguire rilevazioni sull'oggetto Mat temporaneo. In altre parole, diciamo al classificatore di eseguire solo rilevamenti sulle parti di dadi dell'immagine, invece, e specifichiamo la posizione di ogni dado usando gli oggetti Rect che abbiamo ottenuto eseguendo un rilevamento sull'intera immagine.

Tuttavia, gli oggetti Rect (pips) hanno le loro proprietà relative ai loro dadi, e non l'immagine stessa. Per risolvere questo problema, quando vogliamo disegnare rettangoli sull'immagine reale che mostra le posizioni dei semi, aggiungiamo sia i dice.x che i dice.y al Point iniziale.

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

La funzione getNextImage() restituisce un oggetto Mat , che con gli altri esempi pubblicati può essere chiamato costantemente e può essere convertito in un BufferImage , per fornire un livestream che visualizza i rilevamenti.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow