首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这个Python/numpy代码如何实现XYZ->rgb颜色空间转换的白色缩放?

这个Python/numpy代码如何实现XYZ->rgb颜色空间转换的白色缩放?
EN

Stack Overflow用户
提问于 2018-02-13 21:49:01
回答 1查看 210关注 0票数 0

我正在阅读本指南关于将光谱转换为rgb颜色坐标的内容。

我基本上理解代数在做什么,但是作者并没有真正解释处理白点的代数,我也不能阅读Python/numpy代码来完成这项工作。

代码语言:javascript
复制
import numpy as np

class ColourSystem:

    def __init__(self, red, green, blue, white):

        self.red, self.green, self.blue = red, green, blue
        self.white = white

        # The chromaticity matrix (rgb -> xyz) and its inverse
        self.M = np.vstack((self.red, self.green, self.blue)).T 
        self.MI = np.linalg.inv(self.M)

        # White scaling array
        self.wscale = self.MI.dot(self.white)

        # xyz -> rgb transformation matrix
        self.T = self.MI / self.wscale[:, np.newaxis]

最后两句话让我迷惑了。我的解释是self.white是一个列向量,所以self.MI.dot(self.white)是一个矩阵向量乘法,产生另一个列向量。

但在这种解释中,最后一行读起来就像将矩阵除以向量,这对我来说是毫无意义的。

最后一行是如何通过修改rgb->xyz矩阵的逆来生成xyz->rgb矩阵的?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-14 10:44:30

很抱歉,这是对评论的回答,而不是对原始问题的回答,但是很长,而且有一些代码,所以它不适合这样做。让我重写一个自包含的代码片段,它执行您要求的相同操作(从您提供的链接中获取初始化编号):

代码语言:javascript
复制
import numpy as np
def xyz_from_xy(x, y):
    """Return the vector (x, y, 1-x-y)."""
    return np.array((x, y, 1-x-y))

red=xyz_from_xy(0.67, 0.33)
green=xyz_from_xy(0.21, 0.71)
blue=xyz_from_xy(0.15, 0.06)
white=xyz_from_xy(0.3127, 0.3291)

# The chromaticity matrix (rgb -> xyz) and its inverse
M = np.vstack((red, green, blue)).T 
MI = np.linalg.inv(M)
# White scaling array
wscale = MI.dot(white)
# xyz -> rgb transformation matrix
T = MI / wscale[:, np.newaxis]

在T中写入的值是以下矩阵:

数组([ 6.20584986,-1.71746142,-1.04788582, -2.71554014,5.51336937,0.0968 7197 ( 0.19384968,-0.39357359,2.9841102 ])

现在,这个数字是如何计算的,广播又是如何计算的呢?

正如名称“v堆栈”所示,M只是将红色、绿色和蓝色向量叠加在一起:

数组([ 6.70000000e-01,2.100000e-01,1.50000000e-01, 3.3000000e-01,7.100000e-01,6.0000e-02, -5.55111512e-17、8.000000E-02、7.90000000e-01]

(根据函数xyz_from_xy,最后一个组件总是只有一个减去前两个的和)。MI是相反的:

数组([ 1.72809198,-0.47824736,-0.29179615, -0.81013052,1.64481044,0.02889994 ( 0.08203853,-0.16656308,1.26289621])

而且,正如您正确地提到的,wscale只是一个向量(一维),它是MIwhite=array([0.3127, 0.3291, 0.3582])的标量乘积。

数组(0.27846178,0.29833126,0.42320696)

现在,开始广播。首先,wscale[:, np.newaxis]和wscale是完全一样的,但是用(3,1)形状进行了整形。

数组([0.27846178, 0.29833126, ( 0.42320696])

(同样的效果可以通过写作实现:wscale.reshape(3,1))。当你在MI (有形状(3,3))和另一个对象(形状(3,1))之间做算术运算时,不管它是和,乘法,除法,甚至是一些看起来更奇怪的事情,比如**,它只是对元素做这样的操作。但是,由于维度不同,它试图“广播”,即通过多次重复相同的向量,使等于1的每个维度与另一个对象(在本例中为3)中的相应维数相等。显式地,您将MI元素除以水平重复wscale三次获得的矩阵。您可以通过编写更详细的方式获得相同的结果:

代码语言:javascript
复制
T = MI / np.hstack((wscale.reshape(3,1), wscale.reshape(3,1), wscale.reshape(3,1)))

如果您想要像点积那样执行矩阵运算,则需要显式地编写MI.dot(wscale[:, np.newaxis]) (在本例中,这将返回(3,1)形状的张量)。但这不是我们所做的:T = MI / wscale[:, np.newaxis]的结果是:

数组([ 6.20584986,-1.71746142,-1.04788582, -2.71554014,5.51336937,0.0968 7197 ( 0.19384968,-0.39357359,2.9841102 ])

这只是将MI的任何列按元素除以wscale的结果。例如,看看第一个例子,如果我们做了MI[:,0] / wscale,我们确实可以得到:

数组( 6.20584986,-2.71554014,0.19384968)

即第一栏。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48776200

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档