Szukaj…


Składnia

  • CascadeClassifier cascade = new CascadeClassifier („cascade.xml”); // Tworzy klasyfikator kaskadowy z cascade.xml
  • Mat image = Imgcodecs.imread ("image.png"); // Konwertuje image.png na obiekt Mat (Matrix)
  • Wykrywania MatOfRect = nowy MatOfRect (); // Tworzy pusty plik MatOfRect (Matrix of Rectangles), używany jako dane wyjściowe dla naszych klas wykrywania
  • detections.toArray (); // Zwraca tablicę obiektów Rect, które można iterować
  • Imgproc.prostokąt (obraz, nowy punkt (rect.x, rect.y), nowy punkt (rect.x + rect.width, rect.y + rect.height), nowy Scalar (0, 255, 0)); // Rysuje zielony obrysowany prostokąt z położenia xiy pierwszego punktu do położenia xiy drugiego punktu na „obrazie” obiektu Mat. „rect” to obiekt Rect, zwykle dostarczany przez detections.toArray (). Wykorzystuje klasę Point OpenCV.
  • Imgcodecs.imwrite ("output.png", obraz); // Zapisuje zmodyfikowany obiekt Mat „image” do „output.png”
  • CascadeClassifier.detectMultiScale (obraz, wykrycia); // Wykrywa dowolny obiekt w „obrazie” obiektu Mat i wysyła detekcje w „wykrywaniu” obiektu MatOfRect
  • CascadeClassifier.detectMultiScale (obraz, detekcje, scaleFactor , minNeighbors , flagi , minSize , maxSize ); // Przeprowadza wykrywanie z dodatkowymi parametrami. Szczegóły poniżej.
  • Imgproc.ellipse (obraz, środek, osie , 0, 0, 360, nowy Skalar (255, 0, 255), grubość , typ linii , 0); // Rysuje elipsę na obrazie w center punktu. Wykorzystuje klasę Point OpenCV.

Parametry

Parametr Detale
Współczynnik skali Jak duży rozmiar obrazu jest zmniejszany przy każdej skali obrazu. Domyślnie = 1.1
min Sąsiedzi Ilu sąsiadów powinien mieć prostokąt kandydujący przed wybraniem go jako wykrytego obiektu. Domyślnie = 4
flagi Starsze flagi. W większości przypadków należy ustawić na 0 . Domyślnie = 0
minSize Minimalny rozmiar kandydującego prostokąta może być. Wykorzystuje klasę Size OpenCV. Może być stosowany w celu skrócenia czasu wykrywania i zużycia procesora, a także w celu zmniejszenia fałszywych alarmów.
największy rozmiar Maksymalny rozmiar może być kandydatem na prostokąt. Wykorzystuje klasę Size OpenCV. Może być użyty do skrócenia czasu wykrywania i zużycia procesora, a także do zmniejszenia fałszywych alarmów.
osie Wykorzystuje klasę wielkości OpenCV. Określa szerokość i wysokość elipsy.
grubość Grubość linii w pikselach.
rodzaj linii Ma różne parametry. 0 oznacza linię ciągłą, 8 oznacza linię połączoną 8, 4 oznacza linię połączoną 4, a CV_AA oznacza linię CV_AA . Domyślnie = 8

Uzyskiwanie obrazu statycznego, wykrywanie na nim elementów i generowanie wyników.

Pamiętaj, że w tym przykładzie użyto 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);
    
    }
}

Rect[] zwrócone przez diceDetections.toArray() może być iterowane. Każdy Rect wewnątrz tablicy będzie miał cztery główne właściwości: x , y , width i height . x i y określa położenie górnego lewego prostokąta, a width i height Zwraca int na szerokość i wysokość prostokąta. Jest to używane podczas rysowania prostokątów na obrazach. Minimalne wymagane parametry funkcji Imgproc.rectangle są następujące:

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

Oba Point są używane do pozycji lewego górnego rogu i prawego dolnego rogu. Pozycje te są bezwzględne względem obrazu podanego jako pierwszy parametr, a nie względem siebie. Dlatego należy dodać zarówno pozycję x lub y prostokąta, jak y width lub height aby poprawnie zdefiniować punkt end .

Należy zauważyć, że klasa Point używana w tych parametrach nie jest klasą Point biblioteki standardowej biblioteki Java. Zamiast tego musisz zaimportować klasę Point OpenCV!

Wykrywanie obrazów z urządzenia wideo

Ten przykład przedstawia klasę VideoCapture , w której używamy jej do pobrania obrazu z kamery internetowej i zapisania go na obrazie.

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

Konwertowanie obiektu Mat na obiekt BufferedImage

Ten przykład Daniela Baggio został zaczerpnięty bezpośrednio z tej odpowiedzi StackExchange , ale został przebudowany dla widoczności.

Ta klasa pobiera obiekt Mat i zwraca obiekt BufferedImage używany przez biblioteki javax.swing . Może to zostać wykorzystane przez obiekt Graphics do narysowania obrazu.

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

Wykrywania w ramach Wykrywania

W tym przykładzie jako obiekt wykorzystujemy kości i czarne plamki na kościach (pipsy). Ponieważ przykład jest dość długi, najpierw wyjaśnienie niektórych kluczowych pojęć ma kluczowe znaczenie dla zrozumienia przykładu.

Zrozumienie pierwszego przykładu: „Pobieranie obrazu statycznego, wykrywanie na nim elementów i generowanie wyników”. ma kluczowe znaczenie dla zrozumienia tego przykładu, w szczególności tego, jak OpenCV rysuje prostokąty.

Spójrz na następujący obraz:

wprowadź opis zdjęcia tutaj

Będziemy używać metody obrazowania, w której wykorzystamy wykryty obszar jako bazę do zastosowania większej liczby detekcji. Jest to możliwe tylko wtedy, gdy obiekt zawsze znajdzie się w innym obiekcie, który możemy wykryć, takim jak nasze pestki na naszych kostkach. Ta metoda ma kilka zalet:

  • Zamiast skanować cały obraz, musimy tylko zeskanować obszar, w którym wiemy, że obiekt będzie.
  • Usuwa wszelkie szanse na fałszywe alarmy poza obszarem wykrywania.

Robimy to najpierw poprzez zastosowanie jednego kaskadowego skanu klasyfikatora na całym obrazie, aby dać nam obiekt MatOfRect zawierający nasze duże obiekty (w tym przypadku kostkę). Następnie toArray() tablicę Rect[] podaną przez funkcję toArray() z obiektu MatOfRect . Ten obiekt Rect jest używany do tworzenia tymczasowego obiektu Mat który jest „przycięty” do właściwości obiektu Rect ( x, y, width, height ) z oryginalnego obrazu, gdzie możemy następnie wykryć tymczasowy obiekt Mat . Innymi słowy, mówimy klasyfikatorowi, aby zamiast tego dokonywał detekcji tylko na częściach kostki obrazu, a my określamy pozycję każdej kości za pomocą obiektów Rect , które otrzymaliśmy z wykonania detekcji na całym obrazie.

Jednak obiekty Rect (pipsy) mają swoje właściwości w stosunku do swoich kości, a nie sam obraz. Aby rozwiązać ten problem, gdy chcemy narysować prostokąty na rzeczywistym obrazie pokazującym lokalizację pipsów, dodajemy zarówno dice.x jak i dice.y do Point początkowego.

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

Funkcja getNextImage() zwraca obiekt Mat , który w połączeniu z innymi opublikowanymi przykładami może być wywoływany stale i może być konwertowany na BufferImage , aby zapewnić wykrywanie na żywo.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow