scikit-image逐像素操作

时间:2017-03-31 12:19:57

标签: python numpy scikit-image

我需要读取图像,然后对每个像素执行一个功能,然后将其另存为新图像。我使用scikit-image作为第一部分和最后一部分(阅读和写作),但我很难快速完成第二次操作(实际转换)。

scikit-image中的读取操作的结果是形状(WIDTH,HEIGHT,N_CHANNELS)的numpy数组,其中WIDTH和HEIGHT是图像,N_CHANNELS是3或4.我需要应用这样的函数将像素从[R,G,B]转换为[R - B,G - B,B - R]的像素分别为每个像素。

我花了几天时间试图让这个工作,但到目前为止我唯一可行的解​​决方案是遍历每一行和每一行并执行计算。这需要很长时间才能完成。

我试图对数组进行矢量化,但结果是一维数组,并且不可能使用它。有没有其他高效的方法来完成这项工作?

def calculate_ndvi(nir, red):
    if red == 0 and nir == 0:
        return 0.5
    else:
        num = int(nir) - int(red)
        den = int(nir) + int(red)
        return num / den


zero_uint = numpy.uint8(0)


def process_color(clr):
    ndvi = calculate_ndvi(clr[2], clr[0])
    return [-ndvi, ndvi, zero_uint]


def save_ndvi_file():
    image = io.imread(input_path)

    rows = image.shape[0]
    cols = image.shape[1]

    out = numpy.empty(shape=(rows, cols, 3))
    for i in range(rows):
        for j in range(cols):
            out[i][j] = process_color(image[i][j])

    io.imsave('output.jpg', out)

1 个答案:

答案 0 :(得分:2)

您可以使用多维广播操作来对此进行矢量化。以下是您的函数版本,它以矢量化方式执行所有操作:

def save_ndvi_file():
    image = io.imread(input_path)

    nir = image[:, :, 2]
    red = image[:, :, 0]
    ndvi = (nir - red) / (nir + red)
    ndvi[(nir == 0) & (red == 0)] = 0.5
    out = ndvi[:, :, np.newaxis] * np.array([[[-1, 1, 0]]])

    io.imsave('output.jpg', out)

请注意,您已经循环的所有内容现在都是通过广播的numpy操作完成的,而不是通过循环外部函数调用。以这种方式编写代码需要稍微不同的思考算法的方式,但是一旦习惯了它就会非常直观。