首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将掩码应用于opencv中的网络摄像头流

将掩码应用于opencv中的网络摄像头流
EN

Stack Overflow用户
提问于 2021-11-16 16:17:44
回答 1查看 648关注 0票数 0

我使用OpenCV将掩码应用到视频提要中,并希望在网站上显示Live,但是下面的代码一旦启动就停止流。我绞尽脑汁,却想不出解决办法。任何帮助都将不胜感激。

views.py

代码语言:javascript
复制
def gen(frame):
    while True:
        # frame = camera.get_frame()
        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):
    while True:
        return StreamingHttpResponse(gen(color_detection.color_detection(0)),
                    content_type='multipart/x-mixed-replace; boundary=frame')  

color_detection.py

代码语言:javascript
复制
import numpy as np
import cv2
import sys
'''
ML object detection algo(haarcascade)used to identify objects. 
the XML file consists of trained Haar Cascade models.
'''

def color_detection(season):
    face_cascade = cv2.CascadeClassifier(
        'accounts/personal_color/self_detection/haarcascade_frontalface_default.xml')
        # 'accounts/personal_color/self_detection/haarcascade_frontalface_default.xml'
    # initialize video from the webcam
    video = cv2.VideoCapture(1)
    # Spring/summer/fall/winter
    while True:
        # ret tells if the camera works properly. Frame is an actual frame from the video feed
        ret, frame = video.read()
        # make sure port is working and read the image
        if frame is not None and video.isOpened():
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            '''
            Detect the faces within the subregions of the image in scales
            scaleFactor indicates how much the image size is reduced at each image scale.
            minNeighbors: Higher value results in higher quality of the detected face.
            '''
            faces = face_cascade.detectMultiScale(
            gray, scaleFactor=1.1, minNeighbors=6)
            # Draw the rectangle around each face
            for (x, y, w, h) in faces:
                # Use the stcoordinates to find the center of the face and from that point draw a rectangle of radius w/2 or h/2.
                center_coordinates = x + w // 2, y + h // 2
                radius = w // 2  # or can be h / 2 or can be anything based on your requirements
                # background color(black)
                mask = np.zeros(frame.shape[:2], dtype="uint8")
                # Draw the desired region to crop out in white
                cv2.circle(mask, center_coordinates, radius, (255, 255, 255), -1)
                masked = cv2.bitwise_and(frame, frame, mask=mask)
                if int(season) ==0: # Spring
                    # Replace all (0,0,0)channel with Coral pink
                    masked[np.where((masked == [0, 0, 0]).all(axis=2))] = [121, 131, 248]
                elif int(season) ==1: # Summer
                    #Replace all (0,0,0)channel with Rose Red  
                    masked[np.where((masked==[0,0,0]).all(axis=2))]=[86,30,194]
                elif int(season) ==2: # Fall
                    #Replace all (0,0,0)channel with Red Brown /Cinnamon
                    masked[np.where((masked==[0,0,0]).all(axis=2))]=[30,105,210]
                else: # Winter
                    #Replace all (0,0,0)channel with Burgundy Red
                    masked[np.where((masked==[0,0,0]).all(axis=2))]=[31,2,141]
                # cv2.imshow('mask applied', masked)
                ret, jpeg = cv2.imencode('.jpg', masked)
                return jpeg.tobytes()
            if cv2.waitKey(30) & 0xff == 27:
                break

    video.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
     arg = sys.argv[1]
     color_detection(arg)

Self_color_diagnosis.js

代码语言:javascript
复制
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
import CameraScreen from './CameraScreen'; 
import { StyleSheet, Text, View, Image } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import axios from 'axios';

function Self_color_diagnosis({navigation,route}) {
return (
    <View style={styles.title_container}>
    <Image style={styles.video} source={{
        uri: 'http://localhost:8000/seasoncolor/',}}/>
        </View>

);
}

const styles = StyleSheet.create({
    video: {
        width: 500,
        height: 500
    },
    title_container: {
        flex: 1,
        justifyContent: 'center'
      },
  });

export default Self_color_diagnosis;

上面的代码将得到下面的图。流停止,根本不改变。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-11-17 02:14:39

gen()运行循环,一直使用相同的frame()

你必须让frame进入这个循环。

代码语言:javascript
复制
def gen():
    while True:
        frame = color_detection.color_detection(0)
        if frame:
            yield b'--frame\r\nContent-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n'
        #else:
        #    print('no frame')

但是color_detection应该在没有loop的情况下运行。

而且您应该只创建一次VideoCapture(1)

即使你没有发现任何脸,你也应该返回frame

代码语言:javascript
复制
path = os.path.join(cv2.data.haarcascades, 'haarcascade_frontalface_default.xml')
face_cascade = cv2.CascadeClassifier(path)
    
video = cv2.VideoCapture(1)

