Java借助OpenCV实现人脸识别登录完整示例
OpenCV
效果预览
概述
OpenCV(开源计算机视觉库)是在BSD(开源协议)许可下发布的。它是一个高度优化的库,专注于实时应用程序。它具有C ++,Python和Java接口,支持Windows,Linux,Mac OS,iOS和Android。
下载与安装
下载地址:https://opencv.org/releases/
下载到本地后,双击进行安装即可
目录说明
安装目录如下
build :基于window构建
sources:开源,提供源码
build目录说明
这里是Java开发关注java目录即可
x64与x86代表给不同的系统使用
opencv-460.jar给java操作openvc的程序包
由于是64位系统,所以关注x64目录
DLL(Dynamic Link Library)文件为动态链接库文件,又称“应用程序拓展”,是软件文件类型。DLL文件,放置于系统中。当执行某一个程序时,相应的DLL文件就会被调用
OpenCV的基本使用
官网文档地址:https://docs.opencv.org/4.6.0/df/d65/tutorial_table_of_content_introduction.html
中文文档:http://wiki.opencv.org.cn/index.php
教程参考:https://www.w3cschool.cn/opencv/
教程参考:https://www.yiibai.com/opencv/opencv_adding_text.html
项目集成
方式1:
这里使用IDEA进行开发,导入opencv-460.jar库
使用快捷键 Ctrl+Shift+Alt+S打开
选择库项,导入Java库。
方式2:
除了上述方式,还可以将
opencv-460.jar
安装到本地仓库或私有仓库,然后在pom.xml中引入依赖。
在项目根目录创建lib
目录,将上述提及的opencv-460.jar
与opencv_java460.dll
放到该目录
在pom.xml
文件中,通过坐标的形式引入
<!-- 加载lib目录下的opencv包 -->
<dependency>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
<version>4.6.0</version>
<scope>system</scope>
<systemPath>${
basedir}/lib/opencv-460.jar</systemPath>
</dependency>
图片人脸检测
public static void main(String[] args) {
imageFaceDetection();
}
/**
* 图片人脸检测
*/
public static void imageFaceDetection() {
// 加载OpenCV本地库
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// 从配置文件lbpcascade_frontalface.xml中创建一个人脸识别器,文件位于opencv安装目录中
CascadeClassifier faceDetector = new CascadeClassifier("D:\\Development\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
// 读取测试图片
String imgPath = "D:\\user\\test.png";
Mat image = Imgcodecs.imread(imgPath);
if (image.empty()) {
throw new RuntimeException("图片内存为空");
}
// 检测脸部
MatOfRect face = new MatOfRect();
// 检测图像中的人脸
faceDetector.detectMultiScale(image, face);
// 匹配Rect矩阵
Rect[] rects = face.toArray();
System.out.println("识别人脸个数: " + rects.length);
// 识别图片中的所以人脸并分别保存
int i = 1;
for (Rect rect : face.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), 3);
// 进行图片裁剪
imageCut(imgPath, "D:\\user\\" + i + ".jpg", rect.x, rect.y, rect.width, rect.height);
i++;
}
// 图片中人脸画框保存到本地
Imgcodecs.imwrite("D:\\user\\test1.png", image);
// 展示图片
HighGui.imshow("人脸识别", image);
HighGui.waitKey(0);
}
/**
* 裁剪人脸
*
* @param readPath 读取文件路径
* @param outPath 写出文件路径
* @param x 坐标X
* @param y 坐标Y
* @param width 截图宽度
* @param height 截图长度
*/
public static void imageCut(String readPath, String outPath, int x, int y, int width, int height) {
// 原始图像
Mat image = Imgcodecs.imread(readPath);
// 截取的区域
Rect rect = new Rect(x, y, width, height);
// Mat sub = new Mat(image,rect);
Mat sub = image.submat(rect);
Mat mat = new Mat();
Size size = new Size(width, height);
// 人脸进行截图并保存
Imgproc.resize(sub, mat, size);
Imgcodecs.imwrite(outPath, mat);
}
人脸对比相似度
对比1.jpg与1-1.jpg
对比1.jpg与3.jpg
// 初始化人脸探测器
static CascadeClassifier faceDetector;
static {
// 加载OpenCV本地库
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// 从配置文件lbpcascade_frontalface.xml中创建一个人脸识别器,文件位于opencv安装目录中
faceDetector = new CascadeClassifier("D:\\Development\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
}
public static void main(String[] args) {
double comparison = faceRecognitionComparison("D:\\user\\1.jpg", "D:\\user\\1-1.jpg");
System.out.println("对比结果:" + comparison);
if (comparison > 0.85) {
System.out.println("人脸匹配成功");
} else {
System.out.println("人脸不匹配识别");
}
double comparison2 = faceRecognitionComparison("D:\\user\\1.jpg", "D:\\user\\3.jpg");
System.out.println("对比结果:" + comparison2);
if (comparison2 > 0.85) {
System.out.println("人脸匹配成功");
} else {
System.out.println("人脸不匹配识别");
}
// 终止当前运行的 Java 虚拟机。
System.exit(0);
}
/**
* 人脸识别比对
*/
public static double faceRecognitionComparison(String image1, String image2) {
Mat mat1 = conv_Mat(image1);
Mat mat2 = conv_Mat(image2);
Mat mat3 = new Mat();
Mat mat4 = new Mat();
// 颜色范围
MatOfFloat ranges = new MatOfFloat(0f, 256f);
// 直方图大小, 越大匹配越精确 (越慢)
MatOfInt histSize = new MatOfInt(1000);
Imgproc.calcHist(Arrays.asList(mat1), new MatOfInt(0), new Mat(), mat3, histSize, ranges);
Imgproc.calcHist(Arrays.asList(mat2), new MatOfInt(0), new Mat(), mat4, histSize, ranges);
// 比较两个密集或两个稀疏直方图
return Imgproc.compareHist(mat3, mat4, Imgproc.CV_COMP_CORREL);
}
/**
* 灰度化人脸
*/
public static Mat conv_Mat(String img) {
// 读取图像
Mat mat1 = Imgcodecs.imread(img);
Mat mat2 = new Mat();
// 灰度化:将图像从一种颜色空间转换为另一种颜色空间
Imgproc.cvtColor(mat1, mat2, Imgproc.COLOR_BGR2GRAY);
// 探测人脸:检测到的对象作为矩形列表返回
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(mat1, faceDetections);
// rect中人脸图片的范围
for (Rect rect : faceDetections.toArray()) {
Mat face = new Mat(mat1, rect);
return face;
}
return null;
}
对比结果如下
对比结果:1.0
人脸匹配成功
对比结果:0.2501351968792374
人脸不匹配识别
识别视频中的人脸
// 初始化人脸探测器
static CascadeClassifier faceDetector;
static {
// 加载OpenCV本地库
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// 从配置文件lbpcascade_frontalface.xml中创建一个人脸识别器,文件位于opencv安装目录中
faceDetector = new CascadeClassifier("D:\\Development\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
}
public static void main(String[] args) {
videoFaceRecognition();
// 终止当前运行的 Java 虚拟机。
System.exit(0);
}
/**
* 从视频中识别人脸
*/
public static void videoFaceRecognition() {
// 读取视频文件
VideoCapture capture = new VideoCapture();
capture.open("D:\\user\\test.mp4");
if (!capture.isOpened()) {
throw new RuntimeException("读取视频文件失败");
}
Mat video = new Mat();
int index = 0;
while (capture.isOpened()) {
// 抓取、解码并返回下一个视频帧写入Mat对象中
capture.read(video);
// 显示从视频中识别的人脸图像
HighGui.imshow("视频识别人脸", getFace(video));
// 获取键盘输入
index = HighGui.waitKey(100);
// 如果是 Esc 则退出
if (index == 27) {
capture.release();
return;
}
}
}
/**
* 从视频帧中识别人脸
*
* @param image 待处理Mat图片,即视频中的某一帧
* @return 处理后的图片
*/
public static