Python OpenCV:多线程与 opencv 视频流

Python OpenCV: Mutithreading with opecv video streaming

我想要 运行 一个多线程以及 opencv 视频流。如果在视频不断流式传输时检测到对象 3 秒,我想激活 GPIO。我尝试过使用多线程(连接方法),但视频在线程调用期间暂停,因为它有 time.sleep()。有什么方法可以让我不断地并行播放视频 运行 线程?下面是行为相同的代码。如果我删除连接比 time.sleep 根本没有任何效果。

import threading 
import time
import numpy as np
import cv2

def print_hello():
    print("Hello")
    time.sleep(3)
    print ("World")

t1 = threading.Thread(target=print_hello)  

cap = cv2.VideoCapture(0)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()

    # Our operations on the frame come here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Display the resulting frame
    cv2.imshow('frame',gray)

    t1.start()
    t1.join()

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

这几乎不是一个好主意:

t1.start()
t1.join()

问题是,它违背了线程的 唯一 目的,即能够同时处理两个不同的事情。

这更有意义,因为“...some_other_thing...()”可以在 t1 执行 t1 执行的任何操作时发生。

t1.start()
do_some_other_thing_concurrently_with_t1()
t1.join()

.join() 等待线程结束并阻塞代码 - 因此它不会在循环内发送到 运行 它,但你应该在循环后或循环结束时 运行 它程序

另一个问题是 .start() 在循环中,因为 .start() 只能 运行 线程一次,所以在循环中多次使用它会产生错误。

您可以在循环之前启动线程,并且 运行 线程内的一些循环始终 运行 它。

import threading 
import time
import numpy as np
import cv2

# --- functions ---

running = True

def print_hello():
    while running:
        print("Hello World")
        time.sleep(3)

# --- main ---

t1 = threading.Thread(target=print_hello)  
t1.start()

# --- loop ---

cap = cv2.VideoCapture(0)

while True:
    # Capture frame-by-frame
    ret, frame = cap.read()

    # Our operations on the frame come here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Display the resulting frame
    cv2.imshow('frame',gray)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# --- after loop ---

running = False # to stop loop in thread
t1.join()

cap.release()
cv2.destroyAllWindows()

如果您必须在循环中启动线程,那么您还必须在循环内创建新线程。

在这个例子中,我使用键 t 来启动新线程 - 如果没有这个,它会在每个循环中创建新线程,所以它会在短时间内创建数百个线程,所以它没有意义。

import threading 
import time
import numpy as np
import cv2

# --- functions ---

def print_hello():
    print("Hello")
    time.sleep(3)
    print("World")

# --- main ---

all_threads = []

# --- loop ---

cap = cv2.VideoCapture(0)

while True:
    # Capture frame-by-frame
    ret, frame = cap.read()

    # Our operations on the frame come here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Display the resulting frame
    cv2.imshow('frame',gray)

    key = cv2.waitKey(1) & 0xFF
    if key == ord('q'):
        break
    if key == ord('t'):
        t = threading.Thread(target=print_hello)  
        t.start()
        all_threads.append(t)

# --- after loop ---

for t in all_threads:
    t.join()

cap.release()
cv2.destroyAllWindows()

但即使多次按下 t,您也可以同时创建多个线程,它们将协同工作。如果您不需要它,那么您将不得不控制威胁是否仍在起作用,并且只有在它不再起作用时才创建新的威胁 - 使用 is_alive() - 这样可以使它变得更复杂。

import threading 
import time
import numpy as np
import cv2

# --- functions ---

def print_hello():
    print("Hello")
    time.sleep(3)
    print("World")

# --- main ---

t = None

# --- loop ---

cap = cv2.VideoCapture(0)

while True:
    # Capture frame-by-frame
    ret, frame = cap.read()

    # Our operations on the frame come here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Display the resulting frame
    cv2.imshow('frame',gray)

    key = cv2.waitKey(1) & 0xFF
    if key == ord('q'):
        break

    if key == ord('t'):
        if t is None or not t.is_alive():
            t = threading.Thread(target=print_hello)  
            t.start()
        else:
            print('previous thread is still running')
            
# --- after loop ---

if t is not None:
    t.join()

cap.release()
cv2.destroyAllWindows()