python - 使用并发期货通过多处理运行多个视频
问题描述
我正在尝试使用 concurrent.futres.ProcessPoolExecuter 运行代码,但在运行视频时遇到下面提到的while true
错误class get_frames
concurrent.futures.process.BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending.
下面提到的是我的实际代码:
import cv2
import numpy as np
import imutils
import os
import threading
import concurrent.futures
import time
start = time.perf_counter()
class VideoCapture:
def __init__(self, name):
self.cap = cv2.VideoCapture(name)
self.q = queue.Queue()
t = threading.Thread(target=self._reader)
# t.get_ident()
t.start()
t.daemon = True
# read frames as soon as they are available, keeping only most recent one
def _reader(self):
while True:
ret, frame = self.cap.read()
if not ret:
break
if not self.q.empty():
try:
self.q.get_nowait() # discard previous (unprocessed) frame
except Queue.Empty:
pass
self.q.put(frame)
@classmethod
def read(cls):
return cls(self.q.get())
names = ['test.mp4', 'test1.mp4']
frames = [None] * len(names);
#frame_in = [None] * len(names);
ret = [None] * len(names);
cap_list = [cv2.VideoCapture(k) for k in names]
# print(cap_list)
class get_frames:
def __init__(self, cap, name):
self.cap = cap
self.name = name
# print(self.cap)
def display_frames(self):
while True:
ret, frames = self.cap.read()
if ret is True:
count += 1
print(self.name)
with concurrent.futures.ProcessPoolExecutor(max_workers=3) as executor:
for i, cap in enumerate(cap_list):
g_f = get_frames(cap, i)
results = executor.map(g_f.display_frames, cap_list)
print(results)
对此的任何建议都会有很大帮助
解决方案
您可以坚持使用ProcessPoolExecutor Example。
示例如下:
def main():
with concurrent.futures.ProcessPoolExecutor() as executor:
for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
print('%d is prime: %s' % (number, prime))
if __name__ == '__main__':
main()
- 您必须使用
if __name__ == '__main__':
语法。按照方法
放置准备代码。 没有它,整个脚本会被执行多次,并且会卡住。cap_list = [cv2.VideoCapture(k) for k in names]
main()
- 该示例使用方法,而不是对象。
我想你可以映射对象方法,但我不能让它工作。 - 使用 Python 3.6 时,出现错误:
"TypeError: can't pickle cv2.VideoCapture objects"
.
我将文件名传递给display_frames
,并在方法cv2.VideoCapture
的开头执行display_frames
。 - 您发布的代码未使用
class VideoCapture
.
用于检测:
- 我的示例生成合成视频文件(为了使示例“自包含”)。
- 该示例显示了用于测试的视频帧。
这是代码:
import cv2
import numpy as np
import concurrent.futures
def display_frames(name):
cap = cv2.VideoCapture(name)
while True:
ret, frames = cap.read()
if ret is False:
break
# Show frames for testing:
cv2.imshow(str(cap), frames)
cv2.waitKey(100)
cap.release()
return name
def main():
names = ['test2.mp4', 'test3.mp4']
# Generate two synthetic video files to be used as input:
###############################################################################
width, height, n_frames = 640, 480, 30 # 30 frames, resolution 640x480
intput_filename1 = names[0]
intput_filename2 = names[1]
# Use MPEG4 codec (for testing)
synthetic_out = cv2.VideoWriter(intput_filename1, cv2.VideoWriter_fourcc(*'mp4v'), 25, (width, height))
for i in range(n_frames):
img = np.full((height, width, 3), 60, np.uint8)
cv2.putText(img, str(i+1), (width//2-100*len(str(i+1)), height//2+100), cv2.FONT_HERSHEY_DUPLEX, 10, (30, 255, 30), 20) # Green number
synthetic_out.write(img)
synthetic_out.release()
width, height, n_frames = 320, 240, 20 # 20 frames, resolution 320x240
synthetic_out = cv2.VideoWriter(intput_filename2, cv2.VideoWriter_fourcc(*'mp4v'), 25, (width, height))
for i in range(n_frames):
img = np.full((height, width, 3), 60, np.uint8)
cv2.putText(img, str(i+1), (width//2-50*len(str(i+1)), height//2+50), cv2.FONT_HERSHEY_DUPLEX, 5, (255, 30, 30), 10) # Blue number
synthetic_out.write(img)
synthetic_out.release()
###############################################################################
with concurrent.futures.ProcessPoolExecutor(max_workers=3) as executor:
for name in executor.map(display_frames, names):
print(name)
cv2.destroyAllWindows() # For testing
# Using Python 3.6 there is an error: "TypeError: can't pickle cv2.VideoCapture objects"
if __name__ == '__main__':
main()
我真的不知道它是否回答了您的问题,因为您的原始代码所剩无几。
我希望它有帮助...
推荐阅读
- selenium - 更新 java-client 和 selenium 版本后,Appium 代码不起作用
- php - 如何使用来自 daabase 的 jquery ajax 获取 html 表单字段的数据
- c - 创建一个填充随机唯一数字的数组
- firebase - 使用 FirebaseAuth 、 Firestore 和 Google 登录的 Flutter multidex 问题
- ios - 为什么默认情况下 Swift 中的属性是非原子的?
- javascript - 如何将多个子项链接到单个父项?
- reactjs - GQL 不会自动调用查询
- html - 在 div 上应用灰度,除了它的子元素之一
- laravel - 每次递增按钮单击后如何存储用户ID
- c# - 编译时的 C# 代码扩展/注入