Java使用opencv实现人脸识别、人脸比对

1. opencv概述

OpenCV是一个开源的计算机视觉库,它提供了一系列丰富的图像处理和计算机视觉算法,包括图像读取、显示、滤波、特征检测、目标跟踪等功能。

opencv官网:https://opencv.org/
opencv官网文档:https://docs.opencv.org/4.7.0/index.html
参考教程1:https://www.w3cschool.cn/opencv/
参考教程2:https://www.yiibai.com/opencv/opencv_adding_text.html

2. 安装opencv
2.1 下载opencv

opencv下载:https://opencv.org/releases/
在这里插入图片描述
这里我们使用4.7.0版本,下载到本地后,双击进行安装即可。

进入到opencv的安装目录:
在这里插入图片描述

build :基于window构建sources:开源,提供源码

进入到build\java 目录
在这里插入图片描述

x64与x86目录下是对应的.dll文件:代表给不同的系统使用,下面的代码会使用到.dll文件
opencv-460.jar给java操作openvc的程序包

2.2 准备文件
# 1. 特征分类器:windows 和 linux 中的配置文件都一样,随便用哪个都行
haarcascade_frontalface_alt.xml
# windows 路径 : opencv\build\etc\haarcascades
# linux 路径 : /usr/local/share/opencv4/haarcascades# 2. jar 包 - 也可以直接使用 javacv 中的 opencv 包
opencv-470.jar
# windows 路径 : {opencv安装目录}\opencv\build\java
# linux 路径 : /usr/local/share/java/opencv4# 3. 动态库
opencv_java470.dll (windows系统使用此文件)
# windows 路径 : {opencv安装目录}\opencv\build\java\{x64}/{x86} 跟据系统选择
libopencv_java470.so (linux系统使用此文件)
# linux 路径 : /usr/local/share/java/opencv4
3. 代码实现
3.1 pom.xml添加依赖
<!-- 版本的依赖与下载的opencv版本一致-->
<dependency><groupId>org.bytedeco</groupId><artifactId>opencv</artifactId><version>4.7.0-1.5.9</version></dependency>

或:

        <dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.9</version></dependency>

或:

<dependency><groupId>org.openpnp</groupId><artifactId>opencv</artifactId><version>4.7.0-0</version></dependency>

以上三个依赖任选其一即可,项目打包后观察一下使用哪个依赖打包后的jar文件更小

ps:依赖包太大,优化参考:https://blog.csdn.net/u014644574/article/details/122067708

3.2 编写代码

ps:代码中存在加载.dll、haarcascade_frontalface_alt.xml文件,请确保文件地址正确

