【发布时间】:2019-04-01 18:41:56
【问题描述】:
简介。
以前,我 asked a question 将 rgb 三元数转换为四元数。在那个问题之后,我设法得到了单位四元数,但我怀疑它们的内部结构。没有简单的方法来操作它们,并将 luma 和 chroma 分开,因为它们是单位长度的四元数。根据我的感觉,亮度应该以实部或整幅度编码;并且颜色“chroma”信息应该被编码在虚部中。
今天我决定改进,采用另一种方法,不同于上面链接中的第一种方法。我认为它可以成功,因为四元数不仅可以存储旋转(单位四元数),还可以存储缩放。首先,我将开始解释我的下一个想法。我将在以下解释中使用 GLSL 着色器语法。
方法描述和问题主体。
对于图像的某个像素,让我们在单位立方体内设想一个 3D 矢量vec3 u,其中正坐标位于 [0.0, 1.0] 的封闭范围内,并表示完整的 rgb 颜色空间.所以现在u 的坐标、u.x、u.y 和u.z 将相应地表示该像素的红色、绿色和蓝色值。然后让我们取一个纯白色矢量const vec3 v = vec3(1.0, 1.0, 1.0);。让我们定义一些四元数q,这样我们的向量u就是“v,用四元数q旋转和缩放”。简单来说,q 必须回答问题“如何转换v,以便得到最初设想的颜色u?”。让我们介绍一下“旋转和缩放”操作的功能:vec3 q2c(in vec4 q, in vec3 v)。我将其称为“四元数到颜色”转换器。
编写q2c(q, v) 非常简单,just as defined:q2c(q, v) == (q*vec4(v, 0.0))*q'。这里,“*”运算符表示quaternion multiplication;让它成为一个函数vec4 qmul(in vec4 q1, in vec4 q2)。并且“q'”表示q 的conjugate,让它成为vec4 qconj(in vec4 q)。省略它们的简单实现(您可以在完整源代码中找到),我们将使用经典代码:
vec4 q2c(in vec4 q, in vec3 v) {
return qmul(qmul(q, vec4(v, 0.0)), qconj(q));
}
所以现在我们有了 q2c(q,v) 函数,它通过旋转和缩放一些选定的 3D 矢量 v 将四元数 q 转换为颜色。
问题是如何找到那个四元数q?
从程序员的角度来看,目标是编写反向函数vec4 c2q(in vec3 u, in vec3 v)——对应的“颜色到四元数”转换器。
请注意,您不应在没有充分理由的情况下触摸q2c()。例如,其逻辑中存在严重错误,导致“无法解决任务”,您可以证明这一点。
如果你的答案是正确的,你如何检查?
确实,如果您设法来回转换,则检查方法将源于您将获得初始值的事实。所以检查条件是对于任何非零长度v,u 必须始终等于q2c(c2q(u, v), v)。 v 的长度必须非零,因为不能“缩放零”来获得“某物”。
为了方便起见,我准备了 testing program,使用 shadertoy.com 服务。
您需要一台体面的计算机,具有有效的互联网连接和支持 webGL 的网络浏览器(我使用的是 Chrome)。程序应该可以在任何 GPU 上运行,甚至可以嵌入到英特尔的处理器中。它甚至适用于我的低端智能手机!
要测试您的答案,您应该将建议的公式(以 GLSL 语法编写)放入 c2q() 函数中。然后按应用按钮,您的更改将生效:
左边的图像代表一些不变的源像素。右半部分将包含像素,由q2c(c2q()) 来回转换。显然,两半必须在视觉上相等,你不应该注意到任何垂直线。 可能会出现一些小的数学(不明显)错误,但这只是由于浮点的性质 - 它的有限精度和可能的舍入误差。
您可以随意编辑和试验,更改只会在您的计算机上本地完成,您不会破坏任何东西。如果视频在第一次打开时没有播放(shadertoy 错误) - 尝试暂停/取消暂停它。享受吧!
c2q()尝试大厅
如果一切正确,图像的右侧(处理后的)应该等于左侧(原始)。在这里,我将回顾不同的结果,这些结果是通过在 c2q() 实现中放置一些东西而不是 xxxxx 获得的:
vec4 c2q(vec3 u, vec3 v) {
return xxxxx;
}
让我们继续吧!
SE answers 之一:
vec4( cross(u, v), sqrt( dot(u, u) * dot(v, v) ) + dot(u, v) ):在他的提示下“不要忘记规范化 q”:
normalize(vec4( cross(u, v), sqrt( dot(u, u) * dot(v, v) ) + dot(u, v) )):@minorlogic 的评论,似乎更近了一步: 将所有
q的组件按sqrt( length(v)/length(u) )缩放,vec4(cross(u, v), dot(u, v)) * sqrt( length(u)/length(v) ):交换比率:
vec4(cross(u, v), dot(u, v)) * sqrt( length(v)/length(u) ):
【问题讨论】:
-
与链接相比,
qmul存在 (+/-) 差异。 -
@Rabbid76 不是它,而是
q2c()的乘法顺序:q * v * q'与q' * v * q。交换它,您将获得反向旋转和 RGB -> CMY 颜色偏移。我设法在一个小时左右后找到它。此外,规则已更改,问题现在变得更加有趣和互动 ;-) -
@minorlogic 经过测试,出现在“耻辱大厅”部分以及链接问题部分。你有没有试过阅读这个问题?))或者只是搜索 SE,希望重复? ;-p
-
这是描述问题的正确解决方案。所以 1. 检查你的实现是否有错误?测试结果 quat 是否将 "u" 转为 "v" 2. 如果运行良好,验证问题是否正确制定
标签: colors linear-algebra transformation quaternions