【移花接木】OpenCV4.8 For Java 深度学习 实时人脸检测

news2024/11/18 13:41:57

学习《OpenCV应用开发:入门、进阶与工程化实践》一书,学会本文所有技能就这么简单!
做真正的OpenCV开发者,从入门到入职,一步到位!

前言

我写这篇文章之前,我搜索整个网络文章跟问各种语言大模型,太可怕了,它们没有一个正确的,但是都在给我一本正经的胡说八道。所以没办法,我只好自己研究一番,经过两天的折腾终于搞定了OpenCV DNN部署YOLOv5、YOLOv8等各种模型。然后我特别想把这块最关键的知识点给大家分享一下,所以写了这篇文章,以Java语言完成OpenCV DNN的实时人脸检测,同时解释其中的关键知识点。

OpenCV DNN人脸检测

各种博客上的很多Java人脸检测的文章都还是基于级联检测器的,有的好像是我2017年前文章的代码。后来我再也没写过Java,所以网上居然再也找不到Java版本的OpenCV DNN人脸检测的文章跟代码,各种博客上的代码一看就早已落伍多时。这里使用最新版本的Java SDK和OpenCV4.8深度神经网络模块进行深度学习和人脸检测的方法。关于JDK环境搭建与IDE安装可以看这篇文章:
OpenCV4.8 Java SDK实现YOLOv5模型部署

OpenCV DNN官方提供的人脸检测模型下载地址如下:

https://gitee.com/opencv_ai/opencv_tutorial_data/tree/master/models

输入的数据格式如下:
在这里插入图片描述

这是一个SSD的对象检测模型输出的格式为:

1x1xNx7
[batchId, classId, confidence, left, top, right, bottom]

代码实现与演示

我给OpenCV DNN 人脸检测的Java实现封装成了一个类,客户端只要两行代码即可调用执行,简单方便,写个Java的Main方法即可调用,实现人脸检测,唯一需要的就是先加载OpenCV Java的DLL支持,然后就可以正常调用了。客户端代码如下:

public static void main(String[] args) {
    String model_file = "D:/projects/opencv_face_detector_uint8.pb";
    String pb_txt_file = "D:/projects/opencv_face_detector.pbtxt";
    System.load("D:/opencv-4.8.0/opencv/build/java/x64/opencv_java480.dll");
    System.out.println("start to read image...");
    Mat inputImage = Imgcodecs.imread("D:/images/mmc.png");
    JavaFaceDetection face_detector = new JavaFaceDetection(model_file, pb_txt_file, 0.5f);
    face_detector.infer_image(inputImage);
    HighGui.imshow("OpenCV Java 深度学习人脸检测演示", inputImage);
    HighGui.waitKey(0);
    VideoCapture capture = new VideoCapture();
    capture.open(0);
    while(true) {
        Mat frame = new Mat();
        boolean ret = capture.read(frame);
        Core.flip(frame, frame, 1);
        if(ret) {
            face_detector.infer_image(frame);
            HighGui.imshow("OpenCV Java 深度学习人脸检测演示", frame);
            int c = HighGui.waitKey(1);
            if (c == 27) {
                break;
            }
        }
    }
    HighGui.destroyAllWindows();
    System.exit(0);
}

封装的Java版本深度学习人脸检测类的代码如下:

import com.sun.jna.Pointer;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import org.opencv.dnn.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.videoio.VideoCapture;

public class JavaFaceDetection {

    public Net getNet() {
        return net;
    }

    public void setNet(Net net) {
        this.net = net;
    }

    private Net net;
    private float score_t = 0.5f;

    public JavaFaceDetection(String model_path, String pb_txt_file, float conf) {
        this.score_t = conf;
        this.net = Dnn.readNetFromTensorflow(model_path, pb_txt_file);
    }

