opencv Détections dans les détections


Exemple

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.