(资料图片)
欢迎访问我的GitHub本篇概览这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
本文是《JavaCV的摄像头实战》系列的第十三篇,前文《JavaCV的摄像头实战之十二:性别检测》中,借助训练好的卷积神经网络模型开发出了识别性别的应用,今天在前文基础上做少量改动,实现年龄识别的功能,效果如下图:
应用主要功能如下图所示:
如果您看过《JavaCV的摄像头实战》系列的其他文章,就会发现上图中只有蓝色部分是新增内容,其余的步骤都是固定套路,《JavaCV的摄像头实战》系列的每一个应用玩的都是相同套路:别看步骤挺多,其实都是同一个流程
关于性别和年龄检测使用卷积神经网络推理性别和年龄的更多技术细节,这里有更详细的说明:https://talhassner.github.io/home/publication/2015_CVPR本篇会使用已训练好的Caffe 模型,训练该模型的数据来自Flickr相册,通过从 iPhone5(或更高版本)智能手机设备自动上传组装而成,并由其作者根据知识共享 (CC) 许可向公众发布,共有26580张照片,涉及2284人,这些人的年龄一共被标识成八组:(0-2、4-6、8-13、15-20、25-32、38-43、48-53、60 -)关于数据源的更多详细,请参考:https://talhassner.github.io/home/projects/Adience/Adience-data.html论文地址:https://talhassner.github.io/home/projects/cnn_agegender/CVPR2015_CNN_AgeGenderEstimation.pdf源码下载《JavaCV人脸识别三部曲》的完整源码可在GitHub下载到,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):名称 | 链接 | 备注 |
---|---|---|
项目主页 | 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协议 |
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 */@Slf4jpublic 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也更强大?之所以分文两篇,是因为年龄和性别识别的套路比较接近,如果在一篇文中讲完,无非是多写几行代码多打几行字,不会对技术带来提升,那还不如每篇只聚焦一个功能,把初始化、使用、资源释放等技术点说清楚,至于单独用还是组合用,留给聪明的读者按自己的需求去自由组合即可欢迎关注博客园:程序员欣宸学习路上,你不孤单,欣宸原创一路相伴...
标签: