OpenCV为摄像头流添加掩码后Web端直播流启动即停止问题求助
问题根因
color_detection函数处理完第一帧后直接执行return,函数直接终止,仅能返回1张处理后的图片,无法持续生成后续视频帧。views.py中的gen生成器仅接收单张固定帧,循环返回同一张图片,没有更新帧的逻辑。seasoncolor视图中的while True循环无实际作用,第一行就执行return返回响应,不会循环拉取新帧。- 原代码仅在检测到人脸时才返回帧,未检测到人脸的场景下无内容返回,会导致流中断。
修复代码
1. 修改color_detection.py
将原返回逻辑改为生成器模式,用yield逐帧返回,不要用return,同时补充未检测到人脸的处理逻辑:
import numpy as np import cv2 import sys def color_detection(season): face_cascade = cv2.CascadeClassifier( 'accounts/personal_color/self_detection/haarcascade_frontalface_default.xml') video = cv2.VideoCapture(1) season = int(season) while True: ret, frame = video.read() if not ret or frame is None or not video.isOpened(): continue gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=6) # 检测到人脸时加掩码 if len(faces) > 0: (x, y, w, h) = faces[0] center_coordinates = x + w // 2, y + h // 2 radius = w // 2 mask = np.zeros(frame.shape[:2], dtype="uint8") cv2.circle(mask, center_coordinates, radius, (255, 255, 255), -1) masked = cv2.bitwise_and(frame, frame, mask=mask) if season ==0: # 春季 masked[np.where((masked == [0, 0, 0]).all(axis=2))] = [121, 131, 248] elif season ==1: # 夏季 masked[np.where((masked==[0,0,0]).all(axis=2))]=[86,30,194] elif season ==2: # 秋季 masked[np.where((masked==[0,0,0]).all(axis=2))]=[30,105,210] else: # 冬季 masked[np.where((masked==[0,0,0]).all(axis=2))]=[31,2,141] frame = masked # 不管有没有检测到人脸,都编码返回当前帧 ret, jpeg = cv2.imencode('.jpg', frame) if ret: yield jpeg.tobytes() # 控制帧率 if cv2.waitKey(30) & 0xff == 27: break video.release() cv2.destroyAllWindows() if __name__ == '__main__': arg = sys.argv[1] for _ in color_detection(arg): pass
2. 修改views.py
调整生成器逻辑,逐帧拉取color_detection的输出封装为流格式:
from django.http import StreamingHttpResponse from rest_framework.decorators import api_view from . import color_detection def gen(season): for frame in color_detection.color_detection(season): yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n') @api_view(['GET']) def seasoncolor(request): return StreamingHttpResponse(gen(0), content_type='multipart/x-mixed-replace; boundary=frame')
3. 修改Self_color_diagnosis.js
给Image组件添加禁用缓存参数,避免前端缓存第一张图片:
import React, { useState, useEffect } from 'react'; import { StyleSheet, Text, View, Image } from 'react-native'; function Self_color_diagnosis({navigation,route}) { return ( <View style={styles.title_container}> <Image style={styles.video} source={{ uri: 'http://localhost:8000/seasoncolor/', cache: 'no-store' // 新增禁用缓存配置 }}/> </View> ); } const styles = StyleSheet.create({ video: { width: 500, height: 500 }, title_container: { flex: 1, justifyContent: 'center' }, }); export default Self_color_diagnosis;
额外注意事项
- 生产环境不要每个请求都初始化一次
VideoCapture,摄像头是独占设备,多用户请求会直接报错,建议单独启一个进程读取摄像头帧,缓存后供所有请求拉取。 - 如果是Django部署在生产环境,不要用默认的runserver,默认服务器不支持流式响应的并发处理,建议用uWSGI或者Gunicorn配合异步worker部署。
内容的提问来源于stack exchange,提问作者Rebecca L
相关产品推荐
相关产品推荐

