Springboot實現(xiàn)人臉識別與WebSocket長連接的實現(xiàn)代碼
0.什么是WebSocket,由于普通的請求是間斷式發(fā)送的,如果要同一時間發(fā)生大量的請求,必然導(dǎo)致響應(yīng)速度慢(因為根據(jù)tcp協(xié)議要經(jīng)過三層握手,如果不持續(xù)發(fā)送,就會導(dǎo)致n多次握手,關(guān)閉連接,打開連接)
1.業(yè)務(wù)需求: 由于我需要使用java來處理視頻的問題,視頻其實就是圖片,相當(dāng)于每張圖片就是幀,不停發(fā)送幀去實現(xiàn)人臉失敗,然后返回處理結(jié)果,(支付寶刷臉支付也是同樣的道理)
2.前端建立WebSocket()對象,onMessage函數(shù)監(jiān)聽返回的結(jié)果
<!DOCTYPE html>
<html>
<head>
<title>視頻幀捕獲</title>
</head>
<body>
<video id="videoElement" autoplay></video>
<canvas id="canvasElement" style="display: none;"></canvas>
<script>
//如果是https協(xié)議的話,就需要改為 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秒發(fā)送一次視頻幀數(shù)據(jù),必須要在這里寫定時器,因為打開連接后才能發(fā)送請求,不然每次都會報Websocket close的錯誤
setInterval(captureFrame,10000)
};
socket.onmessage = function(event) {
var result = event.data;
// 處理服務(wù)器返回的結(jié)果
console.log(result);//打印出結(jié)果
};
socket.onclose = function(event) {
console.log("WebSocket已關(guān)閉");
};
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);
// 將數(shù)據(jù)URL發(fā)送到WebSocket服務(wù)器
}
// 每隔一段時間捕獲一幀并發(fā)送到Servlet
</script>
</body>
</html>3.后端寫配置類,配置websocket的路徑
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//錄入人臉數(shù)據(jù)頁面
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 {
// 讀取字節(jié)數(shù)組并返回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對象進(jìn)行其他操作
} else {
System.out.println("無法讀取圖像");
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("無效的base64數(shù)據(jù)");
}
}
// 根據(jù)接收到的文本消息進(jìn)行相應(yīng)的處理
}//人臉檢測的控制器
@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 {
// 讀取字節(jié)數(shù)組并返回BufferedImage對象
ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes);
BufferedImage bufferedImage = ImageIO.read(bis);
if (bufferedImage != null) {
FaceEngineService.loadAllFaceFeature();
FaceFeature faceFeature = FaceEngineService.getFaceFeature(bufferedImage);
// 獲取當(dāng)前幀中出現(xiàn)的人臉對應(yīng)的特征碼
String code = FaceEngineService.detectFace(faceFeature);
System.out.println(code);
if (code != null) {// 如果特征碼不為null,表明畫面中存在某員工的人臉
Employee e = HRService.getEmp(code);// 根據(jù)特征碼獲取員工對象
HRService.addClockInRecord(e);// 為此員工添加打卡記錄
// 文本域添加提示信息
session.sendMessage(new TextMessage("打卡成功"));
}
// 在這里可以對BufferedImage對象進(jìn)行其他操作
} else {
session.sendMessage(new TextMessage("打卡成功"));
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("無效的base64數(shù)據(jù)");
}
}
// 根據(jù)接收到的文本消息進(jìn)行相應(yīng)的處理
}到此這篇關(guān)于Springboot實現(xiàn)人臉識別與WebSocket長連接的實現(xiàn)的文章就介紹到這了,更多相關(guān)Springboot WebSocket長連接內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java+selenium 網(wǎng)易云音樂刷累計聽歌數(shù)的方法
這篇文章主要介紹了java+selenium 網(wǎng)易云音樂刷累計聽歌數(shù)的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
mybatis的xml中使用@符號調(diào)用類方法示例
這篇文章主要為大家介紹了mybatis的xml中使用@符號調(diào)用類方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
java.lang.AbstractMethodError: org.apache.xerces.dom.Documen
這篇文章主要介紹了java.lang.AbstractMethodError: org.apache.xerces.dom.DocumentImpl.setXmlVersion問題解決方法,導(dǎo)致本文問題的原因是缺少一個xerces.jar jar包,需要的朋友可以參考下2015-03-03
java利用delayedQueue實現(xiàn)本地的延遲隊列
這篇文章主要給大家介紹了java利用delayedQueue實現(xiàn)本地的延遲隊列的相關(guān)資料,文中介紹的非常詳細(xì),相信對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-04-04
java控制臺實現(xiàn)學(xué)生信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java控制臺實現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02
關(guān)于springboot使用rocketmq?RocketMQMessageListener參數(shù)問題
這篇文章主要介紹了springboot使用rocketmq?RocketMQMessageListener參數(shù)問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值需要的朋友可以參考下2022-11-11

