python - Flask 被 OpenCV 卡住

标签 python python-3.x opencv flask raspberry-pi

在我目前的 Flask 项目中,我正在尝试流式传输两个实时视频,这听起来很简单。问题是我只有一个视频源(相机)。目的是有两个视频流:一个没有任何修改,一个应用了人脸检测。如果用户想要进行人脸检测,那么通过单击按钮,他的相机 View 将更改为应用了人脸检测的流。如果用户不想拥有它,那么他将看到没有它的流。非常重要的是 - 多个用户可以一次查看流。整个程序适用于 RPi 4B 4gb。
我有一个 CamerasPool 类:

from .CameraHandler import CameraHandler

import cv2

class CamerasPool:
    def __init__(self):
        self.__cameras = []

    def registerCamera(self, id, detection):
        self.__cameras.append(CameraHandler(id, cv2.VideoCapture(0), detection))
        print('Camera registered')

    def getCamWithParameters(self, detection):
        camera = None

        for cam in self.__cameras:
            if cam.getDetectionState() == detection:
                camera = cam
                break

        return camera
和 CamerasHandler 类:
import cv2
from time import sleep

class CameraHandler():
    def __init__(self, id, cam, detectionState):
        self.__id = id
        self.__cam = cam
        self.__current_frame = None
        self.__shouldDetect = detectionState
        print(f'Camera created with id {id} created')

    def __del__(self):
        self.__cam.release()

    def getDetectionState(self):
        return self.__shouldDetect

    def __detectFace(self, img):
        faces, confidences = cv.detect_face(img)

        for face in faces:
            (startX, startY) = face[0], face[1]
            (endX, endY) = face[2], face[3]

            cv2.rectangle(img, (startX, startY), (endX, endY), (0, 255, 0), 2)

        return img

    def __getFrame(self):
        rval, frame = self.__cam.read()

        if rval:
            frame = cv2.resize(frame, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)

            try:
                if self.__shouldDetect:
                    frame = self.__detectFace(frame)
            except:
                print('Face detection exception')

            (flag, encodedImage) = cv2.imencode(".jpg", frame)

            self.__current_frame = bytearray(encodedImage)

    def gen(self):
        while True:
            self.__getFrame()

            yield (b'--frame\r\n'
                b'Content-Type: image/jpeg\r\n\r\n' + self.__current_frame + b'\r\n')
我正在尝试按如下方式创建相机:
# Create two cameras
print('Before cameras creation')
camerasPool = CamerasPool()
print('After cameras pool creation')
camerasPool.registerCamera(0, False)
camerasPool.registerCamera(1, True)
print('Created both cameras')
正如您在 CamerasPool 类中看到的,我正在创建这样的相机对象 self.__cameras.append(CameraHandler(id, cv2.VideoCapture(0), detection)) ,它创建了两个想要访问相同资源的对象 - 相机。
当我启动整个程序时,我可以看到以下输出:
 * Serving Flask app "server/" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://192.168.0.151:7070/ (Press CTRL+C to quit)
 * Restarting with stat
Before cameras creation
After cameras pool creation
 * Debugger is active!
 * Debugger PIN: 196-285-435
Before cameras creation
After cameras pool creation
程序卡住,仅此而已。在输出中,我还应该看到 Camera created with id 0 createdCamera created with id 1 created ,但据我所知它们还没有被创建 - 程序在这个陡峭的地方卡住。
我猜这个问题是因为两个 VideoCapture 对象。有人可以帮我解决这个问题吗?也许其他一些解决方案如何从一台相机获得两个流?
此致,
彼得

最佳答案

你不能实例两个 CamerasPool对象,因为您只有一台相机。但是你可以做的是:

  • 更改CamerasPool的实现以便它成为自己的线程并且不会阻止python应用程序的执行。这个类的目的是简单地从相机读取帧,制作每个帧的副本和put()它们分为两个独立的 queue对象。队列在程序中应该是全局的,以便其他线程可以访问它们,这些线程需要并发运行以处理数据并流式传输它们。
  • 创建新类(class) VideoStream负责get()来自特定的帧 queue ,处理它并流式传输它。处理意味着在将帧流式传输到网络之前您想对帧执行的任何操作:转换为灰度、绘制矩形、检测人脸等。此类还需要在单独的线程中运行,并且构造函数需要接收两个参数:第一个指示它应该使用两个全局队列中的哪一个;第二个参数指示帧在流式传输之前是否应进行处理;

  • 如果您正在寻找有关如何使用多线程从相机检索帧并将它们存储在队列中的代码示例,check this answer ,特别是说:

    How to capture at the closest maximum fps supported by the camera? A threading and queue example.


    请记住,您的应用程序将有 4 个线程:
  • 主线程;
  • 属于CamerasPool的那个;
  • 其他 2 个线程分别来自 VideoStream将被实例化的对象;
  • 关于python - Flask 被 OpenCV 卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62745729/

    相关文章:

    python - 如何更直接地引用函数?

    c++ - CMake如何在VC2010上设置正确的包含路径前缀?

    c++ - OpenCV 的卡尔曼滤波器转换矩阵如何处理运动预测的时间(例如 t 和 t^2)?

    python - 通过 RandomizedLogisticRegression 查找选定的特征

    python - pandas describe函数的统计意义是什么,如何使用?

    python - 在 Python 中,我无法使用 PIL 正确打开一些 png 图像

    django - 使用 django-rest-framework 处理 django 中多个应用程序的权限

    python-3.x - 修复了从PIL图像到OpenCV Mat的低效图像转换

    python - 如何让 get_dummies 工作到位?

    python - 'global' 在 if 语句下如何表现?