В предыдущей статье мы говорили об использовании JavaCV для вывода экрана камеры ноутбука. На этот раз мы обработали функцию распознавания лиц на основе прошлого раза.
Принцип очень прост: вытащите каждый кадр камеры, а затем определите каждый кадр, чтобы увидеть, есть ли в нем лицо. Если да, нарисуйте рамку на лице, нарисуйте красную рамку на экране, а затем верните «Показать». это вперед.
Для функции распознавания лиц требуется файл haarcascade_frontalface_alt.xml. Это файл классификатора лиц, обученный в OpenCV. Он также называется классификатором фронтального распознавания лиц. Мы загружаем его локально и размещаем в разделе «Ресурсы». Используйте CascadeClassifier для загрузки.
Затем возникали различные проблемы с вылетом: либо была проблема с загрузкой xml-файла, либо была проблема с упаковкой метода, предоставляемой chatgpt.
Возникла проблема с ошибкой загрузки haarcascade_frontalface_alt.xml.
Также есть проблемы с конвертацией Mat.
К счастью, если я спрошу об этом, он сможет обнаружить проблему самостоятельно.
Проходя целый день, я, наконец, исправил это. Если вы зайдете в Baidu, чтобы найти кейс, написанный другими, это может не занять и пяти минут, но действительно будет сложно чему-либо научиться.
Далее поговорим о распознавании шагов человека!
использоватьOpenCVFrameGrabber
объект Получить эту машину Камера,Укажите разрешение
//Получаем локальную камеру, обычно 0
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
// Камера может иметь несколько разрешений, указанных здесь.
// Вы можете указать ширину и высоту или вызвать метод Grabber.getImageWidth, чтобы получить их вместо указания.
grabber.setImageWidth(1280);
grabber.setImageHeight(720);
// Включить сканер
grabber.start();
использоватьCanvasFrame
объект Создайте окно для отображениявидеопоток
//Создаем окно фрейма
CanvasFrame previewCanvas = new CanvasFrame("Предварительный просмотр камеры", CanvasFrame.getDefaultGamma() / grabber.getGamma());
previewCanvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
previewCanvas.setAlwaysOnTop(true);
использоватьCascadeClassifier
объектнагрузкараспознавание лиц Модель
// Скачать файл модели
CascadeClassifier cascadeClassifier = new CascadeClassifier("D:\\IDEA_Work\\LinkCV\\src\\main\\resources\\haarcascade_frontalface_alt.xml");
Обход каждого кадра, преобразование объекта кадра в объект IplImage, а затем преобразование его в объект Mat.
// Перебирать каждый кадр
while ((captureFrame = grabber.grab()) != null) {
// Преобразовать объект кадра в объект IplImage
IplImage img = openCVConverter.convert(captureFrame);
// Зеркало флип
cvFlip(img, img, 1);
// IplImage в мат
Mat mat1 = new Mat(img);
......
}
Преобразуйте изображение в оттенки серого, поскольку изображения в оттенках серого больше подходят для распознавания лиц и требуют меньше производительности.
// Преобразовать изображение в оттенки серого
Mat grayMat = new Mat();
// Преобразовать текущее изображение в оттенки серого
cvtColor(mat1, grayMat, CV_BGR2GRAY);
Создайте контейнер для результатов обнаружения, а затем запустите обнаружение.
// Контейнер для хранения результатов испытаний
RectVector objects = new RectVector();
// Начать обнаружение
if (cascadeClassifier.empty()) {
System.out.println("Failed to load cascade classifier.");
}
cascadeClassifier.detectMultiScale(grayMat, objects);
Получите результаты обнаружения и обведите их красной рамкой.
// Общее количество результатов теста
long total = objects.size();
// Если есть результат обнаружения, на основе данных результата строится прямоугольный кадр и рисуется на исходном изображении.
for (long i = 0; i < total; i++) {
Rect r = objects.get(i);
int x = r.x(), y = r.y(), w = r.width(), h = r.height();
rectangle(mat1, new Point(x, y), new Point(x + w, y + h), Scalar.RED, 1, CV_AA, 0);
}
Освободите ресурсы и верните картинку с красной рамкой на передний план.
// Опубликовать ресурсы с результатами тестирования
objects.close();
// Преобразуйте аннотированное изображение в рамку и верните его.
Frame convert = openCVConverter.convert(mat1);
// отображать изображение
previewCanvas.showImage(convert);
На этом распознавание лиц заканчивается.
Первым шагом определенно является введение зависимостей maven.
Одна из них — зависимость JavaCV, а другая — зависимость от Lombok, потому что я планирую использовать @Slf4j.
<!-- зависимости, связанные с javacv, достаточно одной -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
Затем есть код распознавания лица
package com.gateway.link.cv.local;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import javax.swing.*;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import static cn.hutool.core.util.ClassUtil.getClassLoader;
import static org.bytedeco.opencv.global.opencv_core.cvFlip;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
/**
* @author YESIJIE
* @date 2023-07-16 16:16
*/
@Slf4j
public class localVideFace {
/**
* Выходная частота кадров
*/
private static final double frameRate = 30;
/**
* Ширина камерывидео
*/
private static final int cameraImageWidth = 1280;
/**
* Камеравидеовысота цели */
private static final int cameraImageHeight = 720;
/**
* преобразователь
*/
private static final OpenCVFrameConverter.ToIplImage openCVConverter = new OpenCVFrameConverter.ToIplImage();
public static void main(String[] args) throws Exception
{
long startTime = System.currentTimeMillis();
// Установить уровень журнала ffmepg
avutil.av_log_set_level(avutil.AV_LOG_INFO);
FFmpegLogCallback.set();
//Получаем локальную камеру, обычно 0
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
// Камера может иметь несколько разрешений, указанных здесь.
// Вы можете указать ширину и высоту или вызвать метод Grabber.getImageWidth, чтобы получить их вместо указания.
grabber.setImageWidth(1280);
grabber.setImageHeight(720);
// Включить сканер
grabber.start();
//Создаем окно фрейма
CanvasFrame previewCanvas = new CanvasFrame("Предварительный просмотр камеры", CanvasFrame.getDefaultGamma() / grabber.getGamma());
previewCanvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
previewCanvas.setAlwaysOnTop(true);
log.info("Инициализация завершена, заняла [{}] миллисекунд, частота кадров [{}], ширина изображения [{}], высота изображения [{}]",
System.currentTimeMillis()-startTime,
frameRate,
cameraImageWidth,
cameraImageHeight);
// Инструмент «Время», используемый при добавлении водяных знаков
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// Расположение водяного знака на изображении
org.bytedeco.opencv.opencv_core.Point point = new org.bytedeco.opencv.opencv_core.Point(15, 35);
Frame captureFrame;
// Скачать файл модели
CascadeClassifier cascadeClassifier = new CascadeClassifier("D:\\IDEA_Work\\LinkCV\\src\\main\\resources\\haarcascade_frontalface_alt.xml");
// Перебирать каждый кадр
while ((captureFrame = grabber.grab()) != null) {
// Преобразовать объект кадра в объект IplImage
IplImage img = openCVConverter.convert(captureFrame);
// Зеркало флип
cvFlip(img, img, 1);
// IplImage в мат
Mat mat1 = new Mat(img);
// Добавьте водяной знак к изображению. Содержимое водяного знака — это текущее время, а его положение — верхний левый угол.
opencv_imgproc.putText(mat1,
simpleDateFormat.format(new Date()),
point,
opencv_imgproc.CV_FONT_VECTOR0,
0.8,
new Scalar(0, 200, 255, 0),
1,
0,
false);
// Преобразовать изображение в оттенки серого
Mat grayMat = new Mat();
// Преобразовать текущее изображение в оттенки серого
cvtColor(mat1, grayMat, CV_BGR2GRAY);
// Контейнер для хранения результатов испытаний
RectVector objects = new RectVector();
// Начать обнаружение
if (cascadeClassifier.empty()) {
System.out.println("Failed to load cascade classifier.");
}
cascadeClassifier.detectMultiScale(grayMat, objects);
// Общее количество результатов теста
long total = objects.size();
// Если есть результат обнаружения, на основе данных результата строится прямоугольный кадр и рисуется на исходном изображении.
for (long i = 0; i < total; i++) {
Rect r = objects.get(i);
int x = r.x(), y = r.y(), w = r.width(), h = r.height();
rectangle(mat1, new Point(x, y), new Point(x + w, y + h), Scalar.RED, 1, CV_AA, 0);
}
// Опубликовать ресурсы с результатами тестирования
objects.close();
// Преобразуйте аннотированное изображение в рамку и верните его.
Frame convert = openCVConverter.convert(mat1);
// отображать изображение
previewCanvas.showImage(convert);
}
log.info("Конец вывода");
if (null!= previewCanvas) {
previewCanvas.dispose();
}
if (null!=grabber) {
try {
grabber.close();
} catch (Exception exception) {
log.error("close grabber error", exception);
}
}
}
}
Эффект наверное выглядит так,На кадре видео будет нарисована рамка для распознанной части лица.,Затем вытащите его на дисплей. Потому что у меня нет внешности,Поэтому я закодировал себя.
Что касается модели haarcascade_frontalface_alt, вы можете скачать ее прямо с github.
https://github.com/opencv/opencv/tree/master/data/haarcascades