通过色彩变换矩阵对RGB阵列进行矢量化处理,以进行图像处理

问题描述 投票:2回答:1

我正在自学使用Python 3进行彩色图像处理(此特定任务为NumPy)。

我有一个3d数组image,代表图像每个像素上的RGB值,因此其形状为(height,width,3)。在每个像素处,我想创建新的RGB值,这些值是该给定像素处原始RGB值的线性组合。我将通过将每个像素的RGB向量乘以W(权重的3x3矩阵)来实现此目的。

我可以使用嵌套的for循环来完成此操作,但是速度很慢:

newRGB = np.zeros((height,width,3))   # make empty array to update with RGB values
for i in range(height):
    for j in range(width):                     
        RGB = image[i,j,:]            # RGB vector at given pixel with size 3 since is [R,G,B]
        new = np.dot(W,RGB)           # W is 3x3 matrix of weights
        newRGB[i,j,:] = new           # put new RGB values into the empty matrix

或者,一种更快的向量化方式是:

image = mpimg.imread('test.png')   # reading image file into matplotlib.image
print(image.shape)                 # image has shape (height,width,3)
W = np.array([...])                # arbitrary 3x3 matrix of weights  
x = np.rollaxis(image,2,1)         # moving the RGB axis to 2nd position
print(x.shape)                     # x has shape (height,3,width)
Wx = np.dot(W,x)                   # matrix multiplication
print(Wx.shape)                    # Wx has shape (3,height,width)
y = np.rollaxis(Wx,0,3)            # moving RGB axis back to 3rd position to have image shape
print(y.shape)                     # y has shape (height,width,3) like original image

是否有较不麻烦的方法,例如通过使用numpy.tensordot()?

或者,由于我采用RGB值的线性组合,是否可以通过在FFT空间中执行简单的逐元素乘法来创建某种3D线性滤波器并将其与图像卷积?

现在,我的图像约为1000x1000像素,因此RGB阵列的形状大致为(1000,1000,3)。但是我也对可能具有更大数组(或更大维度)的其他应用程序的矢量化感兴趣,因此,也欢迎与更大数组大小和维度有关的答案。

python image numpy vectorization rgb
1个回答
2
投票

是,您可以使用np.tensordotnp.einsum

In [9]: np.tensordot(image, W, ([2], [1])).shape
Out[9]: (1000, 1000, 3)

In [13]: np.einsum('ijk,lk->ijl', image, W).shape
Out[13]: (1000, 1000, 3)


In [19]: x = np.rollaxis(image,2,1)

In [20]: Wx = np.dot(W,x)

In [21]: y = np.rollaxis(Wx,0,3)

In [22]: np.allclose(np.tensordot(image, W, ([2], [1])), y)
Out[22]: True

In [14]: np.allclose(np.tensordot(image, W, ([2], [1])), np.einsum('ijk,lk->ijl', image, W))
Out[14]: True

在这两种情况中,np.tensordot似乎是更快的方法。

In [15]: %timeit np.einsum('ijk,lk->ijl', image, W)
10 loops, best of 3: 31.1 ms per loop

In [16]: %timeit np.tensordot(image, W, ([2], [1]))
100 loops, best of 3: 18.9 ms per loop
© www.soinside.com 2019 - 2024. All rights reserved.