package com.testpro.test.opencv;import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;import java.util.Arrays;public class FaceCompare {// 初始化人脸探测器static CascadeClassifier faceDetector;private static final String PATH_PREFIX = "C:\\Users\\dev\\Desktop\\";static int i = 0;static {// 判断系统String os = System.getProperty("os.name");// 加载动态库if (os != null && os.toLowerCase().startsWith("windows")) {// Windows操作系统// todo windows 系统部署加载 .dll 文件 - 路径跟据自己存放位置更改【这里需要使用绝对路径】System.load("D:\\opencv\\opencv\\build\\java\\x64\\opencv_java470.dll");} else if (os != null && os.toLowerCase().startsWith("linux")) {// Linux操作系统// todo Linux 服务器部署加载 .so 文件 - 路径跟据自己存放位置更改【是否需要绝对路径有待验证,目前只在windows 系统实践过】System.load("/opt/face/libopencv_java440.so");}// 引入 特征分类器配置 文件:haarcascade_frontalface_alt.xml 文件路径// 此文件在opencv的安装目录build\etc\haarcascades下可以找到String property = "D:\\opencv\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_alt.xml";System.out.println(property);faceDetector = new CascadeClassifier(property);}public static void main(String[] args) {// 图片路径不能包含中文String str1 = PATH_PREFIX + "3-1.jpg";String str2 = PATH_PREFIX + "3-2.jpg";long start = System.currentTimeMillis();double compareHist = compare_image(str1, str2);System.out.println("time:" + (System.currentTimeMillis() - start));System.out.println(compareHist);if (compareHist > 0.6) {System.out.println("人脸匹配");} else {System.out.println("人脸不匹配");}}// 灰度化人脸public static Mat conv_Mat(String img) {Mat image0 = Imgcodecs.imread(img);Mat image1 = new Mat();// 灰度化Imgproc.cvtColor(image0, image1, Imgproc.COLOR_BGR2GRAY);// 探测人脸MatOfRect faceDetections = new MatOfRect();faceDetector.detectMultiScale(image1, faceDetections);// rect中人脸图片的范围for (Rect rect : faceDetections.toArray()) {Mat face = new Mat(image1, rect);return face;}return null;}// 比较图片public static double compare_image(String img_1, String img_2) {Mat mat_1 = conv_Mat(img_1);Mat mat_2 = conv_Mat(img_2);Mat hist_1 = new Mat();Mat hist_2 = new Mat();//颜色范围MatOfFloat ranges = new MatOfFloat(0f, 256f);//直方图大小, 越大匹配越精确 (越慢)MatOfInt histSize = new MatOfInt(10000000);Imgproc.calcHist(Arrays.asList(mat_1), new MatOfInt(0), new Mat(), hist_1, histSize, ranges);Imgproc.calcHist(Arrays.asList(mat_2), new MatOfInt(0), new Mat(), hist_2, histSize, ranges);// CORREL 相关系数double res = Imgproc.compareHist(hist_1, hist_2, Imgproc.CV_COMP_CORREL);return res;}}

上述代码加载.dll文件也可使用以下方式:

ps:【不过以下方式需要将opencv安装目录下的build\java\x64\opencv_java470.dll文件复制到C:\Windows\System32目录下才可使用否则会报错】

// 使用此方法需将D:\opencv\opencv\build\java\x64\opencv_java470.dll文件复制到C:\Windows\System32目录下
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

如下:
在这里插入图片描述

4. 效果

在这里插入图片描述

5. 附:完整代码

包括:
从摄像头实时人脸识别,识别成功保存图片到本地
从本地视频文件中识别人脸
本地图片人脸识别,识别成功并保存人脸图片到本地

package com.testpro.test.opencv;import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.VideoWriter;
import org.opencv.videoio.Videoio;import java.util.Arrays;/*** Opencv 图片人脸识别、实时摄像头人脸识别、视频文件人脸识别*/
public class FaceVideo {// 初始化人脸探测器static CascadeClassifier faceDetector;static int i = 0;static {// 判断系统String os = System.getProperty("os.name");// 加载动态库if (os != null && os.toLowerCase().startsWith("windows")) {// Windows操作系统// todo windows 系统部署加载 .dll 文件 - 路径跟据自己存放位置更改System.load("D:\\opencv\\opencv\\build\\java\\x64\\opencv_java470.dll");
//            ClassLoader.getSystemResource("dlls/opencv_java470.dll");} else if (os != null && os.toLowerCase().startsWith("linux")) {// Linux操作系统// todo Linux 服务器部署加载 .so 文件 - 路径跟据自己存放位置更改System.load("/opt/face/libopencv_java440.so");}// 引入 特征分类器配置 文件:haarcascade_frontalface_alt.xml 文件路径String property = "D:\\opencv\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_alt.xml";System.out.println(property);faceDetector = new CascadeClassifier(property);}private static final String PATH_PREFIX = "C:\\Users\\dev\\Desktop\\";public static void main(String[] args) {// 1- 从摄像头实时人脸识别,识别成功保存图片到本地
//        getVideoFromCamera();// 2- 从本地视频文件中识别人脸
//        getVideoFromFile();// 3- 本地图片人脸识别,识别成功并保存人脸图片到本地
//        face("5-1.jpg");// 4- 比对本地2张图的人脸相似度 (越接近1越相似)double compareHist = compare_image(PATH_PREFIX + "5-1.jpg", PATH_PREFIX + "6-1.jpg");System.out.println(compareHist);if (compareHist > 0.72) {System.out.println("人脸匹配");} else {System.out.println("人脸不匹配");}}/*** OpenCV-4.7.0 从摄像头实时读取*/public static void getVideoFromCamera() {//1 如果要从摄像头获取视频 则要在 VideoCapture 的构造方法写 0VideoCapture capture = new VideoCapture(0);Mat video = new Mat();int index = 0;if (capture.isOpened()) {while (i < 3) {// 匹配成功3次退出capture.read(video);HighGui.imshow("实时人脸识别", getFace(video));index = HighGui.waitKey(100);if (index == 27) {capture.release();break;}}} else {System.out.println("摄像头未开启");}try {capture.release();Thread.sleep(1000);System.exit(0);} catch (InterruptedException e) {e.printStackTrace();}return;}/*** OpenCV-4.7.0 从视频文件中读取*/public static void getVideoFromFile() {VideoCapture capture = new VideoCapture();capture.open(PATH_PREFIX + "yimi.mp4");//1 读取视频文件的路径if (!capture.isOpened()) {System.out.println("读取视频文件失败!");return;}Mat video = new Mat();int index = 0;while (capture.isOpened()) {capture.read(video);//2 视频文件的视频写入 Mat video 中HighGui.imshow("本地视频识别人脸", getFace(video));//3 显示图像index = HighGui.waitKey(100);//4 获取键盘输入if (index == 27) {//5 如果是 Esc 则退出capture.release();return;}}}/*** OpenCV-4.7.0 人脸识别** @param image 待处理Mat图片(视频中的某一帧)* @return 处理后的图片*/public static Mat getFace(Mat image) {// 1 读取OpenCV自带的人脸识别特征XML文件(faceDetector)
//        CascadeClassifier facebook = new CascadeClassifier("D:\\Sofeware\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");// 2 特征匹配类MatOfRect face = new MatOfRect();// 3 特征匹配faceDetector.detectMultiScale(image, face);Rect[] rects = face.toArray();System.out.println("匹配到 " + rects.length + " 个人脸");if (rects != null && rects.length >= 1) {// 4 为每张识别到的人脸画一个圈for (int i = 0; i < rects.length; i++) {Imgproc.rectangle(image, new Point(rects[i].x, rects[i].y), new Point(rects[i].x + rects[i].width, rects[i].y + rects[i].height), new Scalar(0, 255, 0));Imgproc.putText(image, "Human", new Point(rects[i].x, rects[i].y), Imgproc.FONT_HERSHEY_SCRIPT_SIMPLEX, 1.0, new Scalar(0, 255, 0), 1, Imgproc.LINE_AA, false);//Mat dst=image.clone();//Imgproc.resize(image, image, new Size(300,300));}i++;if (i == 3) {// 获取匹配成功第10次的照片Imgcodecs.imwrite(PATH_PREFIX + "face.png", image);}}return image;}/*** OpenCV-4.7.0 图片人脸识别*/public static void face(String filename) {// 1 读取OpenCV自带的人脸识别特征XML文件// OpenCV 图像识别库一般位于 opencv\sources\data 下面
//        CascadeClassifier facebook=new CascadeClassifier("D:\\Sofeware\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");// 2 读取测试图片String imgPath = PATH_PREFIX + filename;Mat image = Imgcodecs.imread(imgPath);if (image.empty()) {System.out.println("image 内容不存在!");return;}// 3 特征匹配MatOfRect face = new MatOfRect();faceDetector.detectMultiScale(image, face);// 4 匹配 Rect 矩阵 数组Rect[] rects = face.toArray();System.out.println("匹配到 " + rects.length + " 个人脸");// 5 为每张识别到的人脸画一个圈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, PATH_PREFIX + i + ".jpg", rect.x, rect.y, rect.width, rect.height);// 进行图片裁剪i++;}// 6 展示图片HighGui.imshow("人脸识别", image);HighGui.waitKey(0);}/*** 裁剪人脸** @param imagePath* @param outFile* @param posX* @param posY* @param width* @param height*/public static void imageCut(String imagePath, String outFile, int posX, int posY, int width, int height) {// 原始图像Mat image = Imgcodecs.imread(imagePath);// 截取的区域:参数,坐标X,坐标Y,截图宽度,截图长度Rect rect = new Rect(posX, posY, width, height);// 两句效果一样Mat sub = image.submat(rect); // Mat sub = new Mat(image, rect);Mat mat = new Mat();Size size = new Size(width, height);Imgproc.resize(sub, mat, size);// 将人脸进行截图并保存Imgcodecs.imwrite(outFile, mat);System.out.println(String.format("图片裁切成功,裁切后图片文件为: %s", outFile));}/*** 人脸比对** @param img_1* @param img_2* @return*/public static double compare_image(String img_1, String img_2) {Mat mat_1 = conv_Mat(img_1);Mat mat_2 = conv_Mat(img_2);Mat hist_1 = new Mat();Mat hist_2 = new Mat();//颜色范围MatOfFloat ranges = new MatOfFloat(0f, 256f);//直方图大小, 越大匹配越精确 (越慢)MatOfInt histSize = new MatOfInt(1000);Imgproc.calcHist(Arrays.asList(mat_1), new MatOfInt(0), new Mat(), hist_1, histSize, ranges);Imgproc.calcHist(Arrays.asList(mat_2), new MatOfInt(0), new Mat(), hist_2, histSize, ranges);// CORREL 相关系数double res = Imgproc.compareHist(hist_1, hist_2, Imgproc.CV_COMP_CORREL);return res;}/*** 灰度化人脸** @param img* @return*/public static Mat conv_Mat(String img) {Mat image0 = Imgcodecs.imread(img);Mat image1 = new Mat();// 灰度化Imgproc.cvtColor(image0, image1, Imgproc.COLOR_BGR2GRAY);// 探测人脸MatOfRect faceDetections = new MatOfRect();faceDetector.detectMultiScale(image1, faceDetections);// rect中人脸图片的范围for (Rect rect : faceDetections.toArray()) {Mat face = new Mat(image1, rect);return face;}return null;}/*** OpenCV-4.7.0 将摄像头拍摄的视频写入本地*/public static void writeVideo() {//1 如果要从摄像头获取视频 则要在 VideoCapture 的构造方法写 0VideoCapture capture = new VideoCapture(0);Mat video = new Mat();int index = 0;Size size = new Size(capture.get(Videoio.CAP_PROP_FRAME_WIDTH), capture.get(Videoio.CAP_PROP_FRAME_HEIGHT));VideoWriter writer = new VideoWriter("D:/a.mp4", VideoWriter.fourcc('D', 'I', 'V', 'X'), 15.0, size, true);while (capture.isOpened()) {capture.read(video);//2 将摄像头的视频写入 Mat video 中writer.write(video);HighGui.imshow("像头获取视频", video);//3 显示图像index = HighGui.waitKey(100);//4 获取键盘输入if (index == 27) {//5 如果是 Esc 则退出capture.release();writer.release();return;}}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/102833.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring三级缓存流程再梳理

本文主要是说下在使用spring时遇到了循环依赖&#xff0c;Spring利用三级缓存怎么解决 getBean(beanName)doGetBean(name, null, null, false);getSingleton(beanName)方法&#xff0c; 最后会通过addSingleton(beanName, singletonObject)存到一级缓存里面去createBean(beanN…

一文拿捏对象内存布局及JMM(JAVA内存模型)

1 JMM(Java Memory Model) 1 概述 Java内存模型(Java Memory Model简称JMM)是一种抽象的概念&#xff0c;并不真实存在&#xff0c;它描述的一组规则或者规范。通过这些规则、规范定义了程序中各个变量的访问方式。jvm运行的程序的实体是线程&#xff0c;而每个线程运行时&am…

Unity编辑器从PC平台切换到Android平台下 Addressable 加载模型出现粉红色,类似于材质丢失的问题

Unity编辑器在PC平台下使用Addressable加载打包好的Cube&#xff0c;运行发现能正常显示。 而在切换到Android平台下&#xff0c;使用Addressable时加载AB包&#xff0c;生成Cube对象时&#xff0c;Cube模型呈现粉红色&#xff0c;出现类似材质丢失的问题。如下图所示。 这是…

安全设备和防火墙

文章目录 微步TDP态势感知防火墙防火墙的负载均衡 微步TDP态势感知 安全设备的主要功能在黑名单&#xff0c;只要记住黑名单的功能在哪即可 常用的是威胁选项卡的监控功能&#xff0c;监控模块会把实时的告警列出来&#xff0c;只要列出来就能分析流量是误报还是真实的&#x…

tomcat服务tomcat多实例部署

tomcat服务&&tomcat多实例部署 文章目录 tomcat服务&&tomcat多实例部署1.简介2.优缺点优点&#xff1a;缺点&#xff1a; 3.工作原理4.工作流程5.tomcat服务部署5.1.java环境安装5.2.拉取tomcat软件包5.3.解压部署5.4.启动tomcat服务5.5.访问tomcat的web页面5.…

基于VUE的图书借阅管理系统的设计与实现

目录 一、摘要 二、技术描述 三、部分截图 四、获取方式 一、摘要 随着我国经济的高速发展&#xff0c;人们对图书的需求也愈发旺盛&#xff0c;而传统图书管理模式存在以下弊端&#xff1a;信息存储和分类操作不够高效&#xff0c;导致查找书籍困难&#xff1b;借还书流程…

【数据结构-栈 二】【单调栈】每日温度、接雨水

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【单调栈的应用】&#xff0c;使用【栈】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&am…

location rewrite

Nginx location 匹配的规则和优先级 Nginx常用的变量 rewrite: 重定向功能 Location 匹配 URI URI&#xff1a;统一资源的表示符&#xff0c;是一种字符串标识&#xff0c;用于标识抽象或者物理资源 先来巩固一些与location结合使用的正则表达式 正则表达式&#xff1a;匹…

基于安卓android微信小程序音乐播放器

运行环境 小程序前端框架&#xff1a;uniapp 小程序运行软件&#xff1a;微信开发者 后端技术:javaSsm(SpringSpringMVCMyBatis)vue.js 后端开发环境:idea/eclipse 数据库:mysql 项目介绍 音乐播放器小程序的设计主要是对系统所要实现的功能进行详细考虑&#xff0c;确定所要…

【机器学习 | 回归问题】超越直线:释放多项式回归的潜力 —— 详解线性回归与非线性 (含详细案例、源码)

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

【数据结构-字符串 四】【字符串识别】字符串转为整数、比较版本号

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【字符串转换】&#xff0c;使用【字符串】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&…

Java Day1

day01 一、Markdown 基础语法1.标题2. 字体3. 引用 >4. 分隔线 --- ***5. 图片 ![]()6.超链接7.列表8.表格9.代码 代码名称 二、计算机三、常用快捷键1. Win 系列2. Ctrl 系列3. ALt 系列 四、 基本的DOS命令1. 打开方式&#xff1a;2. 常用DOS命令 五、计算机语言发展史第一…

【软件测试学习】—软件测试知识点总结(二)

【软件测试学习】—软件测试的分类&#xff08;二&#xff09; 一、软件测试的分类 二、软件的生命周期 三、软件测试的工作流程 四、软件测试用例设计方法 &#xff08;一&#xff09;、等价类划分 定义&#xff1a;等价类划分是一种典型的、重要的黑盒测试的方法&#xff…

从零开始探索C语言(十一)----共用体和位域

文章目录 1. 共用体1.1 定义共用体1.2 访问共用体成员 2. 位域2.1 位域声明2.2 位域的定义和位域变量的说明2.3 位域的使用2.4 位域小结 1. 共用体 共用体是一种特殊的数据类型&#xff0c;允许您在相同的内存位置存储不同的数据类型。您可以定义一个带有多成员的共用体&#…

JavaFx学习问题2--音频、视频播放失败情况

文章目录 一、路径注意事项&#xff1a;① 用相对路径的时候别忘了前面的斜杠② uri问题 二、播放不了的问题① 获取的媒体文件路径本身就是不对的② 必须是uri 额外收获: 一、路径注意事项&#xff1a; ① 用相对路径的时候别忘了前面的斜杠 并不是什么大问题&#xff0c;只是…

2.Javaweb模块基本

1.1web基本 session 和 cookie 有什么区别&#xff1f; 存储位置不同&#xff1a;session 存储在服务器端&#xff1b;cookie 存储在浏览器端。 安全性不同&#xff1a;cookie 安全性一般&#xff0c;在浏览器存储&#xff0c;可以被伪造和修改。 容量和个数限制&#xff1a;…

机器学习之旅-从Python 开始

你想知道如何开始机器学习吗&#xff1f;在这篇文章中&#xff0c;我将简要概括一下使用 Python 来开始机器学习的一些步骤。Python 是一门流行的开源程序设计语言&#xff0c;也是在人工智能及其它相关科学领域中最常用的语言之一。机器学习简称 ML&#xff0c;是人工智能的一…

LCD12864驱动开发

目录 一、概述 二、方框图 三、模块接口说明 1、串口接口管脚信号 2、并行接口 四、模块主要硬件构成说明 1、RS&#xff0c;R/W配4种模式&#xff1a; 2、E信号 五、指令说明 六、读写时序图 6.1 数据传输过程 6.2、时序图 6.3、串口读写时序 七、交流参数 八、软件…

Maven Eclipse

Eclipse 提供了一个很好的插件 m2eclipse &#xff0c;该插件能将 Maven 和 Eclipse 集成在一起。 在最新的 Eclipse 中自带了 Maven&#xff0c;我们打开&#xff0c;Windows->Preferences&#xff0c;如果会出现下面的画面&#xff1a; 下面列出 m2eclipse 的一些特点&a…

基于 ceph-deploy 部署 Ceph 集群 超详细

Ceph part1 一、存储基础1.1 单机存储设备1.2 单机存储的问题1.3 单机存储问题的解决方案1.3.1 商业存储解决方案1.3.2 分布式存储&#xff08;软件定义的存储 SDS&#xff09; 二、分布式存储2.1 常见的分布式存储2.2 分布式存储的类型 三、Ceph概述3.1 Ceph简介3.2 Ceph 优势…