先说需求: 我需要处理读取多个视频, 每个视频间隔一定时间取帧进行图像识别。下面是提取视频的代码, 一开始我是使用多进程实现的。后面想着读取视频应该是磁盘 IO, 是否使用协程合适?查资料说不是原生异步需要使用线程池维护, 但是写下来,发现也没关协程啥事啊?是不是我写的有问题。正确写法应该怎么样,求各位大佬解答。
import cv2
import asyncio
import os
import numpy as np
import time
def read(cap):
ret, frame = cap.read()
return ret, frame
def put_frame(queue, video_path,interval=50):
'''
queue: 队列
video_path: 视频路径
interval: 间隔多少帧取一次图片
'''
num = 0
img_list = []
cap = cv2.VideoCapture(video_path)
start = time.time()
while cap.isOpened():
cap.set(cv2.CAP_PROP_POS_FRAMES, num*interval)
ret, frame = read(cap)
if ret:
custom_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
cv2.imshow("{0}".format(video_path), frame)
cv2.waitKey(24)
custom_image = cv2.resize(
custom_image, (416, 416), interpolation=cv2.INTER_NEAREST)
custom_image = custom_image.transpose(2, 0, 1)
img_list.append(custom_image)
num += 1
else:
arr = np.concatenate(img_list, axis=0)
# arr = np.ascontiguousarray(arr.flat, dtype=np.float32) / 255.0
queue.put(arr)
print("--------------, {0}提取视频完成, 用时:{1}", video_path, (time.time()-start))
break
video_dir = './video'
loop = asyncio.get_event_loop()
tasks = []
queue = asyncio.Queue(loop=loop, maxsize=10)
for video in os.listdir(video_dir):
# await asyncio.sleep(0)
video_path = os.path.join(video_dir, video)
task = loop.run_in_executor(None, put_frame, queue, video_path)
tasks.append(task)
loop.run_until_complete(asyncio.wait(tasks))
# 他还会出现这个警告:
C:/Users/rookie/Desktop/20200512/demo3.py:36: RuntimeWarning: coroutine 'Queue.put' was never awaited
queue.put(arr)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.