def color_detection(season):
    # ret tells if the camera works properly. Frame is an actual frame from the video feed
    ret, frame = video.read()
    # make sure port is working and read the image
    if frame is not None and video.isOpened():
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        '''
        Detect the faces within the subregions of the image in scales
        scaleFactor indicates how much the image size is reduced at each image scale.
        minNeighbors: Higher value results in higher quality of the detected face.
        '''
        faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=6)

        # Draw circle around each face
        for (x, y, w, h) in faces:
            # Use the stcoordinates to find the center of the face and from that point draw a rectangle of radius w/2 or h/2.
            center_coordinates = x + w // 2, y + h // 2
            radius = w // 2  # or can be h / 2 or can be anything based on your requirements
            # background color(black)
            mask = np.zeros(frame.shape[:2], dtype="uint8")
            # Draw the desired region to crop out in white
            cv2.circle(mask, center_coordinates, radius, (255, 255, 255), -1)
            masked = cv2.bitwise_and(frame, frame, mask=mask)
            if season == 0: # Spring
                # Replace all (0,0,0)channel with Coral pink
                masked[np.where((masked == [0, 0, 0]).all(axis=2))] = [121, 131, 248]
            elif season == 1: # Summer
                #Replace all (0,0,0)channel with Rose Red  
                masked[np.where((masked==[0,0,0]).all(axis=2))] = [86,30,194]
            elif season == 2: # Fall
                #Replace all (0,0,0)channel with Red Brown /Cinnamon
                masked[np.where((masked==[0,0,0]).all(axis=2))] = [30,105,210]
            else: # Winter
                #Replace all (0,0,0)channel with Burgundy Red
                masked[np.where((masked==[0,0,0]).all(axis=2))] = [31,2,141]
            ret, jpeg = cv2.imencode('.jpg', masked)
        else: # it is `for/else` construction, not `if/else`
            ret, jpeg = cv2.imencode('.jpg', frame)
    
        return jpeg.tobytes()

    #return None

BTW:

我看到了其他的问题。当它检测到多张脸时,它会为每一张脸创建新的面罩,并将每一张面具分配给原始图像--因此每个面具都跳过了以前的面具--所以它应该只显示最后一张脸,并隐藏其他面孔。您应该首先创建一个面罩与所有的圆圈,然后使用它的形象。

编辑:

我不知道您使用的是什么web框架,所以我使用Flask来创建最小的工作示例。

代码语言:javascript
复制
import os
from flask import Flask, Response
import cv2
import numpy as np

app = Flask(__name__)

print('\n'.join(sorted(os.listdir(cv2.data.haarcascades))))
    
path = os.path.join(cv2.data.haarcascades, 'haarcascade_frontalface_default.xml')
face_cascade = cv2.CascadeClassifier(path)
    
#video = cv2.VideoCapture(0)  # my webcam
video = cv2.VideoCapture(0)   # your webcam

def color_detection(season):    
    ret, frame = video.read()

    if frame is not None and video.isOpened():
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=6)

        # test two circles on image 640x480
        #faces = [[100, 100, 250, 250], [640-100-250, 480-100-250, 250, 250]]

        if len(faces) > 0:  # it can be `if faces:` because `faces` is `numpy array` which need different method to check if not empty
            # background color(black)
            mask = np.zeros(frame.shape[:2], dtype="uint8")
            
            # draw all circles on mask
            for (x, y, w, h) in faces:
                #print(x, y, w, h)
                
                # use the coordinates to find the center of the face and from that point draw a rectangle of radius w/2 or h/2.
                center_coordinates = x + w // 2, y + h // 2
                radius = max(w, h) // 2  # or can be h / 2 or can be anything based on your requirements
                
                # draw the desired region to crop out in white
                cv2.circle(mask, center_coordinates, radius, (255, 255, 255), -1)

            # use mask with all circles
            masked = cv2.bitwise_and(frame, frame, mask=mask)
            
            if season == 0: # Spring - Coral pink
                color = [121, 131, 248]
            elif season == 1: # Summer - Rose Red  
                color = [86,30,194]
            elif season == 2: # Fall - Red Brown /Cinnamon
                color = [30,105,210]
            else: # Winter - Burgundy Red
                color = [31,2,141]

            masked[np.where((masked == [0,0,0]).all(axis=2))] = color
        else:  # no faces
            masked = frame
                        
        ret, jpeg = cv2.imencode('.jpg', masked)
        return jpeg.tobytes()
    

def gen():
    while True:
        frame = color_detection(0)
        if frame:
            yield (b'--frame\r\nContent-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
        #else:
        #    print('no frame')
                    
                    
@app.route('/')
def index():
    return '<image src="/seasoncolor">'
                    
@app.route('/seasoncolor')
def seasoncolor():
    return Response(gen(), mimetype='multipart/x-mixed-replace; boundary=frame')
    
    
if __name__ == '__main__':
    #app.debug = True
    app.run()

BTW:

要确保:VideoCapture只能与运行web服务器的本地摄像机一起工作。它不能在用户计算机上与远程摄像机一起工作。只有用户的浏览器才能访问其照相机。要在用户计算机上使用远程摄像机,您必须使用JavaScript在用户浏览器中访问摄像机并将帧发送到服务器--如我在GitHub python-examples浏览器-画布中的网络摄像机-获取图像并上传到服务器中的示例所示。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69992634

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档