简体   繁体   English

图像处理中的多线程 - 视频 python opencv

[英]Multi-threading in image processing - video python opencv

Im working on object detection from a live stream video using opencv python.我正在使用 opencv Z23EEEB4347BDD26BFC6B7EE9A3B755DD. The program I have is running on a single thread because of that the resulting video shown on the screen doesnt even look like a video, since there is a delay in detection process.我拥有的程序在单个线程上运行,因为屏幕上显示的结果视频甚至看起来不像视频,因为检测过程存在延迟。 So, Im trying to re-implement it using multiple threads.所以,我试图使用多个线程重新实现它。 I am using one thread for reading frames and another for showing the detection result and about 5 threads to run the detection algorithm on multiple frames at once.我使用一个线程读取帧,另一个线程显示检测结果,大约 5 个线程一次在多个帧上运行检测算法。 I have written the following code but the result is not different from the single thread program.我已经编写了以下代码,但结果与单线程程序没有什么不同。 Im new to python.我是 python 的新手。 So, any help is appreciated.因此,任何帮助表示赞赏。

import threading, time
import cv2
import queue


def detect_object():
    while True:
        print("get")
        frame = input_buffer.get()
        if frame is not None:
            time.sleep(1)
            detection_buffer.put(frame)
        else:
            break
    return


def show():
    while True:
        print("show")
        frame = detection_buffer.get()
        if frame is not None:
            cv2.imshow("Video", frame)
        else:
            break
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    return


if __name__ == "__main__":

    input_buffer = queue.Queue()
    detection_buffer = queue.Queue()

    cap = cv2.VideoCapture(0)

    for i in range(5):
        t = threading.Thread(target=detect_object)
        t.start()

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

    while True:
        ret, frame = cap.read()
        if ret:
            input_buffer.put(frame)
            time.sleep(0.025)
        else:
            break

    print("program ended")

Working on the assumption that the detection algorithm is CPU-intensive, you need to be using multiprocessing instead of multithreading since multiple threads will not run Python bytecode in parallel due to contention for the Global Interpreter Lock.假设检测算法是 CPU 密集型的,您需要使用多处理而不是多线程,因为由于争用全局解释器锁,多个线程不会并行运行 Python 字节码。 You should also get rid of all the calls to sleep .您还应该摆脱所有对sleep的调用。 It is also not clear when you run multiple threads or processes the way you are doing it what guarantees that the frames will be output in the correct order, that is, the processing of the second frame could complete before the processing of the first frame and get written to the detection_buffer first.当您运行多个线程或以您的方式处理时,也不清楚什么保证帧将以正确的顺序成为 output,也就是说,第二帧的处理可以在第一帧的处理之前完成,并且首先写入detection_buffer

The following uses a processing pool of 6 processes (there is no need now for an implicit input queue).以下使用 6 个进程的处理池(现在不需要隐式输入队列)。

from multiprocessing import Pool, Queue
import time
import cv2

# intialize global variables for the pool processes:
def init_pool(d_b):
    global detection_buffer
    detection_buffer = d_b


def detect_object(frame):
    time.sleep(1)
    detection_buffer.put(frame)


def show():
    while True:
        print("show")
        frame = detection_buffer.get()
        if frame is not None:
            cv2.imshow("Video", frame)
        else:
            break
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    return


# required for Windows:
if __name__ == "__main__":

    detection_buffer = Queue()
    # 6 workers: 1 for the show task and 5 to process frames:
    pool = Pool(6, initializer=init_pool, initargs=(detection_buffer,))
    # run the "show" task:
    show_future = pool.apply_async(show)

    cap = cv2.VideoCapture(0)

    futures = []
    while True:
        ret, frame = cap.read()
        if ret:
            f = pool.apply_async(detect_object, args=(frame,))
            futures.append(f)
            time.sleep(0.025)
        else:
            break
    # wait for all the frame-putting tasks to complete:
    for f in futures:
        f.get()
    # signal the "show" task to end by placing None in the queue
    detection_buffer.put(None)
    show_future.get()
    print("program ended")

for me what I've done is building 2 threads for 2 funtions and use one queue:对我来说,我所做的是为 2 个函数构建 2 个线程并使用一个队列:

  1. to get the frame and process it获取框架并处理它
  2. to dispaly显示

the cap variable was inside my process function.上限变量在我的进程 function 中。

def process:
     cap = cv2.VideoCapture(filename)
     ret, frame = cap.read()

      while ret:
          ret, frame = cap.read()
#detection part in my case I use tensorflow then 
     # end of detection part 
          q.put(result_of_detection)

def Display():
  while True:
    if q.empty() != True:
        frame = q.get()
        cv2.imshow("frame1", frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

if __name__ == '__main__':
#  start threads
p1 = threading.Thread(target=process)
p2 = threading.Thread(target=Display)
p1.start()
p2.start()

it works just fine for me它对我来说很好用

hope I helped:D希望我有所帮助:D

Also, I think this page could may help: https://pyimagesearch.com/2015/12/21/increasing-webcam-fps-with-python-and-opencv/另外,我认为这个页面可能会有所帮助: https://pyimagesearch.com/2015/12/21/increasing-webcam-fps-with-python-and-opencv/

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

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