簡體   English   中英

如何在python中使用cv2和多處理並行獲取視頻幀

[英]how to get frames from video in parallel using cv2 & multiprocessing in python

我一直在python中使用cv2和多處理,最后我有一個工作腳本,一旦它們已經在輸入隊列中就會對各個幀進行處理。 但是,我想通過使用多個核心來加速將幀放入隊列,因此我嘗試使用相同的多處理方法將每個圖像讀入隊列。 我似乎無法讓它工作,我不知道為什么。 我想也許是因為我試圖寫入一個隊列,所以我把它們分開了,但現在我想知道是不是因為我試圖同時從同一個視頻文件中讀取。

這是我希望在偽代碼中完成的事情:

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,我會將正確的東西放入隊列中,所以我認為該函數本身可以正常工作。

我確定我做的事情真的很傻(或者很奇怪)。 有人可以提出解決方案嗎? 只有一個隊列也很棒......我只有兩個試圖解決問題。

提前致謝。

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對象。 顯然,當前正在文件中讀取的位置存在沖突。

python3.4.2 ,當我嘗試在每個進程中實例化一個VideoCapture時,我的解釋器崩潰了(用python3.4.2 + opencv3.0.0-betapython2.7.6 + opencv2.4.8 )。 這是我到目前為止的嘗試,如果你想檢查它/進一步。

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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM