Django摄像头人脸采集识别报错及人脸框选功能实现问询
解决方案
一、解决「TypeError: Object of type bytes is not JSON serializable」错误
这个错误核心是视图中尝试用JsonResponse返回字节类型数据,而JSON仅支持字符串、数字、数组、对象等可序列化类型。解决思路是将图片数据转为Base64字符串传输:
1. 前端调整:将摄像头帧转为Base64字符串发送
修改JS代码,把canvas捕获的帧转为Base64格式(去掉data:image/jpeg;base64,前缀)后发送给后端:
// 采集摄像头帧并发送 function captureFrame() { const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const video = document.getElementById('video'); ctx.drawImage(video, 0, 0, canvas.width, canvas.height); // 转为Base64并去掉前缀 const imageData = canvas.toDataURL('image/jpeg').split(',')[1]; fetch('/recognize/', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': getCsrfToken() }, body: JSON.stringify({image: imageData}) }) .then(response => response.json()) .then(data => displayResult(data)); } // 获取CSRF令牌 function getCsrfToken() { return document.querySelector('[name=csrfmiddlewaretoken]').value; }
2. 后端视图调整:解码Base64并返回Base64格式的处理后图片
修改Django视图,接收Base64字符串解码为字节处理,再将处理后的图片转为Base64返回:
import base64 import cv2 import numpy as np from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt @csrf_exempt def recognize_face(request): if request.method == 'POST': image_data = request.json.get('image') if not image_data: return JsonResponse({'error': '未接收到图片数据'}, status=400) # 解码Base64为字节 img_bytes = base64.b64decode(image_data) nparr = np.frombuffer(img_bytes, np.uint8) img = cv2.imdecode(nparr, cv2.IMREAD_COLOR) # 调用人脸识别类处理 fr = FaceRecognition() result_img, message = fr.detect_and_draw_face(img) # 将处理后的图片转为Base64 _, buffer = cv2.imencode('.jpg', result_img) img_base64 = base64.b64encode(buffer).decode('utf-8') return JsonResponse({ 'processed_image': img_base64, 'message': message }) return JsonResponse({'error': '请求方法无效'}, status=405)
3. 调整FaceRecognition类的处理方法
确保类方法接收OpenCV格式图片,绘制人脸框后返回处理后的图片和提示信息:
import cv2 class FaceRecognition: def __init__(self): self.face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') def detect_and_draw_face(self, img): gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = self.face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)) message = "未检测到人脸" if len(faces) > 0: message = f"检测到{len(faces)}张人脸" # 绘制绿色人脸框 for (x, y, w, h) in faces: cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) return img, message
二、实现人脸框绘制与采集提示功能
1. 前端HTML结构
添加视频、画布、结果展示元素:
<!DOCTYPE html> <html> <head> <title>人脸采集识别</title> </head> <body> <video id="video" width="640" height="480" autoplay></video> <canvas id="canvas" width="640" height="480" style="display: none;"></canvas> <div id="result-area"> <img id="processed-img" src="" alt="处理后的图片"> <p id="tip-text"></p> </div> <button onclick="startCamera()">开启摄像头</button> <button onclick="captureFrame()">采集识别</button> {% csrf_token %} <script> // 插入之前的JS代码 </script> </body> </html>
2. 前端添加摄像头初始化与结果展示函数
在JS中补充以下代码:
// 开启摄像头 function startCamera() { navigator.mediaDevices.getUserMedia({ video: true }) .then(stream => { document.getElementById('video').srcObject = stream; }) .catch(err => { console.error('摄像头开启失败:', err); alert('无法访问摄像头,请检查权限设置'); }); } // 展示处理结果 function displayResult(data) { const imgEl = document.getElementById('processed-img'); const tipEl = document.getElementById('tip-text'); imgEl.src = `data:image/jpeg;base64,${data.processed_image}`; tipEl.textContent = data.message; }
关键注意事项
- CSRF验证:Django默认开启CSRF保护,必须确保HTML中存在
{% csrf_token %}标签,请求携带令牌。 - 性能控制:若需实时识别,可设置定时器(如每500ms发送一次请求),避免高频请求压垮后端。
- 浏览器兼容性:
getUserMediaAPI需在HTTPS环境下使用(本地http://localhost除外),确保用户浏览器支持该API。
内容的提问来源于stack exchange,提问作者André Pimentel
相关产品推荐
相关产品推荐

