Normal Vector of Three Points

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


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.


@ 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!


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.