【问题标题】:List of Numpy Arrays to single Numpy Array without Copying DataNumpy 数组列表到单个 Numpy 数组而不复制数据
【发布时间】:2015-07-12 09:34:16
【问题描述】:

我正在使用 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.ravelnumpy.asarraynumpy.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)))

【问题讨论】:

  • @hpaulj 我不确定这是否完全重复,因为我不一定需要有单独的数组。我可以预先分配一个 numpy 数组并相应地读取从 opencv 获得的值。
  • np.array([arr1,arr2,...,arrK]) 产生一个(K,N,M,3) 数组。是的,每个arr_i.data 缓冲区都将被复制到目标缓冲区。在列表中它们分散在记忆中,在目的地它们在一起。但是对于这种形状,复制将分块完成。

标签: python opencv numpy scikit-learn


【解决方案1】:

所以我相信我想通了。

  • 第一个错误:使用列表复制帧。我最终预分配了一个 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 中分析我的帧了!酷!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-30
    • 2014-07-04
    • 1970-01-01
    • 2022-01-15
    • 2016-08-19
    • 1970-01-01
    • 1970-01-01
    • 2011-12-13
    相关资源
    最近更新 更多