3x3无循环矩阵转换(RGB颜色转换)

时间:2011-11-04 14:38:55

标签: python image-processing numpy

我通过PIL将RGB图像加载到numpy数组中。我得到一行x cols x 3数组。经过修修补补后,我得到了以下代码。我想学习如何在没有循环的情况下进行这样的数组/矩阵操作。

# Note using matrix not array.
rgb_to_ycc = np.matrix(
     (0.2990,  0.5870,  0.1140,
    -0.1687, -0.3313,  0.5000,
     0.5000, -0.4187, -0.0813,)
).reshape( 3,3 )

ycc_to_rgb = np.matrix(
    ( 1.0, 0.0, 1.4022,
      1.0, -0.3456, -0.7145,
      1.0, 1.7710, 0, )
).reshape( 3, 3 )

def convert_ycc_to_rgb( ycc ) :
    # convert back to RGB
    rgb = np.zeros_like( ycc )
    for row in range(ycc.shape[0]) :
        rgb[row] = ycc[row] * ycc_to_rgb.T
    return rgb

def convert_rgb_to_ycc( rgb ) :
    ycc = np.zeros_like( rgb )
    for row in range(rgb.shape[0]):
        ycc[row] = rgb[row] * rgb_to_ycc.T
    return ycc

我可以使用http://pypi.python.org/pypi/colormath(通过Using Python to convert color formats?),但我正在使用它来练习学习numpy。

前面提到的Colormath库使用点积。

# Perform the adaptation via matrix multiplication.
result_matrix = numpy.dot(var_matrix, rgb_matrix)

我的数学不是应该的。 np.dot()是我最好的选择吗?

EDIT。在深入阅读colormath的apply_RGB_matrix() - color_conversions.py后,我发现如果我的转换3x3s 不是矩阵,则np.dot()有效。奇怪的。

def convert_rgb_to_ycc( rgb ) :
    return np.dot( rgb, np.asarray( rgb_to_ycc ).T )

2 个答案:

答案 0 :(得分:4)

我不确定您使用的公式convert RGB to YCC,所以我不想声称这是完整的计算,但为了简化您发布的功能,是的,使用{{1}使用numpy数组而不是numpy矩阵。

np.dotnp.dot使用numpy矩阵更通用。当使用具有numpy矩阵的*时,两个矩阵必须是2维的。 但是*可以生成具有不同形状的数组的结果。这对于您的应用非常重要,因为np.dot是三维的(例如,当它具有形状(1470,2105,3)时)。

rgb的文档说:

np.dot

这是常规矩阵乘法的推广。


我建议调用你的终极函数 For N dimensions it is a sum product over the last axis of `a` and the second-to-last of `b`:: dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m]) ,而不是将该指定赋给常量矩阵。 (它更短,并准确说出你想要的功能。)

下面,rgb_to_ycc是我建议的函数,我做了一些小修改,使rgb_to_ycc不会引发异常,并进行我认为你想要的计算。

最后一行convert_rgb_to_ycc显示两个函数返回相同的结果。

np.allclose(...)

答案 1 :(得分:3)

def convert_ycc_to_rgb(ycc):
    return ycc * ycc_to_rgb.T

def convert_rgb_to_ycc(rgb):
    return rgb * rgb_to_ycc.T

就这么简单,记住矩阵乘法是如何根据行和列的内积定义的。

修改

我假设rgb和ycc矩阵只是一个矩阵,其行数与像素数相同,每个颜色组件有一列。所以我们首先需要做的是将它们重新塑造为(rows*cols,3),然后再转回(rows, cols, 3)

所以代码最终是:

def convert_ycc_to_rgb(ycc):
    shape = ycc.shape
    return np.array(ycc.reshape(-1,3) * ycc_to_rgb.T).reshape(shape)

def convert_rgb_to_ycc(rgb):
    shape = rgb.shape
    return np.array(rgb.reshape(-1,3) * rgb_to_ycc.T).reshape(shape)