python中视频帧的多处理 [英] multiprocessing of video frames in python

查看:342
本文介绍了python中视频帧的多处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我阅读了一些示例,并按照建议的解决方案

(常规)python中的并行处理有点麻烦:在其他语言中,我们只使用线程,但是GIL使得此问题成问题,并使用多处理在移动数据方面有很大的开销.我发现,(相对)很难实现细粒度的并行处理,而在单个流程中处理需要10秒钟(或更长时间)才能完成的块"工作可能会更加直接.

如果在UNIXy系统上,则并行处理问题的更简单方法是制作一个python程序,该程序可以处理在命令行上指定的一段视频(例如,以帧开头的帧号,以及许多帧),然后使用 GNU并行工具一次处理多个细分.第二个python程序可以合并文件集合的结果,或者从parallel用管道传输的stdin中读取结果.这种方式意味着处理代码不需要自己进行并行处理,但是确实需要对输入文件进行多重访问并从中点开始提取帧. (这也可以扩展为在多台机器上工作而无需更改python ...)

如果需要纯python解决方案,则可以以类似的方式使用multiprocessing.Pool.map:映射元组列表(例如(file, startframe, endframe)),然后在函数中打开文件并处理该段. /p>

I am new to multiprocessing in python. I want to extract features from each frame of hour long video files. Processing each frame takes on the order of 30 ms. I thought multiprocessing was a good idea because each frame is processed independentle of all other frames.

I want to store the results of the feature extraction in a custom class.

I read a few examples and ended up using multiprocessing and Queues as suggested here. The result was disappointing though, now each frames takes about 1000 ms to process. I am guessing I produced a ton of overhead.

is there a more efficient way to process the frames in parallel and collect the results?

to illustrate, I put together a dummy example.

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]

解决方案

Parallel processing in (regular) python is a bit of a pain: in other languages we'd just use threads but the GIL makes that problematic, and using multiprocessing has a big overhead in moving data around. I've found that fine-grained parallelism is (relatively) hard to do, whilst processing 'chunks' of work that take 10's of seconds (or more) to process in a single process can be much more straight-forward.

An easier path to parallel processing your problem - if you're on a UNIXy system - would be to make a python program which processes a segment of video specified on the command-line (i.e. a frame number to start with, and a number of frames to process), and then use the GNU parallel tool to process multiple segments at once. A second python program can consolidate the results from a collection of files, or reading from stdin, piped from parallel. This way means that the processing code doesn't need to do it's own parallelism, but it does require the input file to be multiply accessed and to extract frames starting from mid-points. (This might also be extendable to work across multiple machines without changing the python...)

Using multiprocessing.Pool.map could be used in a similar way if you need a pure-python solution: map over a list of tuples (say, (file, startframe, endframe)) and then open the file in the function and process that segment.

这篇关于python中视频帧的多处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