我正在使用Python OpenCV读取视频数据,并希望存储K帧数。目前,我有执行以下操作(伪代码)的循环:
frame_list = 1:K
frame_buffer = list(map(ReadFrameNumber, frame_list))
我现在有一个列表,frame_buffer
,长度为 K 帧,数据是 NxMx3 numpy 数组。这一切都很好,但是现在我想重组数据,以便我可以有效地使用scikit-learn来尝试一些模型。为了做到这一点,我需要创建一个 numpy 数组,它可以结构化为 ((N*M*3) x (K)) 或 ((K) x (N*M*3) 矩阵。我可以成功地做到这一点,但是数据正在复制,这使得此功能非常慢。我正在使用numpy.ravel
、numpy.asarray
和numpy.transpose
的组合来完成我的慢速方法。我基本上只是想要一个新的数据视图。
这是我现在正在做的事情,这不起作用(需要太长时间):
def RearrangeData(data):
b = list(map(np.ravel, data))
b = np.asarray(b, dtype=np.float32)
return b
更新:这就是我从opencv读取帧的方式:
import numpy as np
import cv2
K= 10
num_frames = K
cap = cv2.VideoCapture(filename)
def PopulateBuffer(num):
cap.set(cv2.CAP_PROP_POS_FRAMES, num)
ret, frame = cap.read()
if not ret:
print("Fatal Error: Could not read/decode frame %d" % num)
exit(-1)
return frame
frame_nums = list(range(0, int(num_frames)))
return (list(map(PopulateBuffer, frame_nums)))
所以我相信我想通了。
-
第一个错误:使用列表在帧中复制。我最终预分配了一个 numpy 数组:
#Preallocate frame buffer frame_buffer = np.zeros((num_frames,) + frame.shape) # Copy frames for i in range(0, num_frames): frame_buffer[i, :, :, :] = PopulateBuffer(i)
-
第二个错误:我没有意识到
numpy.reshape()
会创建一个新视图(在大多数情况下我认为)。因此,一旦我正确设置了初始阵列,就只需执行以下操作即可。buf_s = frame_buffer.shape K = buf_s[0] # Number of frames M = buf_s[1] # Number of rows N = buf_s[2] # Number of cols chan = buf_s[3] # Color channel # If this copies data, I'm screwed. %time scikit_buffer = frame_buffer.reshape([K, M*N*chan])
我肯定它不是复制数据,因为 reshape 命令以微秒的数量级运行:
CPU 时间:用户 17 μs,系统:1 μs,总计:18 μs挂断时间:21.9 μs
现在我可以在scikit-learn中分析我的框架了!凉!