如何使用cv2& amp;从视频并行获取帧python中的多处理 [英] how to get frames from video in parallel using cv2 & multiprocessing in python

查看:140
本文介绍了如何使用cv2& amp;从视频并行获取帧python中的多处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用cv2&在python中进行多处理,最后我有了一个工作脚本,一旦它们已经在输入队列中,它们就会对各个帧进行填充.但是,我想首先通过使用多个内核来加快将帧放入队列的速度,因此我尝试使用相同的多处理方法将每个图像读入队列.我似乎无法使它正常工作,我不确定为什么.我以为可能是因为我正在尝试写入一个队列,所以我将它们拆分了,但是现在我想知道是否是因为我正在尝试同时读取同一视频文件.

I've been working with cv2 & multiprocessing in python, and I finally have a working script that does stuff to the individual frames once they are already in an input queue. However, I wanted to speed up getting the frames into the queue in the first place by using multiple cores, so I tried to use the same multiprocessing approach to read each image into the queue. I can't seem to get this to work though, and I'm not sure why. I thought maybe it was because I was trying to write to one queue, so I split those up, but now I'm wondering if it's because I'm trying to read from the same video file at the same time.

这是我希望用伪代码完成的事情:

Here is what I am hoping to accomplish in pseudocode:

for process in range(processCount):
    start a process that does this:
        for frame in range(startFrame,endFrame):
            set next frame to startFrame
            read frame
            add frame to queue

这是我当前的代码.我已经尝试过使用泳池&单独的进程,但是现在我坚持使用单独的进程,因为我不确定问题是否出在队列管理上.如果我手动调用getFrame,我会将正确的东西放入队列,因此我认为该功能本身可以正常工作.

Here is my current code. I've tried using pool & separate processes, but for now I'm sticking to separate processes because I'm not sure if the problem is with queue management. If I call getFrame manually, I get the right stuff into the queue, so I think that function by itself works okay.

我确定我所做的事情确实很愚蠢(或者很奇怪).有人可以提出解决方案吗?最好只有一个队列...我只有两个队列来尝试解决问题.

I'm sure I'm doing something really silly (or really odd). Can someone suggest a solution? It would be great to just have one queue as well... I just had two to try to break down the problem.

谢谢.

import numpy as np
import cv2
import multiprocessing as mp
import time

def getFrame(queue, startFrame, endFrame):
    for frame in range(startFrame, endFrame):
        cap.set(1,frame)
        frameNo = int(cap.get(0))
        ret, frame = cap.read()
        queue.put((frameNo,frame))

file = 'video.mov'
cap = cv2.VideoCapture(file)
fileLen = int(cap.get(7))

# get cpuCount for processCount
processCount = mp.cpu_count()/3

inQ1 = mp.JoinableQueue()  # not sure if this is right queue type, but I also tried mp.Queue()
inQ2 = mp.JoinableQueue()
qList = [inQ1,inQ2]

# set up bunches
bunches = []
for startFrame in range(0,fileLen,fileLen/processCount):
    endFrame = startFrame + fileLen/processCount
    bunches.append((startFrame,endFrame))

getFrames = []
for i in range(processCount):
    getFrames.append(mp.Process(target=getFrame, args=(qList[i], bunches[i][0],bunches[i][1],)))

for process in getFrames:
    process.start()

results1 = [inQ1.get() for p in range(bunches[0][0],bunches[0][1])]
results2 = [inQ2.get() for p in range(bunches[1][0],bunches[1][1])]

inQ1.close()
inQ2.close()
cap.release()

for process in getFrames:
    process.terminate()
    process.join()

推荐答案

代码中确实存在一个错误:跨进程使用相同的VideoCapture对象.显然,文件中当前正在读取的位置存在冲突.

There is indeed a mistake in the code : the use of the same VideoCapture object across processes. Obviously there's a conflict on the position currently being read in the file.

话虽这么说,当试图为每个进程实例化一个VideoCapture时,我的解释器崩溃了(用python3.4.2 + opencv3.0.0-betapython2.7.6 + opencv2.4.8测试).到目前为止,这是我的尝试,如果您想检查一下或继续试一下.

This being said, when trying to instantiate one VideoCapture per process, my interpreter crashes (tested with python3.4.2 + opencv3.0.0-beta, and python2.7.6 + opencv2.4.8). Here's my try so far if you want to check it / go further.

import cv2
import multiprocessing as mp

def getFrame(queue, startFrame, endFrame):
    cap = cv2.VideoCapture(file)  # crashes here
    print("opened capture {}".format(mp.current_process()))
    for frame in range(startFrame, endFrame):
        # cap.set(cv2.CAP_PROP_POS_FRAMES, frame)  # opencv3            
        cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, frame)
        # frameNo = int(cap.get(cv2.CAP_PROP_POS_FRAMES))  # opencv3
        frameNo = int(cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES))
        ret, f = cap.read()
        if ret:
            print("{} - put ({})".format(mp.current_process(), frameNo))
            queue.put((frameNo, f))
    cap.release()

file = "video.mov"
capture_temp = cv2.VideoCapture(file)
# fileLen = int((capture_temp).get(cv2.CAP_PROP_FRAME_COUNT))  # opencv3
fileLen = int((capture_temp).get(cv2.cv.CV_CAP_PROP_FRAME_COUNT))
capture_temp.release()

# get cpuCount for processCount
# processCount = mp.cpu_count() / 3
processCount = 2

inQ1 = mp.JoinableQueue()  # not sure if this is right queue type, but I also tried mp.Queue()
inQ2 = mp.JoinableQueue()
qList = [inQ1, inQ2]

# set up bunches
bunches = []
for startFrame in range(0, fileLen, int(fileLen / processCount)):
    endFrame = startFrame + int(fileLen / processCount)
    bunches.append((startFrame, endFrame))

getFrames = []
for i in range(processCount):
    getFrames.append(mp.Process(target=getFrame, args=(qList[i], bunches[i][0], bunches[i][1])))

for process in getFrames:
    process.start()

results1 = [inQ1.get() for p in range(bunches[0][0], bunches[0][1])]
results2 = [inQ2.get() for p in range(bunches[1][0], bunches[1][1])]

inQ1.close()
inQ2.close()

for process in getFrames:
    process.terminate()
    process.join()

这篇关于如何使用cv2& amp;从视频并行获取帧python中的多处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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