3

我正在使用 Python 2.7.4 创建一个简单的绿屏应用程序,但结果很慢。我目前正在使用 PIL 1.1.7 加载和迭代图像,并看到从旧的 getpixel() 到新的 load() 和像素访问对象索引的巨大加速变化。然而,对于分辨率约为 720p 的图像,以下循环仍然需要大约 2.5 秒的时间来运行:

def colorclose(Cb_p, Cr_p, Cb_key, Cr_key, tola, tolb):
    temp = math.sqrt((Cb_key-Cb_p)**2+(Cr_key-Cr_p)**2)
    if temp < tola:
        return 0.0
    else: 
        if temp < tolb:
            return (temp-tola)/(tolb-tola)
        else:
            return 1.0

……

for x in range(width):
    for y in range(height):
        Y, cb, cr = fg_cbcr_list[x, y]
        mask = colorclose(cb, cr, cb_key, cr_key, tola, tolb)
        mask = 1 - mask
        bgr, bgg, bgb = bg_list[x,y]
        fgr, fgg, fgb = fg_list[x,y]
        pixels[x,y] = (
            (int)(fgr - mask*key_color[0] + mask*bgr),
            (int)(fgg - mask*key_color[1] + mask*bgg),
            (int)(fgb - mask*key_color[2] + mask*bgb))

我在这里做了什么效率非常低的事情,让它运行得这么慢吗?我见过类似的、更简单的例子,例如循环被布尔矩阵替换,但在这种情况下,我看不到替换循环的方法。

像素 [x,y] 分配似乎花费了最多的时间,但对 Python 不太了解,我不确定是否有更有效的方法来做到这一点。

任何帮助,将不胜感激。

4

1 回答 1

0

最好逐行遍历像素,因为这是内存中使用的布局。

所以而不是:

for x in range(width):
    for y in range(height):

利用

for y in range(height):
    for x in range(width):

编辑:例如为什么这很重要,您可以阅读有关迭代数组的 numpy 文档

对于此迭代,需要注意的重要一点是,选择顺序以匹配数组的内存布局,而不是使用标准的 C 或 Fortran 排序。这样做是为了提高访问效率,反映了默认情况下人们只想访问每个元素而不关心特定顺序的想法。与以 C 顺序获取该转置的副本相比,我们可以通过迭代我们先前数组的转置来看到这一点。

于 2013-11-05T09:54:16.793 回答