Faster method for adjusting PIL pixel values

与世无争的帅哥 提交于 2019-12-01 10:43:22

问题


I'm writing a script to chroma key (green screen) and composite some videos using Python and PIL (pillow). I can key the 720p images, but there's some left over green spill. Understandable but I'm writing a routine to remove that spill...however I'm struggling with how long it's taking. I can probably get better speeds using numpy tricks, but I'm not that familiar with it. Any ideas?

Here's my despill routine. It takes a PIL image and a sensitivity number but I've been leaving that at 1 so far...it's been working well. I'm coming in at just over 4 seconds for a 720p frame to remove this spill. For comparison, the chroma key routine runs in about 2 seconds per frame.

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

Instead of putpixel, I tried to write the output pixel values to a numpy array then convert the array to a PIL image, but that was averaging just over 5 seconds...so this was faster somehow. I know putpixel isn't the snappiest option but I'm at a loss...


回答1:


putpixel is slow, and loops like that are even slower, since they are run by the Python interpreter, which is slow as hell. The usual solution is to convert immediately the image to a numpy array and solve the problem with vectorized operations on it, which run in heavily optimized C code. In your case I would do something like:

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

(it may not be correct and I'm sure it can be optimized way better, this is just a sketch)



来源:https://stackoverflow.com/questions/33181060/faster-method-for-adjusting-pil-pixel-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!