简体   繁体   English

OpenCV python 3.7 异步处理 cv2.VideoCapture(0)

[英]OpenCV python 3.7 handle cv2.VideoCapture(0) asynchronously

I am new to python and openCV.我是 python 和 openCV 的新手。 I hope this question makes sense.我希望这个问题是有道理的。 I want to use a asyncio/multithreading in python in order process cv2.VideoCapture(0) in openCV asynchronously.我想在 python 中使用异步/多线程,以便异步处理 openCV 中的 cv2.VideoCapture(0)。

The reason: I can only create one cv2.VideoCapture(0) object and I cannot copy it - as far as I know.原因:据我所知,我只能创建一个 cv2.VideoCapture(0) object 并且无法复制它。 Here the errors I got.这是我得到的错误。

TypeError: cannot pickle 'cv2.VideoCapture' object类型错误:无法腌制“cv2.VideoCapture”object

TypeError: 'cv2.VideoCapture' object is not subscriptable TypeError: 'cv2.VideoCapture' object 不可下标

First I want to show the video capturing by the PCs cam in a window:首先,我想在 window 中展示 PC 摄像头拍摄的视频:

cap = cv2.VideoCapture(0)

def one():
        while cv2.waitKey(1) < 0:
        hasFrame, frame = cap.read()
        cv2.imshow('Capturing1', frame)

While I process the same frames in a different function:虽然我在不同的 function 中处理相同的帧:


def two():
    while cv2.waitKey(1) < 0:
        hasFrame, frame = cap.read()
        frameWidth = frame.shape[1]
        frameHeight = frame.shape[0]

        inpBlob = cv2.dnn.blobFromImage(frame, 1.0 / 255, (inWidth, inHeight),
                                        (0, 0, 0), swapRB=False, crop=False)

        net.setInput(inpBlob)
        output = net.forward()

        H = output.shape[2]
        W = output.shape[3]
        # Empty list to store the detected keypoints
        points = []
        for i in range(nPoints):
            threshold = 0.1
            # confidence map of corresponding body's part.
            probMap = output[0, i, :, :]

            # Find global maxima of the probMap.
            minVal, prob, minLoc, point = cv2.minMaxLoc(probMap)

            # Scale the point to fit on the original image
            x = (frameWidth * point[0]) / W
            y = (frameHeight * point[1]) / H

            if prob > threshold:
                # cv2.circle(frameCopy, (int(x), int(y)), 8, (0, 255, 255), thickness=-1, lineType=cv2.FILLED)
                # cv2.putText(frameCopy, "{}".format(i), (int(x), int(y)), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, lineType=cv2.LINE_AA)

                # Add the point to the list if the probability is greater than the threshold
                points.append((int(x), int(y)))
                print(points)
            else:
                points.append(None)

I want to do this, because the我想这样做,因为

 cv2.imshow('Capturing1', frame)

in def one() is slown down by the code in def two() if I would combine those two functions in one.如果我将这两个函数合二为一,则def one()中的代码会减慢def two()中的代码。

Many thanks for help.非常感谢您的帮助。 I hope it makes sense to you.我希望这对你有意义。

You don't have to copy VideoCapture and probably you couldn't use two copies to read camera because only one VideoCapture can access camera.您不必复制VideoCapture并且可能无法使用两个副本来读取相机,因为只有一个VideoCapture可以访问相机。

You can use threads to run two or more processes at the same time - and because threads share memory so you don't have to use queue or pickle to send frame from one thread to another.您可以使用线程同时运行两个或多个进程 - 因为线程共享 memory 所以您不必使用queuepickle将帧从一个线程发送到另一个线程。

You can create one VideoCapture in main thread and use one thread to read frame and other threads to run few processes which create few frames, but GUI (displayng frame) you have to run in main thread.您可以在主线程中创建一个VideoCapture并使用一个线程来读取帧和其他线程来运行创建少量帧的几个进程,但是您必须在主线程中运行 GUI(显示帧)。

import cv2
import threading
import time

# --- functions ---

def read_frame():
    global has_frame
    global frame

    while running:
        has_frame, frame = cap.read()
        #time.sleep(.1)  # 0.1s to use less CPU

def one():
    global frame1

    while running:
        if has_frame:
            # processing frame
            frame1 = frame.copy()
            frame1 = cv2.putText(frame1, "One: fast process", (10, 30), cv2.FONT_HERSHEY_PLAIN, 2, (255, 255, 255))
        time.sleep(.1)  # 0.1s to use less CPU

def two():
    global frame2
    
    while running:
        if has_frame:
            # processing frame
            frame2 = frame.copy()
            frame2 = cv2.putText(frame2, "Two: slow process", (10, 30), cv2.FONT_HERSHEY_PLAIN, 2, (255, 255, 255))
            # simulate long running code
            time.sleep(2)        
        time.sleep(.1)  # 0.1s to use less CPU

#--- main ---

# - init ---

# create variables at start with default values
has_frame = False 
frame = None   # original frame from camera

frame1 = None  # frame after processing
frame2 = None  # frame after processing

cap = cv2.VideoCapture(0)  # create only one access to camera

# - create threads -

t0 = threading.Thread(target=read_frame)
t1 = threading.Thread(target=one)
t2 = threading.Thread(target=two)

# - start threads -

running = True  # use in threads to stop loops

t0.start()
t1.start()
t2.start()

# - GUI has to be in main thread -

while cv2.waitKey(100) != 27:  # ESC  # 100ms to use less CPU

    if frame1 is not None:
        cv2.imshow('Capturing1', frame1)

    if frame2 is not None:
        cv2.imshow('Capturing2', frame2)

    #time.sleep(.1)  # 0.1s to use less CPU
    
# - stop threads -

running = False

t0.join()
t1.join()
t2.join()

# - quit -

cv2.destroyAllWindows()
cap.release()

EDIT: Author of cv2 created also class to run VideoCapture in separated Thread .编辑: cv2的作者还创建了 class 以在单独的Thread中运行VideoCapture

from imutils.video import WebcamVideoStream

See details in Increasing webcam FPS with Python and OpenCV no PyImageSearch.com请参阅使用 Python 和 OpenCV no PyImageSearch.com提高网络摄像头 FPS 中的详细信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM