返回
JavaCV摄像头实战十三:让你的摄像头也会算年龄
后端
2023-12-21 01:23:43
在前面《性别检测》的基础上,修改少量代码,即可实现年龄检测,并且会将检测结果的每一帧输出在预览窗口,产生实时识别的效果。
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_dnn.Net;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import java.io.IOException;
public class AgeDetection {
private static final String MODEL_PATH = "models/age_deploy.prototxt";
private static final String WEIGHTS_PATH = "models/age_net.caffemodel";
private static final String FACE_DETECTOR_PATH = "models/haarcascade_frontalface_default.xml";
public static void main(String[] args) throws IOException, FrameGrabber.Exception {
// 加载模型
Net net = readCaffeModel(MODEL_PATH, WEIGHTS_PATH);
CascadeClassifier faceDetector = new CascadeClassifier(FACE_DETECTOR_PATH);
// 打开摄像头
FrameGrabber grabber = FrameGrabber.createDefault(0);
grabber.start();
// 创建一个窗口来显示视频流
CanvasFrame canvasFrame = new CanvasFrame("摄像头年龄检测");
// 创建一个转换器来将Frame转换为Mat对象
OpenCVFrameConverter converter = new OpenCVFrameConverter.ToMat();
// 无限循环以捕获视频流
while (true) {
// 捕获一帧视频
Frame frame = grabber.grab();
// 将帧转换为Mat对象
Mat mat = converter.convert(frame);
// 检测人脸
MatOfRect faces = new MatOfRect();
faceDetector.detectMultiScale(mat, faces);
// 循环检测到的每张人脸
for (Rect face : faces.toArray()) {
// 提取人脸图像
Mat faceImage = new Mat(mat, face);
// 预处理人脸图像
Mat blob = Dnn.blobFromImage(faceImage, 1.0, new Size(224, 224), new Scalar(78.4263377608, 87.7689143744, 114.895847746));
// 将人脸图像输入模型
net.setInput(blob);
// 预测年龄
Mat output = net.forward();
// 获取预测结果
float[] probabilities = output.ptrFloats(0);
// 找到最大概率对应的年龄组
int maxIndex = 0;
float maxProbability = 0;
for (int i = 0; i < probabilities.length; i++) {
if (probabilities[i] > maxProbability) {
maxIndex = i;
maxProbability = probabilities[i];
}
}
// 将年龄组映射到年龄范围
String ageRange = getAgeRange(maxIndex);
// 在人脸上绘制年龄
Rect rectangle = face;
int x = rectangle.x();
int y = rectangle.y();
int width = rectangle.width();
int height = rectangle.height();
rectangle.x(x + width / 2);
rectangle.y(y - height / 2);
rectangle.width(50);
rectangle.height(20);
Dnn.rectangle(mat, rectangle, new Scalar(0, 255, 0), 2);
// 将年龄添加到人脸上
String text = "Age: " + ageRange;
putText(mat, text, new Point(x + width / 2, y - height / 2 - 5), Font.HERSHEY_SIMPLEX, 0.5, new Scalar(0, 255, 0), 2);
}
// 显示结果
canvasFrame.showImage(converter.convert(mat));
}
// 释放资源
grabber.stop();
canvasFrame.dispose();
}
private static Net readCaffeModel(String modelPath, String weightsPath) throws IOException {
Net net = Dnn.readNetFromCaffe(modelPath, weightsPath);
return net;
}
private static String getAgeRange(int index) {
String[] ageRanges = {"0-2", "4-6", "8-12", "15-20", "25-32", "38-43", "48-53", "60-100"};
return ageRanges[index];
}
}
以上代码的功能是:
- 加载模型。首先,我们需要加载训练好的年龄检测模型。模型包含两个部分:模型结构和模型权重。模型结构定义了模型的网络结构,模型权重包含了训练过程中学习到的参数。
- 打开摄像头。接下来,我们需要打开摄像头以获取视频流。
- 创建一个窗口来显示视频流。我们需要创建一个窗口来显示捕获到的视频流。
- 创建一个转换器来将Frame转换为Mat对象。我们需要创建一个转换器来将Frame对象转换为Mat对象。Mat对象是OpenCV中的一种数据结构,它可以表示图像或视频帧。
- 无限循环以捕获视频流。然后,我们需要进入一个无限循环来捕获视频流。
- 捕获一帧视频。在循环中,我们需要捕获一帧视频。
- 将帧转换为Mat对象。接下来,我们需要将帧转换为Mat对象。
- 检测人脸。然后,我们需要使用人脸检测器检测人脸。
- 循环检测到的每张人脸。对于检测到的每张人脸,我们需要进行以下操作:
- 提取人脸图像。
- 预处理人脸图像。
- 将人脸图像输入模型。
- 预测年龄。
- 获取预测结果。
- 将预测结果映射到年龄范围。
- 在人脸上绘制年龄。
- 显示结果。最后,我们需要将结果显示在窗口中。
通过以上步骤,我们可以实现摄像头年龄检测功能。