    public void infer_image(Mat frame) {
        long stime = System.currentTimeMillis();

        // 推理
        Mat blob = Dnn.blobFromImage(frame, 1.0, new Size(300, 300), new Scalar(104.0, 177.0, 123.0), false, false);
        this.net.setInput(blob);
        Mat probs = this.net.forward();

        // 1x1xNx7
        int rows = probs.size(2);
        int cols = probs.size(3);
        float[] result = new Pointer(probs.dataAddr()).getFloatArray(0, rows*cols);

        probs.get(0, 0, result);
        Mat detectOut = new Mat(rows, cols, CvType.CV_32F);
        detectOut.put(0, 0, result);

        for (int row = 0; row < detectOut.rows(); row++) {
            float conf = (float)detectOut.get(row, 2)[0];
            if (conf > this.score_t) {
                float x1 = (float)(detectOut.get(row, 3)[0] * frame.cols());
                float y1 = (float)(detectOut.get(row, 4)[0] * frame.rows());
                float x2 = (float)(detectOut.get(row, 5)[0] * frame.cols());
                float y2 = (float)(detectOut.get(row, 6)[0] * frame.rows());
                Rect2d box = new Rect2d();
                box.x = x1;
                box.y = y1;
                box.width = x2 - x1;
                box.height = y2 - y1;
                Rect rect = new Rect((int) box.x, (int) box.y, (int) box.width, (int) box.height);
                Imgproc.rectangle(frame, rect, new Scalar(0,0, 255), 2, 8);
                Imgproc.putText(frame, String.format("%.2f", conf), new Point(rect.x, rect.y-5), Imgproc.FONT_HERSHEY_COMPLEX, 0.5, new Scalar(255, 0, 255), 1, 8);
            }
        }
        long end_time = System.currentTimeMillis();
        float fps = 1000.0f /  (end_time - stime);
        Imgproc.putText(frame, String.format("FPS: %.2f", fps), new Point(30, 30), Imgproc.FONT_HERSHEY_COMPLEX, 1.0, new Scalar(0, 0, 255), 2, 8);
    }
}

其中最关键的是如何把推理输出得到四维Tensor张量 1x1xNx7 转换为 一个2D的Mat对象,这个就是各种大语言模型胡编乱造的地方,其实只有用JNA通过JNI接口访问本地C++地址获取推理以后的浮点数数组,然后重新构建一个2D Mat对象即可。解决这个问题其它代码基本是C++版本的Java语言翻译,容易了。

检测单张图像
在这里插入图片描述
视频实时检测-本人亲测有效
在这里插入图片描述
学习《OpenCV应用开发:入门、进阶与工程化实践》一书,学会本文所有技能就这么简单!
做真正的OpenCV开发者,从入门到入职,一步到位!

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

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

相关文章

【Nuxt系列文章】Nuxt3如何更优雅的使用ESLint?

前言 大家好&#xff0c;我是刘明&#xff0c;十年创业老兵&#xff0c;开源技术爱好者。 之前我写了一些关于Nuxt3的技术文章&#xff0c;有些同学很感兴趣。这里做个汇总&#xff0c;大家可以直接点击链接查看。 【Nuxt系列文章】Nuxt3.6带来哪些新特性&#xff1f; 【Nuxt…

【minio】minio文件访问不到问题记录

问题描述&#xff1a; 项目上上传了logo&#xff0c;但是无法回写logo&#xff0c;但是文件minio路径已经返回&#xff0c;并且到minio服务器上也能下载文件&#xff1b; 解决方案&#xff1a; 1.排查Nginx的代理的minio是否正确 2.登录minio服务查一下文件路径policy是否设置访…

【数据结构】树和二叉树的定义 |二叉树的基本特点和性质 |存储与遍历 |递归

专栏文章&#xff1a;数据结构学习笔记 作者主页&#xff1a;格乐斯 前言 树和二叉树的定义 二叉树的基本特点和性质 二叉树的存储与遍历 树的定义 树是n(n>0)个结点的有限集合&#xff1b; 若n0&#xff0c;称为空树&#xff1b; 若n>0&#xff0c;称为非空树&#xf…

【GUI开发基础】

GUI开发基础 &#x1f31f;项目文件组成✨浅析Pro文件配置 &#x1f31f;Qt设计师&#x1f31f;剖析UI文件运行机制&#x1f31f;UI设计方式✨可视化UI设计✨代码化UI设计 &#x1f31f;项目文件组成 创建一个QtGUI项目&#xff1a; open QtCreator —> select Creator Pr…

2024 电工杯高校数学建模竞赛(B题)| 平衡膳食食谱 |建模秘籍文章代码思路大全

铛铛&#xff01;小秘籍来咯&#xff01; 小秘籍团队独辟蹊径&#xff0c;运用负载均衡&#xff0c;多目标规划等强大工具&#xff0c;构建了这一题的详细解答哦&#xff01; 为大家量身打造创新解决方案。小秘籍团队&#xff0c;始终引领着建模问题求解的风潮。 抓紧小秘籍&am…

