三点法线向量

发布于 2024-08-17 07:17:19 字数 527 浏览 8 评论 0 原文

嘿数学极客们,我有一个问题困扰了我一段时间。这是一个个人项目。

我有三个点:红、绿、蓝。它们位于纸板条上,红点位于左下角 (0,0),蓝点位于右下角 (1,0),绿点位于左上方。想象一下退后一步,从某个角度拍摄卡片的照片。如果您要找到图片中每个点的中心(假设单位是像素),您将如何找到图片中卡片正面的法线向量(相对于相机)?

现在我对这个问题了解了一些事情:

  1. 这些点(在“现实生活”中)总是成直角。在图片中,只有当相机沿着“轴”(轴是由红色和蓝色或红色和绿色点创建的线)围绕红点旋转时,它们才处于直角。
  2. 卡片仅一侧有点。因此,您知道您永远不会看到它的背面。
  3. 卡与相机的距离无关。如果我知道每个点的深度,这会容易得多(只是一个简单的叉积,不是吗?)。
  4. 卡的旋转与我正在寻找的内容无关。在我一直在尝试解决这个问题的修补中,最终可以在法线向量的帮助下找到旋转。我不知道旋转是否是寻找法线向量的一部分(或乘积)。

希望有人做到了这一点或者是数学天才。我有两个朋友在这里帮助我,但到目前为止我们还没有成功。

Hey math geeks, I've got a problem that's been stumping me for a while now. It's for a personal project.

