并行处理视频python中的帧

时间:2018-01-03 03:23:52

标签: python image-processing computer-vision multiprocessing

视频python中帧的并行处理,你好我已经尝试使用python中的多处理库进行图像处理,我想做的是我有一个视频,我们知道视频是一个帧流我有核心i5我想要做的每个核心将处理这些帧的一帧示例(将在一秒内发生什么)核心1处理帧1核心2处理帧2核心3处理帧3核心4处理帧4核心。

我的问题是如何实现这一点? 这是我计划进行多处理或多线程的代码

int($(ls|wc -l)) > 20

1 个答案:

答案 0 :(得分:0)

虽然这不是你要求的,但我很好奇我将自己的图像分解成子图像以便进一步处理,所以我把这个例子放在一起。它显示了如何进行线程或多进程。你应该能够弄清楚如何及时分解而不是空间。

基本上,使用框架填充FRAME_QUEUE,而不是块。

import cv2
import numpy as np
import multiprocessing
import threading
import time
import argparse

FRAME_QUEUE = multiprocessing.JoinableQueue()
RESULT_QUEUE = multiprocessing.Queue()

# defaults
NWORKERS = 2
PARALLEL_TYPE = 'thread'
FONT = cv2.FONT_HERSHEY_SIMPLEX


def process_frame(frame):
    # Convert BGR to HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    lower_red = np.array([150, 150, 50], np.uint8)
    upper_red = np.array([180, 255, 150], np.uint8)

    # Threshold the HSV image to get only blue colors
    # finding the range of red
    mask = cv2.inRange(hsv, lower_red, upper_red)
    res = cv2.bitwise_and(frame, frame, mask=mask)

    kernel = np.ones((5, 5), np.uint8)
    mask = cv2.dilate(mask, kernel)
    res = cv2.bitwise_and(frame, frame, mask=mask)

    _, contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    for pic, contour in enumerate(contours):
        area = cv2.contourArea(contour)
        if(area > 1000):
            x, y, w, h = cv2.boundingRect(contour)
            frame = cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)

    return frame, mask, res


def parallel_process_frame(cls):
    """the main function that perfroms the image processing"""
    while True:
        next_frame = FRAME_QUEUE.get()
        if next_frame is None:
            # Poison pill means shutdown
            break

        # process the frame
        i, frame = next_frame
        frame, mask, res = process_frame(frame)

        # draw worker on frame
        frame = cv2.putText(frame, '{}'.format(i),
                            (0, 20), FONT,
                            0.5, (255, 0, 0), 1, cv2.LINE_AA)

        # tell the queue that we are done
        FRAME_QUEUE.task_done()

        # place the results in the result queue
        RESULT_QUEUE.put((i, (frame, mask, res)))


class ParallelProcessWorker(multiprocessing.Process):
    """multiprocess worker"""
    def __init__(self):
        multiprocessing.Process.__init__(self)

    def run(self):
        parallel_process_frame(self)


class ParallelThreadWorker(threading.Thread):
    """multithread worker"""
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        parallel_process_frame(self)


def serial(frame):
    """serial process the frame"""
    return process_frame(frame)


def multi(frame):
    """multithread/multiprocess process the frame"""
    # split the frame and place in the queue
    for i, chunk in enumerate(np.split(frame, NWORKERS)):
        FRAME_QUEUE.put((i, chunk))

    # wait for the chunks to finish
    FRAME_QUEUE.join()

    # collect the results
    results = []
    for i in range(NWORKERS):
        results.append(RESULT_QUEUE.get())

    # sort, because they can come back in any order
    results.sort(key=lambda x: x[0])

    # combine chunks
    frame = np.vstack((r[1][0] for r in results))
    mask = np.vstack((r[1][1] for r in results))
    res = np.vstack((r[1][2] for r in results))

    return frame, mask, res


if __name__ == "__main__":

    parser = argparse.ArgumentParser(
        prog='Parallel',
        description='Program parallel video processing')

    ARG = parser.add_argument
    ARG('-m', '--method', metavar='PAR', action='store', default=None,
        choices=['serial', 'thread', 'process'])
    ARG('-w', '--workers', metavar='N', action='store', default=2,
        help='specify the number of workers')

    args = parser.parse_args()

    # set flags
    PARALLEL_TYPE = args.method
    NWORKERS = int(args.workers)

    # setup parallel scheme
    if PARALLEL_TYPE != 'serial':
        method = multi
        if PARALLEL_TYPE == 'thread':
            worker = ParallelThreadWorker
        else:
            worker = ParallelProcessWorker
        # start the workers
        for i in range(NWORKERS):
            w = worker()
            w.start()
    else:
        method = serial

    # variables

    frame_count = 0
    start = time.time()

    # start capture
    cap = cv2.VideoCapture(0)

    # start the loop
    while(True):
        frame_count += 1

        # Take each frame
        _, frame = cap.read()

        frame, mask, res = method(frame)

        FPS = frame_count/(time.time()-start)

        frame = cv2.putText(frame, 'FPS: {0:.1f}'.format(FPS),
                            (0, 20), FONT,
                            0.5, (0, 255, 0), 1, cv2.LINE_AA)

        cv2.imshow('frame', frame)
        # cv2.imshow('mask', mask)
        # cv2.imshow('res', res)

        k = cv2.waitKey(5) & 0xFF
        if k == 27:
            break
    cap.release()
    cv2.destroyAllWindows()

    # place a bunch of Nones to shutdown the threads/process
    [FRAME_QUEUE.put(None) for i in range(NWORKERS*2)]

    # report
    print('Using a {0} approach with {1} workers resulted in an average FPS of {2:.1f}'.format(PARALLEL_TYPE, NWORKERS, FPS))

您可以指定并行方案和这样的工作人员:

python camera_parallel.py -m serial
python camera_parallel.py -m thread -w 4
python camera_parallel.py -m process -w 2

在我的机器上(MacBook Pro,2009,Core2Duo),串口为我提供了最高的帧速率。

enter image description here