python中视频帧的多处理

时间:2016-07-05 12:16:59

标签: python multiprocessing

我是python中多处理的新手。我想从每小时长的视频文件中提取功能。处理每个帧大约需要30毫秒。我认为多处理是一个好主意,因为每个帧都是独立于所有其他帧处理的。

我想将特征提取的结果存储在自定义类中。

我阅读了一些示例,最终使用了建议here的多处理和队列。结果令人失望,现在每个帧需要大约1000毫秒来处理。我猜我产生了大量的开销。

是否有更有效的方法来并行处理帧并收集结果?

为了说明,我把一个虚拟的例子放在一起。

import multiprocessing as mp
from multiprocessing import Process, Queue
import numpy as np
import cv2

def main():
    #path='path\to\some\video.avi'
    coordinates=np.random.random((1000,2))
    #video = cv2.VideoCapture(path)
    listOf_FuncAndArgLists=[]

    for i in range(50):
        #video.set(cv2.CAP_PROP_POS_FRAMES,i)
        #img_frame_original = video.read()[1]
        #img_frame_original=cv2.cvtColor(img_frame_original, cv2.COLOR_BGR2GRAY)
        img_frame_dummy=np.random.random((300,300)) #using dummy image for this example
        frame_coordinates=coordinates[i,:]
        listOf_FuncAndArgLists.append([parallel_function,frame_coordinates,i,img_frame_dummy])

    queues=[Queue() for fff in listOf_FuncAndArgLists] #create a queue object for each function
    jobs = [Process(target=storeOutputFFF,args=[funcArgs[0],funcArgs[1:],queues[iii]]) for iii,funcArgs in enumerate(listOf_FuncAndArgLists)]
    for job in jobs: job.start() # Launch them all
    for job in jobs: job.join() # Wait for them all to finish
    # And now, collect all the outputs:
    return([queue.get() for queue in queues])         

def storeOutputFFF(fff,theArgs,que): #add a argument to function for assigning a queue
    print 'MULTIPROCESSING: Launching %s in parallel '%fff.func_name
    que.put(fff(*theArgs)) #we're putting return value into queue

def parallel_function(frame_coordinates,i,img_frame_original):
    #do some image processing that takes about 20-30 ms
    dummyResult=np.argmax(img_frame_original)
    return(resultClass(dummyResult,i))

class resultClass(object):
    def __init__(self,maxIntensity,i):
        self.maxIntensity=maxIntensity
        self.i=i

if __name__ == '__main__':
    mp.freeze_support()
    a=main()
    [x.maxIntensity for x in a]

2 个答案:

答案 0 :(得分:1)

多处理会为启动多个进程并将它们全部重新组合起来产生一些开销。

您的代码为每个框架执行此操作。

尝试将视频分割成N个大小均匀的片段并并行处理

将N等于机器上的内核数量或类似内容(您的里程可能会有所不同,但这是一个很好的数字,可以开始尝试)。创建50个进程是没有意义的,例如,其中4个进程正在执行而休息只是等待轮到他们。

答案 1 :(得分:1)

(常规)python中的并行处理有点痛苦:在其他语言中我们只使用线程,但GIL会使问题变得多,并且使用多处理在移动数据时会产生很大的开销。我发现细粒度的并行性(相对)很难做到,而处理在一个进程中处理10秒或更长时间(或更多)的“块”工作可能会更直截了当。

并行处理问题的一个更简单的途径 - 如果你在UNIXy系统上 - 将是一个python程序,它处理命令行上指定的一段视频(即一个帧号开头,和要处理的许多帧),然后使用GNU parallel工具一次处理多个段。第二个python程序可以合并来自parallel的文件集合的结果,或者从stdin读取。这种方式意味着处理代码不需要执行它自己的并行性,但它确实需要多次访问输入文件并从中间点开始提取帧。 (这也可以在不改变python的情况下扩展到跨多台机器工作......)

如果需要pure-python解决方案,可以以类似的方式使用multiprocessing.Pool.map:映射元组列表(例如,(file, startframe, endframe)),然后在函数和进程中打开文件那段。