I've got three dots: red, green, and blue. They're positioned on a cardboard slip such that the red dot is in the lower left (0,0), the blue dot is in the lower right (1,0), and the green dot is in the upper left. Imagine stepping back and taking a picture of the card from an angle. If you were to find the center of each dot in the picture (let's say the units are pixels), how would you find the normal vector of the card's face in the picture (relative to the camera)?

Now a few things I've picked up about this problem:

  1. The dots (in "real life") are always at a right angle. In the picture, they're only at a right angle if the camera has been rotated around the red dot along an "axis" (axis being the line created by the red and blue or red and green dots).
  2. There are dots on only one side of the card. Thus, you know you'll never be looking at the back of it.
  3. The distance of the card to the camera is irrelevant. If I knew the depth of each point, this would be a whole lot easier (just a simple cross product, no?).
  4. The rotation of the card is irrelevant to what I'm looking for. In the tinkering that I've been doing to try to figure this one out, the rotation can be found with the help of the normal vector in the end. Whether or not the rotation is a part of (or product of) finding the normal vector is unknown to me.

Hope there's someone out there that's either done this or is a math genius. I've got two of my friends here helping me on it and we've--so far--been unsuccessful.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

万劫不复 2024-08-24 07:17:19

我在旧版本的 MathCAD 中解决了这个问题:

alt text

编辑:MathCAD 屏幕截图中的措辞错误:“已知:gb彼此垂直”

在MathCAD中,我忘记了进行叉积的最后一步,我将从我之前的答案中复制粘贴到这里:

现在我们已经解决了 XYZ 的问题
翻译后的 g 和 b 点,你的
原来的问题想要正常的
飞机。

如果交叉g x b,我们将得到
垂直于两者的向量:

<前> <代码> | u1 u2 u3 |
gxb = | g1 g2 g3 |
| b1 b2 b3 |

= (g2b3 - b2g3)u1 + (b1g3 - b3g1)u2 + (g1b2 - b1g2)u3

所有值都是已知的,将它们代入
(我不会写出带有g3的版本
和 b3 替换,因为它只是
太长太丑了,没有什么帮助。

但实际上,我认为你必须用数字来解决它,调整 gzbz以便最适合条件:

g · b = 0

|g| = |b|

因为像素在代数上并不完美。

示例

使用阿波罗 13 号宇航员在 LEM 中安装一个方形氢氧化锂罐的照片,我找到了角落:

alt text

使用它们作为 XY 平面的基础:

alt text

我使用 Photoshop 记录了像素位置,正 X 向右,正 Y 向下(以保持 Z 的右手定则“进入”图片):

g = (79.5, -48.5, gz)

b = (-110.8, -62.8, bz)

将两个起始公式输入 Excel,并使用分析工具包通过调整 gzb 来“最小化”错误z,它得出了两个 Z 值:

g = (79.5, -48.5, 102.5)

b = (-110.8, -62.8, 56.2)

然后我可以计算其他有趣的值。

gb 的长度(以像素为单位):

|g| = 138.5

|b| = 139.2

法向量:

g x b = (3710, -15827, -10366)

单位法线(长度 1):

uN = (0.1925, -0.8209, -0.5377)

正常缩放至与 gb< 相同的长度(以像素为单位) /strong>(138.9):

正常 = (26.7, -114.0, -74.7)

现在我的法线长度与 gb 相同,我将它们绘制在同一张图片上:

< a href="https://i.sstatic.net/OWOIJ.png" rel="nofollow noreferrer">替代文本

我认为您将遇到一个新问题:相机镜头引起的失真。这三个点没有完美地投影到二维摄影平面上。球面扭曲使直线不再是直的,使相等的长度不再相等,并使法线稍微偏离法线。

微软研究有一个算法来找出如何校正相机的失真:

一种灵活的相机校准新技术

但这超出了我的范围:

我们提出了一种灵活的新技术
轻松校准相机。很好
适合无需专业人士使用
3D 几何或计算机知识
想象。该技术只需要
相机观察平面图案
显示在几个(至少两个)
不同的方向。要么
相机或平面图案可以
自由移动。该动议不必是
已知。径向透镜畸变为
建模。拟议的程序
由封闭式解决方案组成,
随后进行非线性细化
基于最大似然
标准。两者均采用计算机模拟
并用真实数据进行了测试
所提出的技术,非常好
已取得结果。比较的
与使用经典技术
昂贵的设备,例如两个或
三个正交平面,建议
技术易于使用且灵活。
它推动了 3D 计算机视觉的发展
从实验室环境一步步到
现实世界的使用。

他们有一个示例图像,您可以在其中看到变形:

alt 文本
(来源:microsoft.com< /a>)

注意

  • 你不知道你看到的是纸板的“顶部”还是“底部”,所以法线可以垂直镜像(即 z = -z)

更新

Guy 在导出的代数公式中发现了一个错误。修复它会导致我认为公式没有简单的封闭形式。这还算不错,因为无论如何都无法完全解决它;但从数字上来说。

这是 Excel 的屏幕截图,其中我从两个已知规则开始:

g · b = 0

|g| = |b|

将第二个写为差异(“错误”量),然后您可以将两者相加并将该值用作数字以使 Excel 的求解器最小化

alt text

这意味着您必须编写自己的数值迭代求解器。我正盯着大学的工程师数值方法教科书;我知道它包含求解没有简单封闭形式的递归方程的算法。

i worked it out in my old version of MathCAD:

alt text

Edit: Wording wrong in screenshot of MathCAD: "Known: g and b are perpendicular to each other"

In MathCAD i forgot the final step of doing the cross-product, which i'll copy-paste here from my earlier answer:

Now we've solved for the X-Y-Z of the
translated g and b points, your
original question wanted the normal of
the plane.

If cross g x b, we'll get the
vector normal to both:

        | u1  u2  u3 |
g x b = | g1  g2  g3 |
        | b1  b2  b3 |  

      = (g2b3 - b2g3)u1 + (b1g3 - b3g1)u2 + (g1b2 - b1g2)u3

All the values are known, plug them in
(i won't write out the version with g3
and b3 substituted in, since it's just
too long and ugly to be helpful.

But in practical terms, i think you'll have to solve it numerically, adjusting gz and bz so as to best fit the conditions:

g · b = 0

and

|g| = |b|

Since the pixels are not algebraically perfect.

Example

Using a picture of the Apollo 13 astronauts rigging one of the command module's square Lithium Hydroxide cannister to work in the LEM, i located the corners:

alt text

Using them as my basis for an X-Y plane:

alt text

i recorded the pixel locations using Photoshop, with positive X to the right, and positive Y down (to keep the right-hand rule of Z going "into" the picture):

g = (79.5, -48.5, gz)

b = (-110.8, -62.8, bz)

Punching the two starting formulas into Excel, and using the analysis toolpack to "minimize" the error by adjusting gz and bz, it came up with two Z values:

g = (79.5, -48.5, 102.5)

b = (-110.8, -62.8, 56.2)

Which then lets me calcuate other interesting values.

The length of g and b in pixels:

|g| = 138.5

|b| = 139.2

The normal vector:

g x b = (3710, -15827, -10366)

The unit normal (length 1):

uN = (0.1925, -0.8209, -0.5377)

Scaling normal to same length (in pixels) as g and b (138.9):

Normal = (26.7, -114.0, -74.7)

Now that i have the normal that is the same length as g and b, i plotted them on the same picture:

alt text

i think you're going to have a new problem: distortion introduced by the camera lens. The three dots are not perfectly projected onto the 2-dimensional photographic plane. There's a spherical distortion that makes straight lines no longer straight, makes equal lengths no longer equal, and makes the normals slightly off of normal.

Microsoft research has an algorithm to figure out how to correct for the camera's distortion:

A Flexible New Technique for Camera Calibration

But it's beyond me:

We propose a flexible new technique to
easily calibrate a camera. It is well
suited for use without specialized
knowledge of 3D geometry or computer
vision. The technique only requires
the camera to observe a planar pattern
shown at a few (at least two)
different orientations. Either the
camera or the planar pattern can be
freely moved. The motion need not be
known. Radial lens distortion is
modeled. The proposed procedure
consists of a closed-form solution,
followed by a nonlinear refinement
based on the maximum likelihood
criterion. Both computer simulation
and real data have been used to test
the proposed technique, and very good
results have been obtained. Compared
with classical techniques which use
expensive equipments such as two or
three orthogonal planes, the proposed
technique is easy to use and flexible.
It advances 3D computer vision one
step from laboratory environments to
real world use.

They have a sample image, where you can see the distortion:

alt text
(source: microsoft.com)

Note

  • you don't know if you're seeing the "top" of the cardboard, or the "bottom", so the normal could be mirrored vertically (i.e. z = -z)

Update

Guy found an error in the derived algebraic formulas. Fixing it leads to formulas that i, don't think, have a simple closed form. This isn't too bad, since it can't be solved exactly anyway; but numerically.

Here's a screenshot from Excel where i start with the two knowns rules:

g · b = 0

and

|g| = |b|

Writing the 2nd one as a difference (an "error" amount), you can then add both up and use that value as a number to have excel's solver minimize:

alt text

This means you'll have to write your own numeric iterative solver. i'm staring over at my Numerical Methods for Engineers textbook from university; i know it contains algorithms to solve recursive equations with no simple closed form.

从声音来看,您有三个点 p1p2p< sub>3 定义一个平面,并且您想要找到该平面的法向量。

将点表示为来自原点的向量,法线向量方程 将是
n = (p2 - p1)x(p 3 - p1
(其中 x 是两个向量的叉积)

如果您希望向量从卡片的正面指向外部,则使用右手定则,设置
p1 = 红点(左下)
p2 = 蓝色(右下)点
p3 = 绿色(左上角)点

From the sounds of it, you have three points p1, p2, and p3 defining a plane, and you want to find the normal vector to the plane.

Representing the points as vectors from the origin, an equation for a normal vector would be
n = (p2 - p1)x(p3 - p1)
(where x is the cross-product of the two vectors)

If you want the vector to point outwards from the front of the card, then ala the right-hand rule, set
p1 = red (lower-left) dot
p2 = blue (lower-right) dot
p3 = green (upper-left) dot

许一世地老天荒 2024-08-24 07:17:19

@ Ian Boyd ...我喜欢你的解释,只是当你说解决 bz 时,我陷入了步骤 2。您的答案中仍然包含 bz,我认为您的答案中不应该包含 bz答案...

bz 应该是 gx2 + g 的 +/- 平方根y2 + gz2 - bx2 - by2

我自己做了之后,发现很难替代bz<当您求解 gz 时,将 /strong> 代入第一个方程,因为当替换 bz 时,您现在将得到:

gz = -(gxbx + gyby) / sqrt( gx2 + gy2 + gz2 - bx2 - by2

使这变得困难的部分是平方根中有gz,所以你必须将它分开并将gz组合在一起,并求解 gz 我这样做了,只是我不认为我解决它的方法是正确的,因为当我编写程序来计算 g z 对我来说,我使用了你的gxgy 值看看我的答案是否与你的相符,但事实并非如此。

所以我想知道你是否可以帮助我,因为我真的需要让它为我的一个项目工作。谢谢!

@ Ian Boyd...I liked your explanation, only I got stuck on step 2, when you said to solve for bz. You still had bz in your answer, and I don't think you should have bz in your answer...

bz should be +/- square root of gx2 + gy2 + gz2 - bx2 - by2

After I did this myself, I found it very difficult to substitute bz into the first equation when you solved for gz, because when substituting bz, you would now get:

gz = -(gxbx + gyby) / sqrt( gx2 + gy2 + gz2 - bx2 - by2 )

The part that makes this difficult is that there is gz in the square root, so you have to separate it and combine the gz together, and solve for gz Which I did, only I don't think the way I solved it was correct, because when I wrote my program to calculate gz for me, I used your gx, and gy values to see if my answer matched up with yours, and it did not.

So I was wondering if you could help me out, because I really need to get this to work for one of my projects. Thanks!

踏雪无痕 2024-08-24 07:17:19

只是在这里思考。

您的有效输入是表观比率 RB/RG [+]、表观角度 BRG 以及(比如说)RB 与屏幕坐标 y 轴形成的角度(我错过了什么吗)。你需要标准化法线(嘿!)向量的分量,我相信这只是两个独立的值(尽管如果卡片是透明的,你会留下前后模糊性)。[++]

所以我猜测这是可能的...

从这里开始,我假设 RB 的视角始终为 0,稍后我们可以围绕 z 轴旋转最终的解。

首先将卡片放置在与观察平面平行的位置,并以“自然”方式定向(即,尊重上、下、左、右分配)。我们可以通过围绕初始 x 轴旋转 \theta 来到达卡片上所有有趣的位置(对于 -\pi/2 < \theta < \pi/2 code>),然后绕初始 y 轴旋转 \phi(对于 -\pi/2 < \phi < \pi/2)。请注意,我们保留了 RB 向量的表观方向。

下一步根据 \theta\phi 计算表观比率和表观角度,并将结果反转。[+++]

法线将为 R_y (\phi)R_x(\theta)(0, 0, 1)R_i 绕轴 i 的原始旋转矩阵。

[+] 绝对长度不计算在内,因为它只是告诉您到卡的距离。

[++] 又一个假设:卡片到视平面的距离远大于卡片的尺寸。

[+++] 这里您使用的从三维空间到观察平面的投影很重要。这是最困难的部分,但我们无法为您做任何事情,除非您说明您正在使用什么投影。如果您使用的是真实相机,那么这就是透视投影,并且基本上任何有关 3D 图形的书籍都会对此进行介绍。

Just thinking on my feet here.

Your effective inputs are the apparent ratio RB/RG [+], the apparent angle BRG, and the angle that (say) RB makes with your screen coordinate y-axis (did I miss anything). You need out the components of the normalized normal (heh!) vector, which I believe is only two independent values (though you are left with a front-back ambiguity if the card is see through).[++]

So I'm guessing that this is possible...

From here on I work on the assumption that the apparent angle of RB is always 0, and we can rotate the final solution around the z-axis later.

Start with the card positioned parallel to the viewing plane and oriented in the "natural" way (i.e. you upper vs. lower and left vs. right assignments are respected). We can reach all the interesting positions of the card by rotating by \theta around the initial x-axis (for -\pi/2 < \theta < \pi/2), then rotating by \phi around initial y-axis (for -\pi/2 < \phi < \pi/2). Note that we have preserved the apparent direction of the RB vector.

Next step compute the apparent ratio and apparent angle after in terms of \theta and \phi and invert the result.[+++]

The normal will be R_y(\phi)R_x(\theta)(0, 0, 1) for R_i the primitive rotation matrix around axis i.

[+] The absolute lengths don't count, because that just tells you the distance to card.

[++] One more assumption: that the distance from the card to view plane is much large than the size of the card.

[+++] Here the projection you use from three-d space to the viewing plane matters. This is the hard part, but not something we can do for you unless you say what projection you are using. If you are using a real camera, then this is a perspective projection and is covered in essentially any book on 3D graphics.

梦言归人 2024-08-24 07:17:19

是的,法线向量不会随距离变化,但纸板在图片上的投影会随距离变化(简单:如果你有一块小纸板,则不会发生任何变化。
如果您有一块 1 英里宽、1 英里高的纸板,并旋转它,使一侧更近,另一侧更远,则图片上的近侧会被放大,远侧会被缩短。您可以立即看到,矩形不再是矩形,而是梯形)

对于小角度和相机位于中间的最准确的方法是测量“正常”图像和角度图像之间的宽度/高度之比在中间线上(因为它们没有扭曲)。

我们将 x 定义为从左到右,y 定义为从下到上,z 定义为从远到近。

然后
x = arcsin(measuredWidth/normWidth) 红-蓝
y = arcsin(measuredHeight/normHeight) 红绿
z = sqrt(1.0-x^2-y^2)

我明天会计算一个更精确的解决方案,但我现在太累了......

right, the normal vector does not change by distance, but the projection of the cardboard on a picture does change by distance (Simple: If you have a small cardboard, nothing changes.
If you have a cardboard 1 mile wide and 1 mile high and you rotate it so that one side is nearer and the other side more far away, the near side is magnified and the far side shortened on the picture. You can see that immediately that an rectangle does not remain a rectangle, but a trapeze)

The mostly accurate way for small angles and the camera centered on the middle is to measure the ratio of the width/height between "normal" image and angle image on the middle lines (because they are not warped).

We define x as left to right, y as down to up, z as from far to near.

Then
x = arcsin(measuredWidth/normWidth) red-blue
y = arcsin(measuredHeight/normHeight) red-green
z = sqrt(1.0-x^2-y^2)

I will calculate tomorrow a more exact solution, but I'm too tired now...

梓梦 2024-08-24 07:17:19

您可以使用 u,v,n 坐标。将您的视点设置为“眼睛”或“相机”的位置,然后将您的 x、y、z 坐标转换为 u、v、n。从那里您可以确定法线,以及透视和可见表面(如果需要的话)(u',v',n')。另外,请记住 2D = 3D,且 z=0。最后,确保使用齐次坐标。

You could use u,v,n co-oridnates. Set your viewpoint to the position of the "eye" or "camera", then translate your x,y,z co-ordinates to u,v,n. From there you can determine the normals, as well as perspective and visible surfaces if you want (u',v',n'). Also, bear in mind that 2D = 3D with z=0. Finally, make sure you use homogenious co-ordinates.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文