You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV为摄像头流添加掩码后Web端直播流启动即停止问题求助

问题根因

  1. color_detection函数处理完第一帧后直接执行return,函数直接终止,仅能返回1张处理后的图片,无法持续生成后续视频帧。
  2. views.py中的gen生成器仅接收单张固定帧,循环返回同一张图片,没有更新帧的逻辑。
  3. seasoncolor视图中的while True循环无实际作用,第一行就执行return返回响应,不会循环拉取新帧。
  4. 原代码仅在检测到人脸时才返回帧,未检测到人脸的场景下无内容返回,会导致流中断。

修复代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 08:54:08