欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

本篇概览

  • 本文是《JavaCV的摄像头实战》系列的第十三篇,前文《JavaCV的摄像头实战之十二:性别检测》中,借助训练好的卷积神经网络模型开发出了识别性别的应用,今天在前文基础上做少量改动,实现年龄识别的功能,效果如下图:

  • 应用主要功能如下图所示:

  • 如果您看过《JavaCV的摄像头实战》系列的其他文章,就会发现上图中只有蓝色部分是新增内容,其余的步骤都是固定套路,《JavaCV的摄像头实战》系列的每一个应用玩的都是相同套路:别看步骤挺多,其实都是同一个流程

关于性别和年龄检测

源码下载

名称 链接 备注
项目主页 https://github.com/zq2599/blog_demos 该项目在GitHub上的主页
git仓库地址(https) https://github.com/zq2599/blog_demos.git 该项目源码的仓库地址,https协议
git仓库地址(ssh) git@github.com:zq2599/blog_demos.git 该项目源码的仓库地址,ssh协议
  • 这个git项目中有多个文件夹,本篇的源码在javacv-tutorials文件夹下,如下图红框所示:

  • javacv-tutorials里面有多个子工程,《JavaCV的摄像头实战》系列的代码在simple-grab-push工程下:

准备:文件下载

  • 本次实战需要三个文件:
  1. 人脸检测的模型文件:https://raw.github.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_alt.xml
  2. 年龄识别的配置文件:https://raw.githubusercontent.com/GilLevi/AgeGenderDeepLearning/master/age_net_definitions/deploy.prototxt
  3. 年龄识别的模型文件:https://raw.githubusercontent.com/GilLevi/AgeGenderDeepLearning/master/models/age_net.caffemodel

准备:代码接口简介

  • 编码前,先把涉及到的所有java文件说明一下:
  1. AbstractCameraApplication.java:主程序的抽象类,这里面定义了打开摄像头、抓取每一帧、处理每一帧的基本框架,避免每个应用都把这些事情重复做一遍
  2. PreviewCameraWithGenderAge.java:主程序,是AbstractCameraApplication的实现类,本次实战的核心功能人脸检测和年龄检测,都委托给它的成员变量detectService去完成
  3. DetectService.java:检测服务的接口,里面定义了几个重要的api,例如初始化、处理每一帧、释放资源等
  4. AgeDetectService.java:前文GenderDetectService的子类,仅仅是处理推理结果的逻辑与前文的性别识别略有不同,其余功能完全继承自性别识别
  • 以上代码,咱们已经在前文写过一次了,今天当然不需要重复再做一次,今天是在上述代码基础上做两处小幅度修改,接下来就开始吧

改动一:主程序(PreviewCameraWithGenderAge.java)

  • 卷积神经网络所需的配置和模型文件,是在主程序的main方法内设置的,上一章是性别检测,这里替换为年龄检测的文件,如下所示,请您将路径换为自己电脑上的文件路径:
    public static void main(String[] args) {
String base = "E:\\temp\\202112\\25\\opencv\\"; DetectService detectService = new AgeDetectService(
base + "haarcascade_frontalface_alt.xml",
base + "age\\deploy.prototxt",
base + "age\\age_net.caffemodel"); new PreviewCameraWithGenderAge(detectService).action(1000);
}

改动二:检测服务实现(GenderDetectService的子类)

  • 前文《性别检测》的核心功能都集中在GenderDetectService.java中,今天要做的年龄检测,除了推理结果的处理逻辑略有不同,其余功能与《性别检测》完全一致
  • 所以,实现年龄检测的最简单方法就是写一个子类继承GenderDetectService,这个子类中只有神经网络推理结果的处理逻辑,完整代码如下,注释中已经有了详细说明,就不多赘述了:
package com.bolingcavalry.grabpush.extend;

import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.DoublePointer;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Point; import static org.bytedeco.opencv.global.opencv_core.minMaxLoc; /**
* @author willzhao
* @version 1.0
* @description 检测年龄的服务
* @date 2021/12/3 8:09
*/
@Slf4j
public class AgeDetectService extends GenderDetectService { /**
* 设置训练模型时划分的年龄段,所以推理结果也是这样的年龄段
*/
private static final String[] AGES = new String[]{"0-2", "4-6", "8-13", "15-20", "25-32", "38-43", "48-53", "60-"}; /**
* 构造方法,在此指定proto和模型文件的下载地址
*
* @param classifierModelFilePath
* @param cnnProtoFilePath
* @param cnnModelFilePath
*/
public AgeDetectService(String classifierModelFilePath, String cnnProtoFilePath, String cnnModelFilePath) {
super(classifierModelFilePath, cnnProtoFilePath, cnnModelFilePath);
} @Override
protected String getDescriptionFromPredictResult(Mat prob) {
DoublePointer pointer = new DoublePointer(new double[1]);
Point max = new Point(); // 把prob理解为一个数组,
// 第一个元素是"0-2"的置信度
// 第二个元素是"4-6"的置信度
// 第三个元素是"8-13"的置信度
// 第四个元素是"15-20"的置信度
// ...
// 第八个元素是"60-"的置信度
// minMaxLoc方法帮忙我们找出了置信度最高的元素,max是元素位置,pointer是这个元素的置信度
minMaxLoc(prob, null, pointer, null, max, null); // 如果置信度太低,那就是"难以置信",就返回空字符串
if (pointer.get()<0.6d) {
return "";
} else {
// 如果置信度可信,就返回该元素对应的年龄范围
return AGES[max.x()];
}
}
}
  • 至此,编码完成,按套路出牌让咱们省下不少时间,接下来开始验证

