Skip to main content
 首页 » 编程设计

python之python 中的快速循环缓冲区比使用 deque 的循环缓冲区

2025年05月04日32pander-it

我正在使用 collections.deque 在 python 中实现循环缓冲区,以将其用于某些计算。这是我的原始代码:

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 

这是最快的方法吗?我听说 numpy roll 是一种选择。但是我不知道如何让它像上面的代码那样表现?

请您参考如下方法:

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

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 

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

def two(): 
    buf = np.zeros((5,6), dtype=np.int32) 
    for idx, i in enumerate(range(5, 10)): 
        buf[idx] = np.array([[i,i+1,i+2,i+3,i+4,i+5]], dtype=np.int32) 
    return (buf.T * np.array([1, 2, 3, 4, 5])).sum(axis=1).reshape((2,3)) 

第二个实现返回相同的值并且在我的机器上运行速度大约快 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) 

三(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)