我是 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]
最佳答案
(常规)python 中的并行处理有点痛苦:在其他语言中,我们只使用线程,但 GIL 使这个成为问题,并且使用多处理在移动数据方面有很大的开销。我发现细粒度的并行性(相对)很难做到,而在单个进程中处理需要 10 秒(或更多)才能处理的“大块”工作可能会更直接。
如果您使用的是 UNIXy 系统,并行处理您的问题的一个更简单的途径是制作一个 python 程序,该程序处理命令行上指定的一段视频(即开始的帧号,以及要处理的帧数),然后使用 GNU parallel一次处理多个片段的工具。第二个 python 程序可以合并文件集合的结果,或者从标准输入读取,从 parallel
管道传输。这种方式意味着处理代码不需要执行它自己的并行性,但它确实需要对输入文件进行多次访问并从中点开始提取帧。 (这也可以扩展为在不更改 python 的情况下跨多台机器工作...)
如果您需要纯 Python 解决方案,可以以类似的方式使用 multiprocessing.Pool.map
:映射元组列表(例如,(file, startframe, endframe )
) 然后在函数中打开文件并处理该段。
关于python - python中视频帧的多处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38203239/