验证

  • 确保摄像头工作正常,运行PreviewCameraWithGenderAge类的main方法(再次提醒,main方法中文件的位置,注意是年龄检测的模型文件,不是性别检测的)
  • 天气很冷,为了领到免费盒饭,群众演员早就等得不耐烦了,让他站在摄像头前,如下图,年龄识别成功,且实时展示:

  • 至此,本地窗口预览集成人脸检测和年龄检测的功能就完成了,得益于JavaCV的强大,整个过程是如此的轻松愉快,接下来请继续关注欣宸原创,《JavaCV的摄像头实战》系列还会呈现更多丰富的应用;

关于性别+年龄识别

  • 如果您关注过网上关于性别和年龄识别相关的技术文章,您会发现通常这些文章会将两种识别集成在一起讲,并且代码的效果也是继承了两种识别的,如下图:

  • 也行您会有疑问:欣宸为何不把两种识别放在一篇文章和一个demo中,这样内容更完整demo也更强大?
  • 之所以分文两篇,是因为年龄和性别识别的套路比较接近,如果在一篇文中讲完,无非是多写几行代码多打几行字,不会对技术带来提升,那还不如每篇只聚焦一个功能,把初始化、使用、资源释放等技术点说清楚,至于单独用还是组合用,留给聪明的读者按自己的需求去自由组合即可

欢迎关注博客园:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

JavaCV的摄像头实战之十三:年龄检测的更多相关文章

  1. JavaCV的摄像头实战之一:基础

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 关于<JavaCV的摄像头实战>系列 &l ...

  2. JavaCV的摄像头实战之二:本地窗口预览

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  3. JavaCV的摄像头实战之四:抓图

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<JavaCV的摄像头实战> ...

  4. JavaCV的摄像头实战之五:推流

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<JavaCV的摄像头实战> ...

  5. JavaCV的摄像头实战之六:保存为mp4文件(有声音)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. JavaCV的摄像头实战之七:推流(带声音)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<JavaCV的摄像头实战> ...

  7. OpenCV实战:人脸关键点检测(FaceMark)

    Summary:利用OpenCV中的LBF算法进行人脸关键点检测(Facial Landmark Detection) Author:    Amusi Date:       2018-03-20 ...

  8. TF项目实战(SSD目标检测)-VOC2007

    TF项目实战(SSD目标检测)-VOC2007 训练好的模型和代码会公布在网上: 步骤: 1.代码地址:https://github.com/balancap/SSD-Tensorflow 2.解压s ...

  9. python基础实战之猜年龄游戏

    目录 一.Python基础实战之猜年龄游戏 给定年龄,用户可以猜三次年龄 年龄猜对,让用户选择两次奖励 用户选择两次奖励后可以退出 age = 18 # 答案 count = 0 # 游戏次数控制 p ...

  10. JavaCV 采集摄像头和麦克风数据推送到流媒体服务器

    越来越觉得放弃JavaCV FFmpeg native API,直接使用JavaCV二次封装的API开发是很明智的选择,使用JavaCV二次封装的API开发避免了各种内存操作不当引起的crash. 上 ...

随机推荐

  1. python实现关闭usb功能

    禁用usb和启用usb 一禁用usb自动加载功能 公司内部有时候需要禁用usb接口的文件拷贝,但是打印机,扫描枪等待其他设备的使用,我们应该怎么做呢,很简单,可以通过修改BIOS,注册表和第三方软件实 ...

  2. [Linux]浅析"command > /dev/null 2>&1 &" 与 "command 1>/dev/null 2>&1 &"

    1 问题描述 1.1 问题描述 在一项目中查看CENTOS 服务器的定时任务crontab时查看到如下这段命令: 命令clearLog.sh > /dev/null 2>&1 &a ...

  3. Java设计模式 —— 观察者模式

    16 观察者模式 16.1 观察者模式概述 Observer Pattern: 定义对象之间的依赖关系(一对多),当一个对象的状态发生改变时,其关联的依赖对象均收到通知并自动更新. 观察者模式又称:发 ...

  4. day47:Bootstrap

    什么是Bootstrap? Bootstrap是一个开源框架,是对html\css\js\jquery等的封装,用法,复制黏贴一把梭. 关于Bootstrap的一些常用网址 网址: https://w ...

  5. socket 到底是个啥

    哈喽大家好,我是咸鱼 我相信大家在面试过程中或多或少都会被问到这样一个问题:你能解释一下什么是 socket 吗 我记得我当初的回答很是浅显:socket 也叫套接字,用来负责不同主机程序之间的网络通 ...

  6. JAVASE和JAVAEE的区别

    JAVASE和JAVAEE的区别 JavaEE: Java Enterprise Edition,Java企业版,多用于企业级开发,包括web开发等等.企业版本帮助开发和部署可移植.健壮.可伸缩切安全 ...

  7. SpringBoot整合EMQ

    1.引入依赖 <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.ecli ...

  8. AI 绘画咒语入门 - Stable Diffusion Prompt 语法指南 【成为初级魔导士吧!】

    要用好 Stable Diffusion,最最重要的就是掌握 Prompt(提示词).由于提示词对于生成图的影响甚大,所以被称为魔法,用得好惊天动地,用不好魂飞魄散 . 因此本篇整理下提示词的语法(魔 ...

  9. VS2022使用ClickOnce发布程序本地安装.net框架

    因为遇到下面的错误,没有在网上搜到详细解决问题的教程,费了一些时间才解决了问题,特此记录一下,也希望能帮助到其他人. 要在"系统必备"对话框中启用"从与我的应用程序相同的 ...

  10. rnacos——用rust重新实现的nacos开源配置、注册中心服务

    1. 简介 rnacos 是一个用rust实现的nacos服务. rnacos是一个轻量.快速.稳定的服务,包含注册中心.配置中心.web管理控制台功能. rnacos兼容nacos client s ...