JavaCV的摄像头实战之十二:性别检测,java程序员面试秘籍

  1. AbstractCameraApplication.java:主程序的抽象类,这里面定义了打开摄像头、抓取每一帧、处理每一帧的基本框架,避免每个应用都把这些事情重复做一遍

  2. PreviewCameraWithGenderAge.java:主程序,是AbstractCameraApplication的实现类,本次实战的核心功能人脸检测和性别检测,都委托给它的成员变量detectService去完成

  3. DetectService.java:检测服务的接口,里面定义了几个重要的api,例如初始化、处理每一帧、释放资源等

  4. GenderDetectService.java:是DetectService接口的实现类,本次实战的核心功能都写在这个类中

  • 介绍完毕,可以开始编码了,先从最简单的主程序开始

编码:主程序

  • 《JavaCV的摄像头实战之一:基础》创建的simple-grab-push工程中已经准备好了父类AbstractCameraApplication,所以本篇继续使用该工程,创建子类实现那些抽象方法即可

  • 编码前先回顾父类的基础结构,如下图,粗体是父类定义的各个方法,红色块都是需要子类来实现抽象方法,所以接下来,咱们以本地窗口预览为目标实现这三个红色方法即可:

在这里插入图片描述

  • 新建文件PreviewCameraWithGenderAge.java,这是AbstractCameraApplication的子类,其代码很简单,接下来按上图顺序依次说明

  • 先定义CanvasFrame类型的成员变量previewCanvas,这是展示视频帧的本地窗口:

protected CanvasFrame previewCanvas

  • 把前面创建的DetectService作为成员变量,后面检测的时候会用到:

/**

  • 检测工具接口

*/

private DetectService detectService;

  • PreviewCameraWithGenderAge的构造方法,接受DetectService的实例:

/**

  • 不同的检测工具,可以通过构造方法传入

  • @param detectService

*/

public PreviewCameraWithGenderAge(DetectService detectService) {

this.detectService = detectService;

}

  • 然后是初始化操作,可见是previewCanvas的实例化和参数设置,还有检测、识别的初始化操作:

@Override

protected void initOutput() throws Exception {

previewCanvas = new CanvasFrame(“摄像头预览”, CanvasFrame.getDefaultGamma() / grabber.getGamma());

previewCanvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

previewCanvas.setAlwaysOnTop(true);

// 检测服务的初始化操作

detectService.init();

}

  • 接下来是output方法,定义了拿到每一帧视频数据后做什么事情,这里调用了detectService.convert检测人脸并识别性别,然后在本地窗口显示:

@Override

protected void output(Frame frame) {

// 原始帧先交给检测服务处理,这个处理包括物体检测,再将检测结果标注在原始图片上,

// 然后转换为帧返回

Frame detectedFrame = detectService.convert(frame);

// 预览窗口上显示的帧是标注了检测结果的帧

previewCanvas.showImage(detectedFrame);

}

  • 最后是处理视频的循环结束后,程序退出前要做的事情,先关闭本地窗口,再释放检测服务的资源:

@Override

protected void releaseOutputResource() {

if (null!= previewCanvas) {

previewCanvas.dispose();

}

// 检测工具也要释放资源

detectService.releaseOutputResource();

}

  • 由于检测有些耗时,所以两帧之间的间隔时间要低于普通预览:

@Override

protected int getInterval() {

return super.getInterval()/8;

}

  • 至此,功能已开发完成,再写上main方法,代码如下,请注意AgeDetectService构造方法的三个入参,分别是前面下载的三个文件在本机的位置:

public static void main(String[] args) {

String base = “E:\temp\202112\25\opencv\”;

DetectService detectService = new GenderDetectService(

base + “haarcascade_frontalface_alt.xml”,

base + “gender\deploy.prototxt”,

base + “gender\gender_net.caffemodel”);

new PreviewCameraWithGenderAge(detectService).action(1000);

}

  • 主程序已经写完,接下来是核心功能

编码:服务接口回顾

  • 本篇的核心功能是检测性别,相关代码被封装在DetectService接口的实现类GenderDetectService中,这个DetectService接口是咱们的老朋友了,之前识别相关的实战都有它的身影,再来回顾一下,如下,定义了初始化、处理原始帧、释放资源等关键行为的接口:

package com.bolingcavalry.grabpush.extend;

public interface DetectService {

/**

  • 根据传入的MAT构造相同尺寸的MAT,存放灰度图片用于以后的检测

  • @param src 原始图片的MAT对象

  • @return 相同尺寸的灰度图片的MAT对象

*/

static Mat buildGrayImage(Mat src) {

return new Mat(src.rows(), src.cols(), CV_8UC1);

}

/**

  • 初始化操作,例如模型下载

  • @throws Exception

*/

void init() throws Exception;

/**

  • 得到原始帧,做识别,添加框选

  • @param frame

  • @return

*/

Frame convert(Frame frame);

/**

  • 释放资源

*/

void releaseOutputResource();

}

  • 接下来,就是DetectService接口的实现类,也就是今天实战的核心:GenderDetectService.java

编码:检测服务实现

  • 今天的核心功能都集中在GenderDetectService.java中,直接贴出全部源码吧,有几处要注意的地方稍后会提到:

package com.bolingcavalry.grabpush.extend;

import com.bolingcavalry.grabpush.Constants;

import lombok.extern.slf4j.Slf4j;

import org.bytedeco.javacpp.indexer.Indexer;

import org.bytedeco.javacv.Frame;

import org.bytedeco.javacv.OpenCVFrameConverter;

import org.bytedeco.opencv.opencv_core.*;

import org.bytedeco.opencv.opencv_dnn.Net;

import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;

import static org.bytedeco.opencv.global.opencv_core.NORM_MINMAX;

import static org.bytedeco.opencv.global.opencv_core.normalize;

import static org.bytedeco.opencv.global.opencv_dnn.blobFromImage;

import static org.bytedeco.opencv.global.opencv_dnn.readNetFromCaffe;

import static org.bytedeco.opencv.global.opencv_imgproc.*;

/**

  • @author willzhao

  • @version 1.0

  • @description 音频相关的服务

  • @date 2021/12/3 8:09

*/

@Slf4j

public class GenderDetectService implements DetectService {

/**

  • 每一帧原始图片的对象

*/

private Mat grabbedImage = null;

/**

  • 原始图片对应的灰度图片对象

*/

private Mat grayImage = null;

/**

  • 分类器

*/

private CascadeClassifier classifier;

/**

  • 转换器

*/

private OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat();

/**

  • 人脸检测模型文件的下载地址

*/

private String classifierModelFilePath;

/**

  • 性别识别proto文件的下载地址

*/

private String genderProtoFilePath;

/**

  • 性别识别模型文件的下载地址

*/

private String genderModelFilePath;

/**

  • 推理性别的神经网络对象

*/

private Net cnnNet;

/**

  • 构造方法,在此指定proto和模型文件的下载地址

  • @param classifierModelFilePath

  • @param cnnProtoFilePath

  • @param cnnModelFilePath

*/

public GenderDetectService(String classifierModelFilePath,

String cnnProtoFilePath,

String cnnModelFilePath) {

this.classifierModelFilePath = classifierModelFilePath;

this.genderProtoFilePath = cnnProtoFilePath;

this.genderModelFilePath = cnnModelFilePath;

}

/**

  • 初始化操作,主要是创建推理用的神经网络

  • @throws Exception

*/

@Override

public void init() throws Exception {

// 根据模型文件实例化分类器

classifier = new CascadeClassifier(classifierModelFilePath);

// 实例化推理性别的神经网络

cnnNet = readNetFromCaffe(genderProtoFilePath, genderModelFilePath);

}

@Override

public Frame convert(Frame frame) {

// 由帧转为Mat

grabbedImage = converter.convert(frame);

// 灰度Mat,用于检测

if (null==grayImage) {

grayImage = DetectService.buildGrayImage(grabbedImage);

}

// 当前图片转为灰度图片

cvtColor(grabbedImage, grayImage, CV_BGR2GRAY);

// 存放检测结果的容器

RectVector objects = new RectVector();

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

知其然不知其所以然,大厂常问面试技术如何复习?

1、热门面试题及答案大全

面试前做足功夫,让你面试成功率提升一截,这里一份热门350道一线互联网常问面试题及答案助你拿offer

2、多线程、高并发、缓存入门到实战项目pdf书籍

3、文中提到面试题答案整理

4、Java核心知识面试宝典

覆盖了JVM 、JAVA集合、JAVA多线程并发、JAVA基础、Spring原理、微服务、Netty与RPC、网络、日志、Zookeeper、Kafka、RabbitMQ、Hbase、MongoDB 、Cassandra、设计模式、负载均衡、数据库、一致性算法 、JAVA算法、数据结构、算法、分布式缓存、Hadoop、Spark、Storm的大量技术点且讲解的非常深入

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

g-22YBidnK-1712790332354)]

3、文中提到面试题答案整理

[外链图片转存中…(img-DBdHeAAd-1712790332354)]

4、Java核心知识面试宝典

覆盖了JVM 、JAVA集合、JAVA多线程并发、JAVA基础、Spring原理、微服务、Netty与RPC、网络、日志、Zookeeper、Kafka、RabbitMQ、Hbase、MongoDB 、Cassandra、设计模式、负载均衡、数据库、一致性算法 、JAVA算法、数据结构、算法、分布式缓存、Hadoop、Spark、Storm的大量技术点且讲解的非常深入

[外链图片转存中…(img-q5LVd9SU-1712790332354)]

[外链图片转存中…(img-5EoCug57-1712790332354)]

[外链图片转存中…(img-tQ7BzUYg-1712790332355)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-YjE6ecVB-1712790332355)]

  • 23
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值