Springboot实现人脸识别与WebSocket长连接的实现-CSDN博客
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
0.什么是WebSocket,由于普通的请求是间断式发送的,如果要同一时间发生大量的请求,必然导致响应速度慢(因为根据tcp协议要经过三层握手,如果不持续发送,就会导致n多次握手,关闭连接,打开连接)
1.业务需求: 由于我需要使用java来处理视频的问题,视频其实就是图片,相当于每张图片就是帧,不停发送帧去实现人脸失败,然后返回处理结果,(支付宝刷脸支付也是同样的道理)
2.前端建立WebSocket()对象,onMessage函数监听返回的结果
<!DOCTYPE html>
<html>
<head>
<title>视频帧捕获</title>
</head>
<body>
<video id="videoElement" autoplay></video>
<canvas id="canvasElement" style="display: none;"></canvas>
<script>
//如果是https协议的话,就需要改为 wss
var socket = new WebSocket("ws://localhost:8080/facedetect");
const video = document.getElementById('videoElement');
const canvas = document.getElementById('canvasElement');
const context = canvas.getContext('2d');
socket.onopen = function() {
console.log("xxxx");
// 每1秒发送一次视频帧数据,必须要在这里写定时器,因为打开连接后才能发送请求,不然每次都会报Websocket close的错误
setInterval(captureFrame,10000)
};
socket.onmessage = function(event) {
var result = event.data;
// 处理服务器返回的结果
console.log(result);//打印出结果
};
socket.onclose = function(event) {
console.log("WebSocket已关闭");
};
socket.onerror = function(event) {
console.error('WebSocket错误:', event);
};
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {
video.srcObject = stream;
})
.catch(error => {
console.error('无法访问摄像头:', error);
});
function captureFrame() {
context.drawImage(video, 0, 0, canvas.width, canvas.height);
const imageDataUrl = canvas.toDataURL('image/jpeg', 0.5);
console.log(imageDataUrl)
socket.send(imageDataUrl);
// 将数据URL发送到WebSocket服务器
}
// 每隔一段时间捕获一帧并发送到Servlet
</script>
</body>
</html>
3.后端写配置类,配置websocket的路径
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//录入人脸数据页面
registry.addHandler(myHandler(), "/face").setAllowedOrigins("*");
//人脸识别页面
registry.addHandler(myHandler1(), "/facedetect").setAllowedOrigins("*");
}
@Bean
public WebSocketHandler myHandler() {
return new FaceController();
}
@Bean
public WebSocketHandler myHandler1() {
return new FaceController1();
}
}
4.写controller
//人脸录入的controller
@Controller
@RequestMapping("/face")
@CrossOrigin
public class FaceController extends TextWebSocketHandler {
private WebSocketSession session;
// 处理WebSocket连接请求
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("WebSocket连接已建立");
// 保存WebSocket会话
this.session = session;
}
// 处理WebSocket文本消息
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String text = message.getPayload();
System.out.println(text);
text = text.replaceFirst("^data:image/[^;]+;base64,?\\s*", "");
text = text.replaceAll("[^A-Za-z0-9+/=]", "");
System.out.println(text);
byte[] imageBytes = Base64.getDecoder().decode(text);
if (imageBytes != null) {
try {
// 读取字节数组并返回BufferedImage对象
ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes);
BufferedImage bufferedImage = ImageIO.read(bis);
if (bufferedImage != null) {
// 示例显示图像宽度和高度
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
System.out.println("图像宽度" + width);
System.out.println("图像高度" + height);
//录入人脸
Employee e1 = HRService.addEmp(UUID.randomUUID().toString().substring(0,10), bufferedImage);
ImageService.saveFaceImage(bufferedImage, e1.getCode());// 保存员工照片文件
System.out.println(e1.getCode());
// 在这里可以对BufferedImage对象进行其他操作
} else {
System.out.println("无法读取图像");
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("无效的base64数据");
}
}
// 根据接收到的文本消息进行相应的处理
}
//人脸检测的控制器
@Controller
@RequestMapping("/facedetect")
@CrossOrigin
public class FaceController1 extends TextWebSocketHandler {
private WebSocketSession session;
// 处理WebSocket连接请求
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("WebSocket连接已建立");
// 保存WebSocket会话
this.session = session;
}
// 处理WebSocket文本消息
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println("detect");
String text = message.getPayload();
System.out.println(text);
text = text.replaceFirst("^data:image/[^;]+;base64,?\\s*", "");
text = text.replaceAll("[^A-Za-z0-9+/=]", "");
System.out.println(text);
byte[] imageBytes = Base64.getDecoder().decode(text);
if (imageBytes != null) {
try {
// 读取字节数组并返回BufferedImage对象
ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes);
BufferedImage bufferedImage = ImageIO.read(bis);
if (bufferedImage != null) {
FaceEngineService.loadAllFaceFeature();
FaceFeature faceFeature = FaceEngineService.getFaceFeature(bufferedImage);
// 获取当前帧中出现的人脸对应的特征码
String code = FaceEngineService.detectFace(faceFeature);
System.out.println(code);
if (code != null) {// 如果特征码不为null表明画面中存在某员工的人脸
Employee e = HRService.getEmp(code);// 根据特征码获取员工对象
HRService.addClockInRecord(e);// 为此员工添加打卡记录
// 文本域添加提示信息
session.sendMessage(new TextMessage("打卡成功"));
}
// 在这里可以对BufferedImage对象进行其他操作
} else {
session.sendMessage(new TextMessage("打卡成功"));
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("无效的base64数据");
}
}
// 根据接收到的文本消息进行相应的处理
}
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |