Рубрики
Без рубрики

Введение в OpenCV с Java

Узнайте, как использовать OpenCV с Java

Автор оригинала: baeldung.

1. введение

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

2. Установка

Чтобы использовать библиотеку OpenCV в нашем проекте, нам нужно добавить зависимость opencv Maven в ваш pom.xml :


    org.openpnp
    opencv
    3.4.2-0

Для пользователей Gradle нам нужно будет добавить зависимость в наш файл build.gradle :

compile group: 'org.openpnp', name: 'opencv', version: '3.4.2-0'

После добавления библиотеки в наши зависимости мы можем использовать функции, предоставляемые OpenCV.

3. Использование библиотеки

Чтобы начать использовать OpenCV, нам нужно инициализировать библиотеку , что мы можем сделать в нашем методе main :

OpenCV.loadShared();

OpenCV – это класс, который содержит методы, связанные с загрузкой собственных пакетов , требуемых библиотекой OpenCV для различных платформ и архитектур.

Стоит отметить, что документация делает вещи немного по-другому:

System.loadLibrary(Core.NATIVE_LIBRARY_NAME)

Оба этих вызова метода фактически загрузят необходимые собственные библиотеки.

Разница здесь в том, что последнее требует установки собственных библиотек . Первый, однако, может установить библиотеки во временную папку, если они недоступны на данной машине. Из-за этой разницы метод load Shared обычно является лучшим способом .

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

4. Загрузка изображений

Для начала давайте загрузим образец образа с диска с помощью OpenCV :

public static Mat loadImage(String imagePath) {
    Imgcodecs imageCodecs = new Imgcodecs();
    return imageCodecs.imread(imagePath);
}

Этот метод загрузит данное изображение в виде объекта Mat , который является матричным представлением.

Чтобы сохранить ранее загруженное изображение, мы можем использовать метод imwrite() класса Imgcodecs :

public static void saveImage(Mat imageMatrix, String targetPath) {
    Imgcodecs imgcodecs = new Imgcodecs();
    imgcodecs.imwrite(targetPath, imageMatrix);
}

5. Каскадный классификатор Хаара

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

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

5.1. Особенности Haar

Распознавание лиц в OpenCV выполняется каскадными классификаторами на основе функций Haar.

Особенности Haar это фильтры, которые используются для обнаружения краев и линий на изображении. Фильтры отображаются в виде квадратов с черно – белыми цветами:

Особенности Haar

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

6. Распознавание лиц

Как правило, каскадный классификатор должен быть предварительно обучен, чтобы иметь возможность обнаруживать что-либо вообще.

Поскольку процесс обучения может быть длительным и потребует большого набора данных, мы собираемся использовать одну из предварительно обученных моделей, предлагаемых OpenCV . Мы поместим этот XML-файл в нашу папку resources для легкого доступа.

Давайте пройдем через процесс обнаружения лица:

Лицо Для Обнаружения

Мы попытаемся определить лицо, обведя его красным прямоугольником.

Для начала нам нужно загрузить изображение в формате Mat из нашего исходного пути:

Mat loadedImage = loadImage(sourceImagePath);

Затем мы объявим объект MatOfRect для хранения найденных граней:

MatOfRect facesDetected = new MatOfRect();

Затем нам нужно инициализировать Каскадный классификатор , чтобы выполнить распознавание:

CascadeClassifier cascadeClassifier = new CascadeClassifier(); 
int minFaceSize = Math.round(loadedImage.rows() * 0.1f); 
cascadeClassifier.load("./src/main/resources/haarcascades/haarcascade_frontalface_alt.xml"); 
cascadeClassifier.detectMultiScale(loadedImage, 
  facesDetected, 
  1.1, 
  3, 
  Objdetect.CASCADE_SCALE_IMAGE, 
  new Size(minFaceSize, minFaceSize), 
  new Size() 
);

Выше параметр 1.1 обозначает масштабный коэффициент, который мы хотим использовать, указывая, насколько уменьшается размер изображения при каждом масштабе изображения. Следующий параметр, 3 , is minNeighbors. Это количество соседей, которое должен иметь прямоугольник-кандидат, чтобы сохранить его.

Наконец, мы пройдемся по граням и сохраним результат:

Rect[] facesArray = facesDetected.toArray(); 
for(Rect face : facesArray) { 
    Imgproc.rectangle(loadedImage, face.tl(), face.br(), new Scalar(0, 0, 255), 3); 
} 
saveImage(loadedImage, targetImagePath);

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

Обнаружено лицо

7. Доступ к камере С помощью OpenCV

До сих пор мы видели, как выполнять распознавание лиц на загруженных изображениях. Но большую часть времени мы хотим делать это в режиме реального времени. Чтобы сделать это, нам нужно получить доступ к камере.

Однако, чтобы иметь возможность показывать изображение с камеры, нам нужно несколько дополнительных вещей, помимо очевидного — камеры. Чтобы показать изображения, мы будем использовать JavaFX.

Поскольку мы будем использовать ImageView для отображения снимков, сделанных нашей камерой, нам нужен способ перевести OpenCV Mat в JavaFX Изображение :

public Image mat2Img(Mat mat) {
    MatOfByte bytes = new MatOfByte();
    Imgcodecs.imencode("img", mat, bytes);
    InputStream inputStream = new ByteArrayInputStream(bytes.toArray());
    return new Image(inputStream);
}

Здесь мы преобразуем наш Mat в байты, а затем преобразуем байты в Изображение объект.

Мы начнем с потоковой передачи вида камеры на сцену JavaFX .

Теперь давайте инициализируем библиотеку с помощью метода load Shared :

OpenCV.loadShared();

Далее мы создадим сцену с Видеозахватом и ImageView для отображения изображения :

VideoCapture capture = new VideoCapture(0); 
ImageView imageView = new ImageView(); 
HBox hbox = new HBox(imageView); 
Scene scene = new Scene(hbox);
stage.setScene(scene); 
stage.show();

Вот, 0 это идентификатор камеры, которую мы хотим использовать. Нам также нужно создать Таймер анимации для обработки настройки изображения:

new AnimationTimer() { 
    @Override public void handle(long l) { 
        imageView.setImage(getCapture()); 
    } 
}.start();

Наконец, наш метод getCapture обрабатывает преобразование Mat в Изображение :

public Image getCapture() { 
    Mat mat = new Mat(); 
    capture.read(mat); 
    return mat2Img(mat); 
}

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

8. Распознавание Лиц В Режиме Реального Времени

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

Код из предыдущего раздела отвечает за захват изображения с камеры и отображение его пользователю. Теперь все, что нам нужно сделать, это обработать захваченные изображения, прежде чем показывать их на экране, используя наш класс CascadeClassifier .

Давайте просто изменим наши getCapture способ также выполнять распознавание лиц:

public Image getCaptureWithFaceDetection() {
    Mat mat = new Mat();
    capture.read(mat);
    Mat haarClassifiedImg = detectFace(mat);
    return mat2Img(haarClassifiedImg);
}

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

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

9. Резюме

В этом уроке мы узнали, как использовать OpenCV в Java.

Мы использовали предварительно обученный каскадный классификатор для обнаружения лиц на изображениях. С помощью JavaFX нам удалось заставить классификаторы обнаруживать лица в режиме реального времени с помощью изображений с камеры.

Как всегда, все примеры кода можно найти на GitHub .