Recherche…


Syntaxe

  • CascadeClassifier cascade = new CascadeClassifier ("cascade.xml"); // Crée un classificateur en cascade à partir de cascade.xml
  • Mat image = Imgcodecs.imread ("image.png"); // Convertit image.png en un objet Mat (Matrix)
  • Détections MatOfRect = new MatOfRect (); // Crée un fichier MatOfRect (Matrix of Rectangles) vide, utilisé comme sortie pour nos classes de détection
  • detections.toArray (); // Retourne un tableau d'objets Rect pouvant être itéré sur
  • Imgproc.rectangle (image, nouveau point (rect.x, rect.y), nouveau point (rect.x + rect.width, rect.y + rect.height), nouveau scalaire (0, 255, 0)); // Dessine un rectangle à contour vert depuis les emplacements x et y du premier point vers l'emplacement x et y du second point sur l'objet Mat "image". "rect" est un objet Rect, généralement fourni par detections.toArray (). Utilise la classe de points OpenCV.
  • Imgcodecs.imwrite ("output.png", image); // Ecrit l'objet Mat modifié "image" dans le fichier "output.png"
  • CascadeClassifier.detectMultiScale (image, détections); // Détecte tout objet dans l'objet Mat "image" et affiche les détections dans l'objet MatOfRect "détections"
  • CascadeClassifier.detectMultiScale (image, détections, scaleFactor , minNeighbors , flags , minSize , maxSize ); // Effectue une détection avec des paramètres supplémentaires. Voir les détails ci-dessous.
  • Imgproc.ellipse (image, centre, axes , 0, 0, 360, nouveau Scalar (255, 0, 255), épaisseur , lineType , 0); // Dessine une ellipse sur l'image au center du point. Utilise la classe de points OpenCV.

Paramètres

Paramètre Détails
facteur d'échelle Combien la taille de l'image est réduite à chaque échelle d'image. Par défaut = 1.1
minNeighbors Combien de voisins un rectangle candidat doit avoir avant de le sélectionner comme objet détecté. Par défaut = 4
drapeaux Drapeaux hérités Dans la plupart des cas, cela devrait être mis à 0 . Par défaut = 0
minSize La taille minimale d'un rectangle candidat peut être. Cela utilise la classe de Size OpenCV. Peut être utilisé pour réduire le temps de détection et l'utilisation du processeur, ainsi que pour réduire les faux positifs.
taille max Taille maximale que peut contenir un rectangle candidat. Cela utilise la classe de Size OpenCV. Peut être utilisé pour réduire le temps de détection et l'utilisation du processeur, ainsi que pour réduire les faux positifs.
les axes Utilise la classe de taille OpenCV. Définit la largeur et la hauteur de l'ellipse.
épaisseur Épaisseur de la ligne, en pixels.
type de ligne A divers paramètres. 0 correspond à la ligne CV_AA , 8 ligne à 8 connexions, 4 ligne à 4 connexions et CV_AA à la ligne antialiasée. Par défaut = 8

Obtenir une image statique, détecter les éléments et afficher les résultats.

Veuillez noter que cet exemple utilise 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);
    
    }
}

Le Rect[] renvoyé par diceDetections.toArray() peut être itéré sur. Chaque Rect à l'intérieur du tableau aura quatre propriétés principales: x , y , width et height . x et y définissent la position supérieure gauche du rectangle et width et height renvoie un int de la largeur et de la hauteur du rectangle. Ceci est utilisé pour dessiner des rectangles sur des images. Les paramètres requis minimaux de la fonction Imgproc.rectangle sont les suivants:

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

Les deux Point sont utilisés pour les positions du coin supérieur gauche et du coin inférieur droit. Ces positions sont à la fois absolues sur l'image fournie comme premier paramètre et non sur l'autre. Vous devez donc ajouter la position x ou y du rectangle en plus de la width ou de la height pour définir correctement le point de end .

Notez que la classe Point utilisée dans ces paramètres n'est pas la classe Point la bibliothèque standard de Java. Vous devez importer la classe de Point OpenCV à la place!

Détection d'images à partir d'un périphérique vidéo

Cet exemple présente la classe VideoCapture , où nous l'utilisons pour prendre une image à partir d'une webcam et l'enregistrer sur une image.

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

Conversion d'un objet Mat en objet BufferedImage

Cet exemple de Daniel Baggio a été tiré directement de cette réponse StackExchange , mais a été republié pour la visibilité.

Cette classe prend un objet Mat et renvoie l'objet BufferedImage utilisé par les bibliothèques javax.swing . Cela peut être utilisé par un objet Graphics pour dessiner l'image.

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

Détections dans les détections

Cet exemple utilise Dice et les points noirs sur les dés (les pips) comme objet. Comme l'exemple est assez long, expliquer d'abord certains concepts clés est essentiel pour comprendre l'exemple.

Comprendre le premier exemple, "Obtention d’une image statique, détection des éléments et sortie des résultats". est essentiel pour comprendre cet exemple, en particulier comment OpenCV dessine des rectangles.

Regardez l'image suivante:

entrer la description de l'image ici

Nous utiliserons la méthode de sous-application, où nous utiliserons une zone détectée comme base pour appliquer davantage de détections. Ceci n'est possible que si un objet se trouve toujours dans un autre objet que nous pouvons détecter, comme nos pips sur nos dés. Cette méthode présente plusieurs avantages:

  • Au lieu de scanner l'image entière, il suffit de scanner la zone dans laquelle nous savons que l'objet se trouvera.
  • Supprime toute possibilité de faux positifs en dehors de la zone de détection.

Nous faisons cela en appliquant d'abord un balayage classificateur en cascade sur l'image entière pour nous donner un objet MatOfRect contenant nos grands objets (dés, dans ce cas). Nous parcourons ensuite le tableau Rect[] donné par la fonction toArray() de l'objet MatOfRect . Cet objet Rect est utilisé pour créer un objet Mat temporaire qui est "recadré" aux propriétés de l'objet Rect ( x, y, width, height ) à partir de l'image d'origine, où nous pouvons alors effectuer des détections sur l'objet Mat temporaire. En d'autres termes, nous demandons au classificateur de ne faire que des détections sur les parties de dés de l'image, et nous spécifions la position de chaque dé en utilisant les objets Rect obtenus en effectuant une détection sur l'image entière.

Cependant, les objets Rect (pips) ont leurs propriétés par rapport à leurs dés, et non à l'image elle-même. Pour résoudre ce problème, lorsque nous voulons dessiner des rectangles à l'image réelle montrant l'emplacement des pépins, nous ajoutons à la fois dice.x et dice.y au Point départ.

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 fonction getNextImage() renvoie un objet Mat , qui, associé aux autres exemples publiés, peut être appelé en permanence et peut être converti en BufferImage pour fournir un flux de diffusion affichant les détections.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow