java基于OpenCVDnn实现人脸识别和图像分类学习

[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

必备文件:

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; i<faces.rows(); i++) {
            faces.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<String> 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

在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值