更快的调整PIL像素值的方法

3
我正在使用Python和PIL(pillow)编写脚本进行绿幕合成。我可以对720p图像进行关键字处理,但是还有一些绿色溢出。我正在编写一个程序来消除这种溢出,但是我发现这个过程非常耗时。我可能可以使用numpy技巧提高速度,但我不太熟悉它。你有什么建议吗?
这是我的去溢出程序。它需要一个PIL图像和一个灵敏度数字,但我目前将其保留在1上...效果很好。对于一个720p的帧,我需要超过4秒来消除这种溢出。相比之下,关键字处理程序每帧运行约2秒钟。
def despill(img, sensitivity=1):
    """
    Blue limits green.
    """
    start = time.time()
    print '\t[*] Starting despill'
    width, height = img.size
    num_channels = len(img.getbands())
    out = Image.new("RGBA", img.size, color=0)
    for j in range(height):
        for i in range(width):
            #r,g,b,a = data[j,i]
            r,g,b,a = img.getpixel((i,j))
            if g > (b*sensitivity):
                out_g = (b*sensitivity)
            else:
                out_g = g
            # end if

            out.putpixel((i,j), (r,out_g,b,a))
        # end for
    # end for
    out.show()
    print '\t[+] done.'
    print '\t[!] Took: %0.1f seconds' % (time.time()-start)
    exit()
    return out
# end despill

我尝试着将输出的像素值写入到一个numpy数组中,然后将该数组转换为PIL图像,而不是使用putpixel方法。但是这种方式平均需要超过5秒钟...所以这个方法更快一些。我知道putpixel可能不是最快的选项,但我确实没有更好的办法...

1个回答

8

putpixel 很慢,像这样的循环更慢,因为它们由 Python 解释器运行,而解释器非常慢。通常的解决方案是立即将图像转换为 numpy 数组,并使用向量化操作解决问题,在高度优化的 C 代码中运行。在您的情况下,我会这样做:

arr = np.array(img)
g = arr[:,:,1]
bs = arr[:,:,2]*sensitivity
cond = g>bs
arr[:,:,1] = cond*bs + (~cond)*g
out = Image.fromarray(arr)

可能不是很正确,我相信它可以更好地优化,这只是一个草图。


太棒了!速度飞快,谢谢! - Mike Bosland
是的,如果用C语言编写得当,速度可能会快几倍。顺便说一下,公式中有一个错别字,我已经修正了,如果你已经复制了它,应该更新你的代码。 - Matteo Italia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接