【问题标题】:Make faster videocapture opencv制作更快的视频捕获opencv
【发布时间】:2021-07-03 16:32:22
【问题描述】:

所以我创建了一个神经网络 (CNN),可以使用 opencv 实时预测一个人的性别,一切正常,但是,当我运行代码时,OpenCv 有很多延迟,我的网络摄像头还不错,这是我的代码

    '''
Real-time Face Gender Recognition using Conv-Nueral Network (CNN) and Cv2

Here we predict the save model that it is train
'''
from tensorflow.keras.preprocessing.image import img_to_array
from tensorflow.keras.models import load_model
import numpy as np
import cv2
import os
import cvlib as cv
import imutils

# load the model
model = load_model('gender_detection.model')

# open webcams and initiate the camara
webcam = cv2.VideoCapture(0, cv2.CAP_DSHOW)

classes = ['hombre', 'mujer']

# loop through frames
while webcam.isOpened():
    # read frame from webcam
    status, frame = webcam.read()
    #webcam.set(cv2.CAP_PROP_FPS, 1000)
    frame = cv2.flip(frame, 1)

    # apply face detection
    face, confidence = cv.detect_face(frame) # this detects that there is a face in the camara, cvlib does, but not if it is a man that detects the neural network

    # loop through detected faces
    for idx, f in enumerate(face):
        # get corner points of face rectangle
        # this only will draw a rectangle when the cvlib detects the face with the vars giving up there
        startX, startY = f[0], f[1]
        endX, endY = f[2], f[3]

        # draw the rectangle over the face
        cv2.rectangle(frame, (startX, startY), (endX, endY), (0,255,0), 2)

        # crop the detected face region
        face_crop = np.copy(frame[startY:endY, startX:endX])

        if face_crop.shape[0] < 10 or face_crop.shape[1] < 10:
            continue

        # preprocessing for gender detection model
        face_crop = cv2.resize(face_crop, (96,96))
        face_crop = face_crop.astype("float") / 255.0
        face_crop = img_to_array(face_crop)
        face_crop = np.expand_dims(face_crop, axis=0)

        # apply gender detection face with the model
        conf = model.predict(face_crop)[0]

        # get label with max acc
        idx = np.argmax(conf)
        label = classes[idx]

        label = "{}: {:.2f}".format(label, conf[idx] * 100)

        Y = startY - 10 if startY - 10 > 10 else startY + 10

        # write label and confidence above the face rectangle
        cv2.putText(frame, label, (startX, Y), cv2.FONT_HERSHEY_SIMPLEX,
                    0.7, (0,255,0), 2)

    # display output
    cv2.imshow("Gender Detection", frame)

    # press "Q" to stop
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break


#realese resources
webcam.release()
cv2.destroyAllWindows()

我也尝试使用 cv2.CAP_PROB_FPS 但这只是一点点帮助,没有多大帮助。

【问题讨论】:

  • 推理需要多长时间?
  • @Christoph Rackwitz 我该如何检查,或者那是什么?
  • 在代码的不同位置获取time.time(),这样您就可以看到每个步骤需要多长时间。我猜面部识别是你的时间发生的地方
  • @TimRoberts 我试了一下,所有部分都是一样的,但是当我的脸的绿色方块在opencv中没有出现(遮住我的脸)时,它变得更快,不是很快但更快
  • 2 wffectstcan 发生:1. 你的处理速度很慢(如果你需要处理,你不能删除它)。 2.您的处理速度很慢,并且视频捕获提供了旧帧。您可以通过多线程捕获来改善这一点,并且只将最新的帧提供给处理。这里的问题是:例如,如果相机提供 25 fps 并且 videocapture 具有 4 帧的缓冲区并且处理具有 1 fps,那么您将获得 4 秒而不是 1 秒的延迟。

标签: python opencv machine-learning


【解决方案1】:

我在使用带有文本检测的 openCV 视频捕获时遇到了同样的问题。这不是网络摄像头的质量,而是 openCV 只能以尽可能快的速度向您显示帧,因为您可以在性别检测中处理它们。对我有用的解决方案是使用多线程。

