Buscar..


Sintaxis

  • CascadeClassifier cascade = new CascadeClassifier ("cascade.xml"); // Crea un clasificador en cascada desde cascade.xml
  • Mat image = Imgcodecs.imread ("image.png"); // Convierte image.png en un objeto Mat (Matrix)
  • Detecciones de MatOfRect = nuevo MatOfRect (); // Crea un archivo vacío MatOfRect (Matriz de rectángulos), utilizado como salida para nuestras clases de detección
  • detections.toArray (); // Devuelve una matriz de objetos Rect que se pueden iterar sobre
  • Imgproc.rectangle (imagen, nuevo punto (rect.x, rect.y), nuevo punto (rect.x + rect.width, rect.y + rect.height), nuevo escalar (0, 255, 0)); // Dibuja un rectángulo con contorno verde desde las ubicaciones x e y del primer punto hasta las ubicaciones x e y del segundo punto en la "imagen" del objeto Mat. "rect" es un objeto Rect, generalmente proporcionado por detections.toArray (). Utiliza la clase de puntos de OpenCV.
  • Imgcodecs.imwrite ("output.png", imagen); // Escribe el objeto Mat modificado "imagen" en la "salida.png"
  • CascadeClassifier.detectMultiScale (imagen, detecciones); // Detecta cualquier objeto en la "imagen" del objeto Mat y genera las detecciones en el objeto "detecciones" MatOfRect
  • CascadeClassifier.detectMultiScale (imagen, detecciones, scaleFactor , minNeighbors , flags , minSize , maxSize ); // Realiza una detección con parámetros adicionales. Vea los detalles abajo.
  • Imgproc.ellipse (imagen, centro, ejes, 0, 0, 360, nuevo Scalar (255, 0, 255), espesor, tipo de línea, 0); // Dibuja una elipse en la imagen en el center punto. Utiliza la clase de puntos de OpenCV.

Parámetros

Parámetro Detalles
factor de escala Cuánto se reduce el tamaño de la imagen en cada escala de imagen. Predeterminado = 1.1
minNeighbors Cuántos vecinos debe tener un rectángulo candidato antes de seleccionarlo como un objeto detectado. Predeterminado = 4
banderas Banderas heredadas. En la mayoría de los casos, esto se debe establecer en 0 . Predeterminado = 0
tamaño minimo Tamaño mínimo que un rectángulo candidato puede ser. Esto utiliza la clase de Size de OpenCV. Puede usarse para disminuir el tiempo de detección y el uso de la CPU, así como para reducir los falsos positivos.
tamaño máximo Tamaño máximo que puede ser un rectángulo candidato. Esto utiliza la clase de Size de OpenCV. Puede usarse para disminuir el tiempo de detección y el uso de la CPU, así como para reducir los falsos positivos.
hachas Utiliza la clase de tamaño de OpenCV. Define el ancho y la altura de la elipse.
espesor Grosor de la línea, en píxeles.
tipo de línea Tiene varios parámetros. 0 es la línea continua, 8 es para una línea conectada a 8, 4 es para una línea conectada a 4 y CV_AA es para una línea suavizada. Predeterminado = 8

Obtención de una imagen estática, detección de elementos en ella y salida de los resultados.

Tenga en cuenta que este ejemplo utiliza 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);
    
    }
}

El Rect[] devuelto por diceDetections.toArray() puede diceDetections.toArray() . Cada Rect dentro de la matriz tendrá cuatro propiedades principales: x , y , width y height . x e y definen la posición superior izquierda del rectángulo, y el width y la height devuelven un int del ancho y la altura del rectángulo. Esto se utiliza al dibujar rectángulos en imágenes. Los Imgproc.rectangle mínimos requeridos de la función Imgproc.rectangle son los siguientes:

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

Ambos Point se utilizan para las posiciones de la esquina superior izquierda y la esquina inferior derecha. Estas posiciones son ambas absolutas para la imagen proporcionada como primer parámetro, no entre sí. Por lo tanto, debe agregar la posición x o y del rectángulo además del width o la height para definir correctamente el punto end .

Tenga en cuenta que la clase Point utilizada en estos parámetros no es la clase Point la biblioteca estándar de Java. ¡Debes importar la clase Point de OpenCV en su lugar!

Detectar imágenes desde un dispositivo de video

Este ejemplo introduce la clase VideoCapture , donde la usamos para tomar una imagen de una cámara web y guardarla en una imagen.

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

Convertir un objeto Mat en un objeto BufferedImage

Este ejemplo de Daniel Baggio se tomó directamente de esta respuesta de StackExchange , pero se ha vuelto a publicar para visibilidad.

Esta clase toma un objeto Mat y devuelve el objeto BufferedImage utilizado por las bibliotecas javax.swing . Esto puede ser utilizado por un objeto Graphics para dibujar la imagen.

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

Detecciones en Detecciones

Este ejemplo utiliza los dados y los puntos negros en los dados (los puntos) como nuestro objeto. Como el ejemplo es bastante largo, primero es esencial explicar algunos conceptos clave para entender el ejemplo.

Comprensión del primer ejemplo, "Obtención de una imagen estática, detección de elementos en ella y salida de los resultados". Es fundamental para entender este ejemplo, especialmente cómo OpenCV dibuja rectángulos.

Echa un vistazo a la siguiente imagen:

introduzca la descripción de la imagen aquí

Usaremos el método de subimagen, donde usamos un área detectada como nuestra base para aplicar más detecciones. Esto solo es posible si un objeto siempre estará dentro de otro objeto que podamos detectar, como nuestros pips en nuestros dados. Este método tiene varios beneficios:

  • En lugar de escanear toda la imagen, solo necesitamos escanear el área donde sabemos que estará el objeto.
  • Elimina cualquier posibilidad de falsos positivos fuera del área de detección.

Hacemos esto aplicando primero un escaneo clasificador en cascada sobre la imagen completa para darnos un objeto MatOfRect que contiene nuestros objetos grandes (dados, en este caso). Luego Rect[] sobre la matriz Rect[] dada por la función toArray() del objeto MatOfRect . Este objeto Rect se usa para crear un objeto Mat temporal que se "recorta" a las Rect objeto Rect ( x, y, width, height ) de la imagen original, donde luego podemos realizar detecciones en el objeto Mat temporal. En otras palabras, le decimos al clasificador que solo realice detecciones en las partes de la imagen de los dados, y especificamos la posición de cada dado usando los objetos Rect que obtuvimos al realizar una detección en toda la imagen.

Sin embargo, los objetos Rect (pips) tienen sus propiedades en relación con sus dados, y no la imagen en sí. Para resolver este problema, cuando deseamos dibujar rectángulos en la imagen real que muestra las ubicaciones de los pips, agregamos dice.x y dice.y al Point inicio.

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 función getNextImage() devuelve un objeto Mat , que junto con los otros ejemplos publicados, se puede llamar constantemente y se puede convertir en un BufferImage , para proporcionar detecciones de visualización en vivo.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow