Поиск…


Синтаксис

  • CascadeClassifier cascade = новый CascadeClassifier ("cascade.xml"); // Создает каскадный классификатор из cascade.xml
  • Mat image = Imgcodecs.imread ("image.png"); // Преобразует image.png в объект Mat (Matrix)
  • Определение MatOfRect = новый MatOfRect (); // Создает пустой файл MatOfRect (Matrix of Rectangles), используемый в качестве вывода для наших классов обнаружения
  • detections.toArray (); // Возвращает массив объектов Rect, которые могут быть повторены
  • Imgproc.rectangle (изображение, новая точка (rect.x, rect.y), новая точка (rect.x + rect.width, rect.y + rect.height), новый Scalar (0, 255, 0)); // Рисует зеленый очерченный прямоугольник из местоположений x и y первой точки в положение x и y второй точки на объект «Изображение» объекта Mat. «rect» - это объект Rect, обычно предоставляемый функциями detections.toArray (). Использует класс Point OpenCV.
  • Imgcodecs.imwrite ("output.png", изображение); // Записывает измененный объект «объект изображения» Mat в «output.png»
  • CascadeClassifier.detectMultiScale (изображение, обнаружение); // Обнаруживает любой объект в объекте «изображение» объекта Mat и выводит обнаруженные в объекте MatOfRect «обнаружения»,
  • CascadeClassifier.detectMultiScale (изображение, обнаружение, scaleFactor , minNeighbors , flags , minSize , maxSize ); // Выполняет обнаружение с дополнительными параметрами. См. Подробности ниже.
  • Imgproc.ellipse (изображение, центр, оси , 0, 0, 360, новый Scalar (255, 0, 255), толщина , lineType , 0); // Рисуем эллипс на изображении в center точки. Использует класс Point OpenCV.

параметры

параметр подробности
масштаб Насколько размер изображения уменьшается при каждой шкале изображения. По умолчанию = 1.1
minNeighbors Сколько соседей должен иметь прямоугольник-кандидат, прежде чем выбирать его как обнаруженный объект. По умолчанию = 4
флаги Устаревшие флаги. В большинстве случаев это должно быть установлено равным 0 . По умолчанию = 0
MinSize Минимальным размером может быть прямоугольник кандидата. Это использует класс Size OpenCV. Может использоваться для уменьшения времени обнаружения и использования ЦП, а также для уменьшения ложных срабатываний.
MaxSize Максимальный размер прямоугольника-кандидата. Это использует класс Size OpenCV. Может использоваться для уменьшения времени обнаружения и использования ЦП, а также для уменьшения ложных срабатываний.
оси Использует класс размера OpenCV. Определяет ширину и высоту эллипса.
толщина Толщина линии, в пикселях.
LineType Имеет различные параметры. 0 - сплошная линия, 8 - для 8-связной линии, 4 - для 4-связной линии, а CV_AA - для CV_AA линии. По умолчанию = 8

Получение статического изображения, определение элементов на нем и вывод результатов.

Обратите внимание, что в этом примере используется 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[] возвращаемый diceDetections.toArray() может быть повторен. Каждый Rect внутри массива будет иметь четыре основных свойства: x , y , width и height . x и y определяет верхнее левое положение прямоугольника, а width и height возвращают int ширины и высоты прямоугольника. Это используется при рисовании прямоугольников на изображениях. Минимальные требуемые параметры функции Imgproc.rectangle следующие:

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

Обе Point используются для позиций верхнего левого угла и нижнего правого угла. Эти позиции являются абсолютными по отношению к изображению, представленному в качестве первого параметра, а не друг к другу. Таким образом, вы должны добавить как x и y позицию прямоугольника в дополнение к width или height чтобы правильно определить end точку.

Обратите внимание, что класс Point используемый в этих параметрах, не является классом Point стандартной библиотеки Java. Вы должны импортировать класс Point OpenCV вместо этого!

Обнаружение изображений с видеоустройства

В этом примере представлен класс VideoCapture , где мы используем его для получения изображения с веб-камеры и сохранения его на изображении.

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

Преобразование объекта Mat в объект BufferedImage

Этот пример Дэниела Баджо был взят непосредственно из этого ответа StackExchange , но был пересмотрен для видимости.

Этот класс принимает объект Mat и возвращает объект BufferedImage, используемый библиотеками javax.swing . Это может использоваться объектом Graphics для рисования изображения.

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

Обнаружения в пределах детектирования

Этот пример использует Dice и черные пятна на кости (пипсы) в качестве нашего объекта. Поскольку пример довольно длинный, сначала объяснение некоторых ключевых понятий имеет решающее значение для понимания примера.

Понимание первого примера: «Получение статического изображения, определение элементов на нем и вывод результатов». имеет решающее значение для понимания этого примера, особенно в том, как OpenCV рисует прямоугольники.

Взгляните на следующее изображение:

введите описание изображения здесь

Мы будем использовать метод субимации, где мы используем обнаруженную область в качестве нашей базы для применения большего количества обнаружений. Это возможно только в том случае, если объект всегда будет находиться внутри другого объекта, который мы можем обнаружить, например, наши пипсы на наших игральных костях. Этот метод имеет несколько преимуществ:

  • Вместо сканирования всего изображения нам нужно только сканировать область, в которой мы знаем, что объект будет находиться.
  • Удаляет любую вероятность ложных срабатываний вне зоны обнаружения.

Мы делаем это, сначала применяя одно сканирование каскадного классификатора по всему изображению, чтобы дать нам объект MatOfRect содержащий наши большие объекты (в данном случае кости). Затем мы перебираем массив Rect[] заданный функцией toArray() из объекта MatOfRect . Этот объект Rect используется для создания временного объекта Mat который «обрезается» для свойств объекта Rect ( x, y, width, height ) из исходного изображения, где мы можем затем выполнять обнаружение на временном объекте Mat . Другими словами, мы говорим, что классификатор только выполняет обнаружение на частях кости изображения, и мы указываем положение каждой кости, используя объекты Rect которые мы получили от выполнения обнаружения на всем изображении.

Однако объекты Rect (pips) имеют свои свойства относительно своих костей, а не самого изображения. Чтобы решить эту проблему, когда мы хотим нарисовать прямоугольники для фактического изображения, показывающего местоположения пипсов, мы добавляем оба значения dice.x и dice.y в начальную Point .

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

Функция getNextImage() возвращает объект Mat , который вместе с другими опубликованными примерами может быть вызван постоянно и может быть преобразован в BufferImage , чтобы обеспечить отображение живого изображения с обнаружением.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow