java基于OpenCVDnn实现人脸识别和图像分类学习
创始人
2025-06-01 10:16:29

[OpenCV实战]2 人脸识别算法对比 - 落痕的寒假 - 博客园 (cnblogs.com)

java高度人脸识别,再也不用受python的气了!_小明程序猿的博客-CSDN博客

OpenCV 人脸检测详解(仅需2行代码学会人脸检测) - 掘金 (juejin.cn)

OpenCV基础(15)OpenCV DNN模块的深度学习:权威指南_求则得之,舍则失之的博客-CSDN博客

汇总 | OpenCV DNN模块中支持的分类网络 - 腾讯云开发者社区-腾讯云 (tencent.com)

java-opencv-训练自己的物体分类器 - 锐洋智能 - 博客园 (cnblogs.com)

DenseNet-121-昇腾社区 (hiascend.com)

之前的文章地址:http://t.csdn.cn/19X9Q

本次开发语言:Java

其实下载下来的opencv安装包是自带 Haar Cascade人脸分类器的,不过这个识别错误率挺高的。当人脸有遮挡,侧脸,嘴型变化等,都会导致识别失败。

OpenCVDnn 可能综合来说是最好的方法。

OpenCV 深度神经网络(Deep Neural Networks,DNN),使用流行的深度学习框架(例如 CaffeTensorFlowTorchDarknet )通过预先训练的深度网络实现前向计算(即推理阶段)。这里使用的是 ResNet-10 网络的 Single Shot MultiBox Detector (SSD) 框架

这里使用的模型是 ResNet

必备文件:

  • 人脸检测器 (FP16):Caffe 实现的浮点 16 版本,为了使用此检测器,首先下载模型文件(deploy.prototxt)和配置文件(res10_300x300_ssd_iter_140000_fp16.caffemodel);

  • 人脸检测器 (UINT8):TensorFlow 实现的 8 位量化版本,为了使用此检测器,首先下载模型文件(opencv_face_detector.pbtxt)和配置文件(opencv_face_detector_uint8.pb)。

import org.opencv.core.*;
import org.opencv.dnn.Dnn;
import org.opencv.dnn.Net;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;public class Demo {public static void main(String[] args) {imageFaceDetectionDnn();}public static void imageFaceDetectionDnn() {//加载opencv本地库System.loadLibrary(Core.NATIVE_LIBRARY_NAME);//加载预训练好的模型Net net = Dnn.readNetFromCaffe("E:\\电脑文件路径\\deploy.prototxt","E:\\电脑文件路径\\res10_300x300_ssd_iter_140000_fp16.caffemodel");//读取图片String imgPath = "C:\\Users\\A80759\\Pictures\\Saved Pictures\\20200924194319998.jpg";Mat image = Imgcodecs.imread(imgPath);//为了获得最佳精度,必须分别对蓝色、绿色和红色通道执行 `(104, 177, 123)` 通道均值减法Mat inputBlob = Dnn.blobFromImage(image, 1.0f,new Size(image.size().width, image.size().height),new Scalar(104, 117, 123), false, false);net.setInput(inputBlob);Mat res = net.forward();Mat faces = res.reshape(1, res.size(2));System.out.println("faces" + faces);float [] data = new float[7];System.out.println("识别到人脸数:" + faces.rows());for (int i=0; ifaces.get(i, 0, data);float confidence = data[2];if (confidence > 0.2f) {int left   = (int)(data[3] * image.cols());int top    = (int)(data[4] * image.rows());int right  = (int)(data[5] * image.cols());int bottom = (int)(data[6] * image.rows());System.out.println("("+left + "," + top + ")("+right+","+bottom+") " + confidence);Imgproc.rectangle(image, new Point(left,top), new Point(right,bottom), new Scalar(0,200,0), 3);}}Imgcodecs.imwrite("C:\\电脑文件路径\\new.jpg", image);// 展示图片HighGui.imshow("人脸识别", image);HighGui.waitKey(0);}
}

blobFromImage(image, scalefactor=None, size=None, mean=None, swapRB=None, crop=None, ddepth=None) 它将图像以正确的格式输入模型,然后该函数输出一个四维矩阵。

  • image:这是我们刚刚使用imread()函数读取的输入图像。
  • scalefactor:这个值根据提供的值缩放图像。它的默认值是1,这意味着不执行缩放。
  • size:这是图像将被调整为的大小。我们提供了224×224的大小,这是大多数在ImageNet数据集上训练的分类模型所期望的大小。
  • mean:这一参数非常重要。这些实际上是从图像的RGB颜色通道中减去的平均值。这将输入归一化并使最终输入对不同的照明尺度具有不变性。
  • swapRB:表示在3通道图像中是否交换第一个和最后一个通道。
  • crop:图像在调整大小后是否被裁剪,如果crop为真,调整输入图像大小,调整大小后的一边等于相应的尺寸,另一面等于相应的尺寸或比相应的尺寸更大。然后,从中心进行裁剪。
  • ddepth:输出blob的深度。选择CV_32F或CV_8U

示例1

在这里插入图片描述

控制台输出(每个方框上下左右的坐标以及识别率)

(589,258)(616,288) 0.9975394
(124,206)(152,242) 0.9969188
(80,249)(106,286) 0.99600464
(382,199)(409,235) 0.99527127
(312,199)(338,235) 0.99450785
(394,244)(416,273) 0.99186796
(352,220)(377,255) 0.990858
(270,246)(296,280) 0.9882124
(56,226)(81,255) 0.9871501
(519,244)(542,274) 0.98257476
(568,232)(590,260) 0.9770947
(185,203)(210,238) 0.95680207
(224,201)(248,230) 0.9469372
(183,262)(212,301) 0.9389939
(660,216)(684,246) 0.92794573
(468,229)(495,263) 0.8848143
(27,255)(53,284) 0.8775511
(265,209)(284,240) 0.8663978
(496,226)(518,252) 0.85343516
(442,235)(463,263) 0.75329876
(668,164)(690,191) 0.69498074
(324,175)(344,197) 0.3945995
(28,179)(44,203) 0.34156087
(378,171)(395,197) 0.27158168

这里把识别率调整为 大于0.2 即认为是人脸

在这里插入图片描述

示例2

在这里插入图片描述

控制台输出

(1156,374)(1190,417) 0.9992472
(934,274)(960,308) 0.99852234
(557,394)(587,429) 0.99838257
(1385,332)(1423,373) 0.99836737
(1393,386)(1431,428) 0.99816304
(333,368)(363,404) 0.9981445
(1276,378)(1312,420) 0.99808145
(756,266)(787,300) 0.99715877
(270,336)(300,372) 0.996067
(1279,312)(1312,351) 0.9959883
(431,346)(460,382) 0.9959792
(726,374)(754,414) 0.995004
(791,314)(819,352) 0.99491924
(576,273)(602,308) 0.9948049
(296,416)(329,453) 0.99422365
(941,389)(971,430) 0.9940135
(377,320)(407,356) 0.99389946
(474,421)(506,460) 0.9935196
(1243,247)(1274,286) 0.993379
(1047,380)(1076,425) 0.9932128
(233,384)(268,421) 0.99236125
(185,447)(220,483) 0.9923139
(1190,307)(1222,345) 0.9916454
(624,315)(651,353) 0.9911696
(1030,269)(1056,304) 0.99091816
(680,270)(708,305) 0.9895411
(467,295)(494,330) 0.9886185
(131,386)(164,426) 0.98816407
(702,329)(733,368) 0.9881606
(397,414)(428,454) 0.9875408
(1129,270)(1160,306) 0.9863598
(852,278)(878,312) 0.9858732
(985,321)(1014,361) 0.980375
(528,326)(557,360) 0.9786332
(1355,254)(1384,286) 0.9774844
(830,386)(860,427) 0.9756031
(881,328)(911,371) 0.9755162
(632,395)(663,437) 0.9643314
(66,449)(108,488) 0.96184486
(1081,316)(1111,356) 0.95269746

这里把识别率调整为 大于0.9 即认为是人脸

在这里插入图片描述

示例3

在这里插入图片描述

这里把识别率调整为 大于0.99 即认为是人脸

控制台输出

(1372,292)(1488,441) 0.9999876
(83,517)(236,716) 0.9999343
(333,260)(446,414) 0.99986064
(516,310)(612,456) 0.9998554
(394,458)(550,648) 0.9995573
(1126,333)(1234,483) 0.99942386
(898,537)(1044,727) 0.9992487
(1089,566)(1235,751) 0.9991135
(1345,550)(1487,734) 0.9987877
(945,307)(1055,440) 0.99821436
(645,532)(788,719) 0.998075
(718,346)(825,482) 0.9980019

在这里插入图片描述

图片分类

本次使用的模型是 DenseNet-121. 详解DenseNet(密集连接的卷积网络)

  • DenseNet_121.prototxt
  • DenseNet_121.caffemodel

已经做好分类的文本

  • classification_classes_ILSVRC2012.txt
import cn.hutool.core.io.FileUtil;
import org.opencv.core.*;
import org.opencv.dnn.Dnn;
import org.opencv.dnn.Net;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;import java.nio.charset.Charset;
import java.util.List;public class Demo2 {public static void main(String[] args) {//加载opencv本地库System.loadLibrary(Core.NATIVE_LIBRARY_NAME);//读取ImageNet类名List strings = FileUtil.readLines("E:\\xxx\\classification_classes_ILSVRC2012.txt",Charset.defaultCharset());Net net = Dnn.readNetFromCaffe("E:\\xxx\\DenseNet_121.prototxt","E:\\xxx\\DenseNet_121.caffemodel");//读取图片String imgPath = "E:\\xxx\\af0cc6c118a37e9170db1c2ade2ac9c3.jpg";Mat image = Imgcodecs.imread(imgPath);Mat inputBlob = Dnn.blobFromImage(image, 0.01f,new Size(image.size().width, image.size().height),new Scalar(104, 117, 123), false, false);net.setInput(inputBlob);Mat res = net.forward();Mat temp = res.reshape(1, 1);Core.MinMaxLocResult minMaxLocResult = Core.minMaxLoc(temp);Point maxLoc = minMaxLocResult.maxLoc;double x = maxLoc.x;Double d = new Double(x);int classId = d.intValue();double confidence = minMaxLocResult.maxVal;System.out.println(classId + ":" + confidence);Imgproc.putText(image, strings.get(classId)+" "+confidence, new Point(100, 150),Imgproc.CHAIN_APPROX_SIMPLE, 0.5, new Scalar(0, 255, 0, 0));HighGui.imshow("图像分类", image);HighGui.waitKey(0);}
}

结果1

在这里插入图片描述

结果2

在这里插入图片描述

结果3

在这里插入图片描述

还是会出现失误,识别错误率存在

结果4

在这里插入图片描述

相关内容

热门资讯

【实验报告】实验一 图像的... 实验目的熟悉Matlab图像运算的基础——矩阵运算;熟悉图像矩阵的显示方法࿰...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
大模型落地比趋势更重要,NLP... 全球很多人都开始相信,以ChatGPT为代表的大模型,将带来一场NLP领...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
kuernetes 资源对象分... 文章目录1. pod 状态1.1 容器启动错误类型1.2 ImagePullBackOff 错误1....
STM32实战项目-数码管 程序实现功能: 1、上电后,数码管间隔50ms计数; 2、...
TM1638和TM1639差异... TM1638和TM1639差异说明 ✨本文不涉及具体的单片机代码驱动内容,值针对芯...
Qt+MySql开发笔记:Qt... 若该文为原创文章,转载请注明原文出处 本文章博客地址:https://h...
Java内存模型中的happe... 第29讲 | Java内存模型中的happen-before是什么? Java 语言...
《扬帆优配》算力概念股大爆发,... 3月22日,9股封单金额超亿元,工业富联、鸿博股份、鹏鼎控股分别为3.0...
CF1763D Valid B... CF1763D Valid Bitonic Permutations 题目大意 拱形排列࿰...
SQL语法 DDL、DML、D... 文章目录1 SQL通用语法2 SQL分类3 DDL 数据定义语言3.1 数据库操作3.2 表操作3....
文心一言 VS ChatGPT... 3月16号,百度正式发布了『文心一言』,这是国内公司第一次发布类Chat...
CentOS8提高篇5:磁盘分...        首先需要在虚拟机中模拟添加一块新的硬盘设备,然后进行分区、格式化、挂载等...
Linux防火墙——SNAT、... 目录 NAT 一、SNAT策略及作用 1、概述 SNAT应用环境 SNAT原理 SNAT转换前提条...
部署+使用集群的算力跑CPU密... 我先在开头做一个总结,表达我最终要做的事情和最终环境是如何的,然后我会一...
Uploadifive 批量文... Uploadifive 批量文件上传_uploadifive 多个上传按钮_asing1elife的...
C++入门语法基础 文章目录:1. 什么是C++2. 命名空间2.1 域的概念2.2 命名...
2023年全国DAMA-CDG... DAMA认证为数据管理专业人士提供职业目标晋升规划,彰显了职业发展里程碑及发展阶梯定义...
php实现助记词转TRX,ET... TRX助记词转地址网上都是Java,js或其他语言开发的示例,一个简单的...
【分割数据集操作集锦】毕设记录 1. 按要求将CSV文件转成json文件 有时候一些网络模型的源码会有data.json这样的文件里...
Postman接口测试之断言 如果你看文字部分还是不太理解的话,可以看看这个视频,详细介绍postma...
前端学习第三阶段-第4章 jQ... 4-1 jQuery介绍及常用API导读 01-jQuery入门导读 02-JavaScri...
4、linux初级——Linu... 目录 一、用CRT连接开发板 1、安装CRT调试工具 2、连接开发板 3、开机后ctrl+c...
Urban Radiance ... Urban Radiance Fields:城市辐射场 摘要:这项工作的目标是根据扫描...
天干地支(Java) 题目描述 古代中国使用天干地支来记录当前的年份。 天干一共有十个,分别为:...
SpringBoot雪花ID长... Long类型精度丢失 最近项目中使用雪花ID作为主键,雪花ID是19位Long类型数...
对JSP文件的理解 JSP是java程序。(JSP本质还是一个Servlet) JSP是&#...
【03173】2021年4月高... 一、单向填空题1、大量应用软件开发工具,开始于A、20世纪70年代B、20世纪 80年...
LeetCode5.最长回文子... 目录题目链接题目分析解题思路暴力中心向两边拓展搜索 题目链接 链接 题目分析 简单来说࿰...