opencv
Использование каскадных классификаторов в Java
Поиск…
Синтаксис
- 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
, чтобы обеспечить отображение живого изображения с обнаружением.