2024 电工杯高校数学建模竞赛(A题)数学建模完整思路+完整代码全解全析

你是否在寻找数学建模比赛的突破点&#xff1f;数学建模进阶思路&#xff01; 作为经验丰富的数学建模团队&#xff0c;我们将为你带来2024电工杯数学建模竞赛&#xff08;B题&#xff09;的全面解析。这个解决方案包不仅包括完整的代码实现&#xff0c;还有详尽的建模过程和解…

【计算机网络原理】浅谈应用层协议的自定义和传输层UDP协议的总结

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…

Javascript特效之鼠标悬停特效【css】

先看一看效果&#xff0c;是不是很炫酷啊&#xff1f;&#xff1f; HTML代码&#xff1a; <!DOCTYPE html> <html><head><meta charset""UTF-8"" /><title>CSS特效&#xff1a;鼠标悬停效果</title><link rel&q…

LeetCode 132题详解:使用动态规划与中心扩展法解决分割回文串 II 的最少分割次数问题

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

Java面试题--基础篇,更新中...

1、 Java语言有哪些特点 简单易学、有丰富的类库 面向对象&#xff08;Java最重要的特性&#xff0c;让程序耦合度更低&#xff0c;内聚性更高&#xff09; 与平台无关性&#xff08;JVM是Java跨平台使用的根本&#xff09; 可靠安全 支持多线…

列举几个淘宝商品详情API接口测试示例

API名&#xff1a;item_get 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,item_search_shop等]cacheString否[yes…

学生手机管理方案

咱们现在的学生&#xff0c;手机几乎成了标配。所以问题就来了&#xff0c;怎么管理这些手机&#xff0c;让手机在课堂上不成为学习的干扰&#xff1f; 先得搞明白&#xff0c;手机在学生手里上该扮演什么角色。手机确实能帮学生查资料、交流学习&#xff0c;甚至写作业&#x…

初识java——javaSE(6)抽象类与接口【求个关注!】

文章目录 前言一 抽象类1.1 抽象类的概念1.2 抽象类的语法&#xff1a;1.3 抽象类与普通类的区别&#xff1a; 二 接口2.1 接口的概念2.2 接口的语法2.2.1 接口的各个组成2.2.2 接口之间的继承 2.3 接口的实现接口不可以实例化对象 2.4 接口实现多态 三 Object类3.1 Object类是…

如何配置机器人ROS操作系统之间的有线和无线的局域网通信(基于ROS的主从通讯)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言1. 主从配置前的准备工作(1) 查看主从机的hostname(2) 查看各自主机和从机的IP(3) 本教程的hostname和ip如下 2. 在主机中的修改(1) 修改主机的/.bashr文件(2) …

5.1 Go 函数的定义与调用

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

刷题之寻找重复数(leetcode)

寻找重复数 这题实际上就是变形的环形链表Ⅱ&#xff0c;下标为index的下一个元素是nums[index]&#xff0c;下下一个元素是nums[nums[index]] class Solution { public:int findDuplicate(vector<int>& nums) {int fast0;int slow0;while(1){fastnums[nums[fast]]…

数据采集与AI分析,亮数据+通义千问助力跨境电商前行

文章目录 前言工具介绍数据采集工具亮数据Web Scraper IDE亮点 AI数据分析工具 实战电商数据采集与AI分析电商平台选取数据采集完全托管数据集自定义数据集 AI分析 价格总结 前言 随着信息技术的飞速发展&#xff0c;数据采集与AI分析在跨境电商中扮演着越来越重要的角色。通过…

ENVI光谱识别指导采矿管理者监测铜矿分布

圣地亚哥SRGIS的GIS专家Chile需要利用影像光谱信号勘察Chuquicamata的铜矿分布。 解决方案 Chuquicamata是世界上最大的斑岩铜矿分布区。SRGIS发现西部地区只有有限的矿物和贫瘠的岩石&#xff0c;但东部有铜矿分布。为了进一步测定矿藏的情况&#xff0c;他们开发出一套程序&a…

Skywalking快速介绍

&#xff08;01&#xff09;SkyWalking简介 SkyWalking专为微服务&#xff0c;云原生架构和基于容器&#xff08;Docker&#xff0c;k8s&#xff0c;Mesos等&#xff09;的架构设计的应用程序性能监控工具&#xff0c;用于收集、分析、聚合和可视化来自服务和云原生基础设施的数…