IDEA 2020
jdk 1.8
opencv 4.5.5
安装 OpenCV 环境
先下载安装 OpenCV:https://opencv.org/releases.html
官网如下,我点击进入 GitHub
我们需要下载对应的版本的 OpenCV,这里最新版的是 4.5.5
一定要注意版本问题,版本不一致可能会出现各种问题,尽量版本保持一致。如果出现
no jniopencv_core in java.library.path
错误,就是版本问题导致的
下载源码,里面的 data 文件夹中有我们需要的人脸分类数据
因为我是 windows10 系统,所以我下载了 opencv-4.5.5-vc14_vc15.exe 进行安装
然后点击进行安装
创建项目进行测试
我们创建一个 springboot 项目,创建之后将下面 pom 依赖复制粘贴进去
<dependencies>
<!--SpringBoot Web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--JavaCV-->
<!--注意下面的版本号,和下载的 opencv 版本要尽量接近,可避免很多错误-->
<!-- 都是从 https://mvnrepository.com/ 搜索到的最新版本 2022/4/7 -->
<!-- javacv+javacpp核心库-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.5.7</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.7</version>
</dependency>
<!-- ffmpeg最小依赖包,必须包含上面的javacv+javacpp核心库 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>5.0-1.5.7</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>5.0-1.5.7</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv-platform</artifactId>
<version>4.5.5-1.5.7</version>
</dependency>
</dependencies>
然后在 application.properties 文件中设置一下端口,防止默认端口被占用
server.port=8889
这个时候我们需要将源码中 data\haarcascades_cuda 目录下的 haarcascade_frontalface_alt.xml 文件复制粘贴项目中的 resources 目录下,这个文件是用于人脸特征分辨的数据文件
创建一个 Controller
OpencvController
package com.example.opencvtest02.controller;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
import javax.swing.*;
/**
* @author z
* @link https://blog.csdn.net/eguid_1/article/details/107420243
*/
@Controller
public class OpencvController {
// 在这里进行测试
public static void main(String[] args) throws Exception {
// 这个 xml 文件路径一定要正确,否则会报如下行的错误,如果报错,请输出查看 xml 路径是否正确
// error: (-215:Assertion failed) !empty() in function ‘cv::CascadeClassifier::detectMultiScale‘
// @link: https://blog.csdn.net/qq_43061705/article/details/97142914
// 这里路径代码做了修改,下面下载的项目是旧版绝对路径代码
String url = new URL(Thread.currentThread().getContextClassLoader().getResource("") + "haarcascade_frontalface_alt.xml").getPath();
String xmlPath = new File(url).toString();
faceDetection(xmlPath, 960, 540);
}
/**
* 人脸检测-eguid
*
* @param cascadeClassifierXml 基于Haar特征的cascade正面人脸分类器
* @param width 图像宽度
* @param height 图像高度
*/
@PostMapping("/face")
public static void faceDetection(String cascadeClassifierXml, Integer width, Integer height) throws Exception, InterruptedException {
// 开启摄像头,获取图像(得到的图像为frame类型,需要转换为mat类型进行检测和识别)
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
if (width != null && width > 1 && height != null && height > 1) {
grabber.setImageWidth(width);
grabber.setImageHeight(height);
}
grabber.start();
if (width == null || height == null) {
height = grabber.getImageHeight();
width = grabber.getImageWidth();
}
// 新建一个预览窗口
CanvasFrame canvas = new CanvasFrame("人脸检测");
canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
canvas.setVisible(true);
canvas.setFocusable(true);
canvas.setSize(width, height);
//窗口置顶
if (canvas.isAlwaysOnTopSupported()) {
canvas.setAlwaysOnTop(true);
}
Frame frame = null;
// 读取opencv人脸检测器
CascadeClassifier cascade = new CascadeClassifier(cascadeClassifierXml);
while (canvas.isVisible() && (frame = grabber.grab()) != null) {
// 从frame中直接获取Mat
Mat img = (Mat) frame.opaque;
//存放灰度图
Mat grayImg = new Mat();
//摄像头色彩模式设置成ImageMode.Gray下不需要再做灰度
// 摄像头获取的是彩色图像,所以先灰度化下
cvtColor(img, grayImg, COLOR_BGRA2GRAY);
//如果要获取摄像头灰度图,可以直接对FrameGrabber进行设置grabber.setImageMode(ImageMode.GRAY);,grabber.grab()获取的都是灰度图
// 均衡化直方图
equalizeHist(grayImg, grayImg);
// 检测到的人脸
RectVector faces = new RectVector();
cascade.detectMultiScale(grayImg, faces);
// 遍历人脸
for (int i = 0; i < faces.size(); i++) {
Rect faceI = faces.get(i);
//绘制人脸矩形区域,scalar色彩顺序:BGR(蓝绿红)
rectangle(img, faceI, new Scalar(0, 255, 0, 1));
int posX = Math.max(faceI.tl().x() - 10, 0);
int posY = Math.max(faceI.tl().y() - 10, 0);
// 在人脸矩形上方绘制提示文字
putText(img, "people face", new Point(posX, posY), FONT_HERSHEY_COMPLEX, 1.0, new Scalar(0, 0, 255, 2.0));
}
// 获取摄像头图像并放到窗口上显示,frame是一帧视频图像
canvas.showImage(frame);
// 40毫秒刷新一次图像
Thread.sleep(40);
}
cascade.close();
canvas.dispose();
// 停止抓取
grabber.close();
}
}
点击执行 OpencvController 下的 main 方法执行,可以看到会弹出一个 960×540 大小的窗口,且会实时更新人脸检测信息
测试项目下载:OpenCVTest02.zip
参考文章
-
OpenCV+Java做人脸识别/裁剪 (参考 pom 依赖)(建议学习 Controller 中代码,识别并裁剪对应人脸图像)
-
JavaCV进阶opencv图像检测识别:摄像头图像人脸检测 (参考 Java 代码)
-
error: (-215:Assertion failed) !empty() in function ‘cv::CascadeClassifier::detectMultiScale‘ (解决参数路径错误问题)