您可以为 OpenCV 视频捕获创建一个线程,然后为您的图像处理创建另一个线程。需要注意的是:如果不对图像处理本身进行更改,就无法神奇地让图像处理更快地发生。只要需要就需要。您可以做的是让 openCV 自行工作并将帧发送到交换类,然后允许图像处理抓取帧并在 CV2 继续正常运行时以自己的速度工作。

这是我的 OCR 图像处理课程的(缩短的)版本。您可以在 start() 中看到我正在创建一个指向 ocr() 进程的线程。这是您的性别识别过程可以进行的地方。

class OCR:

    # def __init__(self, exchange: VideoStream, language=None):
    def __init__(self):
        self.exchange = None
        # init stuff for OCR not relevant to my example, but note that it 
        # takes a VideoStream class called exchange which is where this class 
        # grabs frames to process

    def start(self):
        Thread(target=self.ocr, args=()).start()
        return self

    def set_exchange(self, video_stream):
        self.exchange = video_stream

    def ocr(self):

        while not self.stopped:
            if self.exchange is not None:
                frame = self.exchange.frame

                # # # OCR stuff goes here

现在这里是 VideoStream 类,它以自己的节奏在不同的线程中抓取帧。然后,图像处理类 (OCR) 可以按照自己的节奏处理这些帧,并且两者不会影响彼此的性能。

class VideoStream:
    """Class for CV2 video capture. The start() method will create a new 
thread to read the video stream"""
    def __init__(self, src=0):
        self.stream = cv2.VideoCapture(src)
        (self.grabbed, self.frame) = self.stream.read()
        # self._boxes = None
        self.stopped = False

    def start(self):
        Thread(target=self.get, args=()).start()
        return self

    def get(self):
        while not self.stopped:
            (self.grabbed, self.frame) = self.stream.read()

    def get_video_dimensions(self):
        width = self.stream.get(cv2.CAP_PROP_FRAME_WIDTH)
        height = self.stream.get(cv2.CAP_PROP_FRAME_HEIGHT)
        return int(width), int(height)

    def stop_process(self):
        self.stopped = True

然后您可以像往常一样执行 CV2 imshow 循环。

exchange = VideoStream(0).start()
ocr = OCR().start()
ocr.set_exchange(exchange)

 while True:  # Begins a loop for the real-time OCR display
        pressed_key = cv2.waitKey(1) & 0xFF
        if pressed_key == ord('q'):
            stop_stream_ocr(exchange, ocr)
            break

        frame = exchange.frame 

        cv2.imshow("Video Get Frame", frame)
        cps1.increment()

请注意,您无法真正控制 CV2 决定在其内部工作中使用哪个线程,但这种方法将允许您以自然 fps 显示您的网络摄像头,同时在后台进行图像处理。

【讨论】:

  • 嗨,我认为这是解决方案,但我怎样才能将它应用到我的代码中?
  • 您可以像我展示的那样将代码分成类。一类是针对在 CV2 框架上执行的性别识别,我称之为 OCR,因为这就是我在写这篇文章时所做的。第二类将用于视频捕获,在您的情况下应该不会有太大差异。然后你可以在主循环中将这两个进程联系在一起,就像我在底部显示的那样。
  • ... 如果您以前从未在类中使用过多线程,这有点令人生畏。我计划很快(在接下来的一两天内)将所有这些代码放到 github 上,希望您可以运行它并对其中的大部分进行逆向工程以供您自己使用。
  • 是的,不太确定为什么这个问题被否决了。这是人们在使用 CV2 imshow() 时遇到的一个非常普遍的问题,而且解决方案并不十分明显。
  • @Rodrigo 在那里回答。如果不在我的机器上设置您的项目,我无法真正深入了解它。如果你想在 github 上发布它,如果我能修复它,我很乐意提出推送请求。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-09
  • 1970-01-01
  • 2022-11-02
  • 1970-01-01
  • 2016-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多