使用带条件的numpy快速遍历像素的方法?

2024-05-17 17:16:55 发布

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

def colorize(im, h, s, l_adjust):
    result = Image.new('RGBA', im.size)
    pixin = np.copy(im)
    pixout = np.array(result)

    >>>>>>>>>>>>>>>>> loop <<<<<<<<<<<<<<<<<

    for y in range(pixout.shape[1]):
        for x in range(pixout.shape[0]):
            lum = currentRGB(pixin[x, y][0], pixin[x, y][1], pixin[x, y][2])
            r, g, b = colorsys.hls_to_rgb(h, lum, s)
            r, g, b = int(r * 255.99), int(g * 255.99), int(b * 255.99)
            pixout[x, y] = (r, g, b, 255)

    >>>>>>>>>>>>>>>>>>>>> Loop end <<<<<<<<<<<

    return result

试图从一帧输入视频中找到每像素HSL值,但需要花费1.5秒的时间,但希望将时间至少减少到0.3秒以内。不使用这两个循环有没有更快的方法?寻找类似LUT(查找表)/矢量化/带有NumPy快捷方式的东西来避免这两个循环。谢谢

第二部分->&燃气轮机

如果我将自定义currentRGB()分解为for循环,它看起来像:

def colorize(im, h, s, l_adjust):
    result = Image.new('RGBA', im.size)
    pixin = np.copy(im)
    pixout = np.array(result)
    for y in range(pixout.shape[1]):
        for x in range(pixout.shape[0]):
            currentR, currentG, currentB = pixin[x, y][0]/255 , pixin[x, y][1]/255, pixin[x, y][2]/255
            #luminance
            lum = (currentR * 0.2126) + (currentG * 0.7152) + (currentB * 0.0722)
            if l_adjust > 0:
                lum = lum * (1 - l_adjust)
                lum = lum + (1.0 - (1.0 - l_adjust))
            else:
                lum = lum * (l_adjust + 1)
            l = lum
            r, g, b = colorsys.hls_to_rgb(h, l, s)
            r, g, b = int(r * 255.99), int(g * 255.99), int(b * 255.99)
            pixout[x, y] = (r, g, b, 255)
    return pixout

Tags: inimagefordefnprangeresultint
1条回答
网友
1楼 · 发布于 2024-05-17 17:16:55

您可以使用Numba大大加快计算速度。以下是实施方案:

import numba as nb

@nb.njit('float32(float32,float32,float32)')
def hue_to_rgb(p, q, t):
    if t < 0: t += 1
    if t > 1: t -= 1
    if t < 1./6: return p + (q - p) * 6 * t
    if t < 1./2: return q
    if t < 2./3: return p + (q - p) * (2./3 - t) * 6
    return p

@nb.njit('UniTuple(uint8,3)(float32,float32,float32)')
def hls_to_rgb(h, l, s):
    if s == 0:
        # achromatic
        r = g = b = l
    else:
        q = l * (1 + s) if l < 0.5 else l + s - l * s
        p = 2 * l - q
        r = hue_to_rgb(p, q, h + 1./3)
        g = hue_to_rgb(p, q, h)
        b = hue_to_rgb(p, q, h - 1./3)

    return (int(r * 255.99), int(g * 255.99), int(b * 255.99))

@nb.njit('void(uint8[:,:,::1],uint8[:,:,::1],float32,float32,float32)', parallel=True)
def colorize_numba(pixin, pixout, h, s, l_adjust):
    for x in nb.prange(pixout.shape[0]):
        for y in range(pixout.shape[1]):
            currentR, currentG, currentB = pixin[x, y, 0]/255 , pixin[x, y, 1]/255, pixin[x, y, 2]/255
            #luminance
            lum = (currentR * 0.2126) + (currentG * 0.7152) + (currentB * 0.0722)
            if l_adjust > 0:
                lum = lum * (1 - l_adjust)
                lum = lum + (1.0 - (1.0 - l_adjust))
            else:
                lum = lum * (l_adjust + 1)
            l = lum
            r, g, b = hls_to_rgb(h, l, s)
            pixout[x, y, 0] = r
            pixout[x, y, 1] = g
            pixout[x, y, 2] = b
            pixout[x, y, 3] = 255

def colorize(im, h, s, l_adjust):
    result = Image.new('RGBA', im.size)
    pixin = np.copy(im)
    pixout = np.array(result)
    colorize_numba(pixin, pixout, h, s, l_adjust)
    return pixout

这个优化的并行实现比我的6核机器(在800x600图像上)上的原始代码快约2000倍。hls_to_rgb实现来自this post。注意@nb.njitdecorators中的字符串不是必需的,但它使Numba能够提前编译函数,而不是在第一次调用时编译。有关这些类型的更多信息,请阅读Numba documentation

相关问题 更多 >