3

I'm reading in video data using Python OpenCV and want to store K number of frames. Currently, I have loop that does the following (pseudo code):

frame_list = 1:K
frame_buffer = list(map(ReadFrameNumber, frame_list))

I now have a list, frame_buffer, that is K frames in length with the data being an NxMx3 numpy array. This is all fine and dandy, but now I want to restructure the data so I can effectively use scikit-learn to try some models out. In order to do this, I need to create a numpy array that can be structured as an ((N*M*3) x (K)) or as a ((K) x (N*M*3) matrix. I can successfully do this, but the data is being copied which makes this the function VERY slow. I am using a combination of numpy.ravel, numpy.asarray, and numpy.transpose to accomplish my slow method. I essentially just want a new view to the data.

Here is what I am doing now, and this is NOT working (it takes way too long):

def RearrangeData(data): 
   b = list(map(np.ravel, data))
   b = np.asarray(b, dtype=np.float32)
   return b

UPDATE: This is how I am reading frames from 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)))
user985030
  • 1,557
  • 1
  • 16
  • 32
  • Duplicate of http://stackoverflow.com/questions/29773918/is-there-any-way-to-make-a-soft-reference-or-pointer-like-objects-using-numpy-ar – hpaulj May 02 '15 at 18:26
  • 1
    @hpaulj I'm not sure this is quite a duplicate, because I don't necessarily need to have separate arrays. I could pre-allocate a numpy array and read in the values I get from opencv accordingly. – user985030 May 02 '15 at 18:36
  • `np.array([arr1,arr2,...,arrK])` produces a `(K,N,M,3)` array. And yes, each `arr_i.data` buffer will be copied to destination buffer. In the list they are scattered around memory, in the destination they are together. But with this shape, the copying will be done in blocks. – hpaulj May 02 '15 at 19:19

1 Answers1

1

So I believe I figured it out.

  • First mistake: using a list to copy in frames. I ended up preallocating a numpy array:

     #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)
    
  • Second mistake: I didn't realize that numpy.reshape() would create a new view (in most cases I think). So it was as simple as doing the following once I had my initial array setup correctly.

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

I'm positive it's not copying data because the reshape command runs on the order of micro seconds:

CPU times: user 17 µs, sys: 1 µs, total: 18 µs Wall time: 21.9 µs

And now I can analyze my frames in scikit-learn! Cool!

user985030
  • 1,557
  • 1
  • 16
  • 32