如何在Python Django中将OpenCV输出推送到浏览器网页应用?
如何将OpenCV处理后的摄像头画面集成到网页中
Hey there! 看你已经搞定了本地的OpenCV人脸识别功能,现在要把这个带识别效果的摄像头画面放到网页里对吧?其实核心思路就是把OpenCV处理后的视频帧转换成可被网页接收的流格式,通过Web服务器推送给前端。下面我给你两种简单易上手的实现方案,都是基于Python后端的:
方案一:用Flask搭建轻量视频流服务
Flask是个简单的Python Web框架,适合快速搭建这类小服务:
- 先安装Flask:
pip install flask
- 把你原有的OpenCV代码修改成Flask服务形式,替换掉本地显示的逻辑,改成生成视频流:
import numpy as np import cv2 import pickle from flask import Flask, Response app = Flask(__name__) # 初始化你的人脸识别组件 face_cascade = cv2.CascadeClassifier('Cascades/data/haarcascade_frontalface_alt2.xml') eye_cascade = cv2.CascadeClassifier('Cascades/data/haarcascade_eye.xml') recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.read("trainer.yml") labels = {"person_name": 1} with open("labels.pickle", 'rb') as f: orig_labels = pickle.load(f) labels = {v:k for k,v in orig_labels.items()} cap = cv2.VideoCapture(0) def generate_frames(): """生成处理后的视频帧流""" while True: ret, frame = cap.read() if not ret: break # 你的人脸识别逻辑(和原代码一致) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, scaleFactor=1.5, minNeighbors=5) for (x, y, w, h) in faces: roi_gray = gray[y:y+h, x:x+w] roi_color = frame[y:y+h, x:x+w] id_, confidence = recognizer.predict(roi_gray) if confidence >= 45 and confidence <= 85: font = cv2.FONT_HERSHEY_SIMPLEX color = (255, 255, 255) name = labels[id_] stroke = 2 cv2.putText(frame, name, (x,y), font, 1, color, stroke, cv2.LINE_AA) color = (0, 255, 255) # BGR格式 stroke = 2 width = x + w height = y + h cv2.rectangle(frame, (x, y), (width, height), color, stroke) eyes = eye_cascade.detectMultiScale(roi_gray) for(ex,ey, ew, eh) in eyes: cv2.rectangle(roi_color, (ex,ey), (ex+ew, ey+eh), (0, 255, 0), 2) # 将帧编码为JPEG格式,用于MJPEG流传输 ret, buffer = cv2.imencode('.jpg', frame) frame = buffer.tobytes() # 按照MJPEG流的格式返回帧 yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n') # 视频流接口 @app.route('/video_feed') def video_feed(): return Response(generate_frames(), mimetype='multipart/x-mixed-replace; boundary=frame') # 主页,返回显示视频流的HTML页面 @app.route('/') def index(): return ''' <html> <head> <title>APS Recognition</title> </head> <body> <h1>APS Face Recognition</h1> <img src="/video_feed" style="max-width: 800px;"> </body> </html> ''' if __name__ == '__main__': try: app.run(debug=True) finally: # 程序结束时释放摄像头 cap.release()
- 运行脚本,然后打开浏览器访问
http://localhost:5000,就能看到带人脸识别标记的摄像头画面了!
方案二:用FastAPI搭建高性能异步服务
如果你更喜欢现代的异步Web框架,FastAPI是个不错的选择,性能会更好一些:
- 安装依赖:
pip install fastapi uvicorn
- 修改后的代码:
import numpy as np import cv2 import pickle from fastapi import FastAPI, Response from fastapi.responses import HTMLResponse app = FastAPI() # 初始化人脸识别组件 face_cascade = cv2.CascadeClassifier('Cascades/data/haarcascade_frontalface_alt2.xml') eye_cascade = cv2.CascadeClassifier('Cascades/data/haarcascade_eye.xml') recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.read("trainer.yml") labels = {"person_name": 1} with open("labels.pickle", 'rb') as f: orig_labels = pickle.load(f) labels = {v:k for k,v in orig_labels.items()} cap = cv2.VideoCapture(0) def generate_frames(): while True: ret, frame = cap.read() if not ret: break # 你的人脸识别逻辑 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, scaleFactor=1.5, minNeighbors=5) for (x, y, w, h) in faces: roi_gray = gray[y:y+h, x:x+w] roi_color = frame[y:y+h, x:x+w] id_, confidence = recognizer.predict(roi_gray) if confidence >= 45 and confidence <= 85: font = cv2.FONT_HERSHEY_SIMPLEX color = (255, 255, 255) name = labels[id_] stroke = 2 cv2.putText(frame, name, (x,y), font, 1, color, stroke, cv2.LINE_AA) color = (0, 255, 255) # BGR格式 stroke = 2 width = x + w height = y + h cv2.rectangle(frame, (x, y), (width, height), color, stroke) eyes = eye_cascade.detectMultiScale(roi_gray) for(ex,ey, ew, eh) in eyes: cv2.rectangle(roi_color, (ex,ey), (ex+ew, ey+eh), (0, 255, 0), 2) ret, buffer = cv2.imencode('.jpg', frame) frame = buffer.tobytes() yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n') @app.get("/video_feed") async def video_feed(): return Response(generate_frames(), media_type="multipart/x-mixed-replace; boundary=frame") @app.get("/", response_class=HTMLResponse) async def root(): return """ <html> <head> <title>APS Recognition</title> </head> <body> <h1>APS Face Recognition</h1> <img src="/video_feed" style="max-width: 800px;"> </body> </html> """ # 程序关闭时释放摄像头 @app.on_event("shutdown") def shutdown_event(): cap.release()
- 运行服务:
uvicorn main:app --reload
然后访问 http://localhost:8000 就能看到效果啦。
一些注意事项
- 确保你的
Cascades文件夹、trainer.yml、labels.pickle和脚本在同一个目录下,不然要修改代码里的文件路径 - 如果是部署到远程服务器,需要服务器有可用的摄像头权限;如果是让用户在本地运行后端,就能直接调用用户自己的摄像头
- MJPEG流的延迟相对会高一点,如果追求更低延迟,可以考虑用WebSocket传输帧,但MJPEG是最容易实现的方案,适合快速验证功能
内容的提问来源于stack exchange,提问作者eden10
相关产品推荐
相关产品推荐

