基于WebSocket和FastAPI实现实时人脸检测系统
立即解锁
发布时间: 2025-08-31 02:11:16 阅读量: 468 订阅数: 34 AIGC 


FastAPI构建高效ML应用
# 基于 WebSocket 和 FastAPI 实现实时人脸检测系统
## 1. WebSocket 实现与图像流发送
### 1.1 WebSocket 实现特点
WebSocket 的实现与之前有所不同,这里不希望两个任务并发执行,而是希望接收新图像并在图像传入时持续进行检测。`detect` 函数有自己的无限循环,通过 `create_task` 将其安排在事件循环中,使其开始处理队列中的图像。同时有常规的 WebSocket 循环调用 `receive` 函数,`detect` 可看作在“后台”运行,并且确保在 WebSocket 关闭时取消该任务,以正确停止无限循环。
### 1.2 从浏览器发送图像流
#### 1.2.1 启用相机输入并建立 WebSocket 连接
首先要在浏览器中启用相机输入,打开 WebSocket 连接,选择相机图像并通过 WebSocket 发送。借助 `MediaDevices` 浏览器 API 列出设备上所有可用的相机输入,构建选择表单让用户选择要使用的相机。具体 JavaScript 实现如下:
```javascript
window.addEventListener('DOMContentLoaded', (event) => {
const video = document.getElementById('video');
const canvas = document.getElementById('canvas');
const cameraSelect = document.getElementById('camera-select');
let socket;
// 列出可用相机并填充选择框
navigator.mediaDevices.enumerateDevices().then((devices) => {
for (const device of devices) {
if (device.kind === 'videoinput' && device.deviceId) {
const deviceOption = document.createElement('option');
deviceOption.value = device.deviceId;
deviceOption.innerText = device.label;
cameraSelect.appendChild(deviceOption);
}
}
});
// 提交表单时启动所选相机的人脸检测
document.getElementById('form-connect').addEventListener('submit', (event) => {
event.preventDefault();
// 若之前有连接则关闭
if (socket) {
socket.close();
}
const deviceId = cameraSelect.selectedOptions[0].value;
socket = startFaceDetection(video, canvas, deviceId);
});
});
```
#### 1.2.2 开始捕获视频并显示
用户提交表单后,`MediaDevices` API 允许开始捕获视频并将输出显示在 HTML `<video>` 元素中,详细信息可查看 MDN 文档:https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices 。
#### 1.2.3 建立 WebSocket 连接并发送图像
同时建立与 WebSocket 的连接,连接建立后启动一个重复任务,从视频输入中捕获图像并发送到服务器。使用 `<canvas>` 元素将当前视频图像绘制并转换为有效的 JPEG 字节。具体 JavaScript 实现如下:
```javascript
const startFaceDetection = (video, canvas, deviceId) => {
const socket = new WebSocket('ws://localhost:8000/face-detection');
let intervalId;
// 连接打开
socket.addEventListener('open', function () {
// 开始从设备读取视频
navigator.mediaDevices.getUserMedia({
audio: false,
video: {
deviceId,
width: { max: 640 },
height: { max: 480 },
},
}).then(function (stream) {
video.srcObject = stream;
video.play().then(() => {
// 调整覆盖画布大小以适应视频大小
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
// 每 160 毫秒在 WebSocket 中发送一张图像
intervalId = setInterval(() => {
// 创建一个虚拟画布来绘制当
```
0
0
复制全文
相关推荐







