首页 > 解决方案 > Python OpenCV:使用 opecv 视频流进行多线程处理

问题描述

我想与 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()

标签: pythonpython-3.xmultithreadingopencvopencv-python

解决方案


.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()

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

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

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()

推荐阅读