python中的循环缓冲比使用deque的快?

2024-10-01 07:34:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我在python中使用收藏.deque用它来做一些计算。这是我的原始代码:

clip=moviepy.editor.VideoFileClip('file.mp4')
clip_size= clip.size[::-1]
Depth=30
dc=5
TempKern = # some array of size Depth
RingBuffer=deque(np.zeros(clip_size, dtype=float),maxlen=NewDepth)
modified_clip = clip.fl_image(new_filtered_output)
modified_clip.write_videofile('output.mp4'))

def new_filtered_output(image):
   global RingBuffer
   inter_frame=somefunction(image)# inter_frame and image shape is same as clip_size
   RingBuffer.append(inter_frame)
   # Apply kernel
   Output =  dc + np.sum([np.asarray(RingBuffer)[j]*TempKern[j] for j in range(Depth)],axis=0)
   return Output

这是最快的办法吗?我听说有个选择。但我不知道如何让它像上面的代码一样工作?在


Tags: 代码imageoutputsizeclipnpdcframe
2条回答

可以将环形缓冲区作为numpy数组,方法是将大小加倍并切片:

clipsize = clip.size[::-1]
depth = 30
ringbuffer = np.zeros((2*depth,) + clipsize)

framecounter = 0

def new_filtered_output(image):
   global ringbuffer, framecounter
   inter_frame = somefunction(image)

   idx = framecounter % depth
   ringbuffer[idx] = ringbuffer[idx + depth] = inter_frame
   buffer = ringbuffer[idx + 1 : idx + 1 + depth]
   framecounter += 1

   # Apply kernel
   output =  dc + np.sum([buffer[j]*kernel[j] for j in range(depth)], axis=0)
   return output

现在,您不必每帧都将deque转换为numpy数组(以及每个循环迭代….)。在

如注释中所述,您可以更有效地应用内核:

^{pr2}$

或者:

output = dc + np.tensordot(kernel, buffer, axes=1)

我注意到您更改了上面的代码,但您原来的代码是:

def one():
    TempKern=np.array([1,2,3,4,5])
    depth=len(TempKern)
    buf=deque(np.zeros((2,3)),maxlen=5)
    for i in range(10):
        buf.append([[i,i+1,i+2],[i+3,i+4,i+5]])
    total=  + np.sum([np.asarray(buf)[j]*TempKern[j] for j in range(depth)],axis=0)
    print('total')
    print(total)
    return total

如果您首先将数组展平以进行计算,那么可以大大简化事情并使其运行得更快一些。在

^{pr2}$

第二个实现返回相同的值,在我的机器上运行速度快4倍

one()

>> [[115 130 145]
    [160 175 190]]   ~ 100µs / loop

two()

>> array([[115, 130, 145],
          [160, 175, 190]])    ~~ 26µs / loop

您可以这样进一步简化和参数化:

def three(n, array_shape):
    buf = np.zeros((n,array_shape[0]*array_shape[1]), dtype=np.int32)
    addit = np.arange(1, n+1, dtype=np.int32)
    for idx, i in enumerate(range(n, 2*n)):
        buf[idx] = np.arange(i, i+n+1)
    return (buf.T * addit).sum(axis=1).reshape(array_shape)

three(5, (2,3))

    >> array([[115, 130, 145],
             [160, 175, 190]])   ~ 17µs / loop

注意,第二个和第三个版本返回一个numpy数组。如果需要,可以使用.tolist()将其强制转换为列表。在

根据您的反馈-编辑以下内容:

def four(array_shape):
    n = array_shape[0] * array_shape[1] - 1
    buf = []
    addit = np.arange(1, n+1, dtype=np.int32)
    for idx, i in enumerate(range(n, 2*n)):
        buf.append(np.arange(i, i+n+1))
    buf = np.asarray(buf)
    summed = (buf.T * addit).sum(axis=1)
    return summed.reshape(array_shape)

相关问题 更多 >