I had a chance to work out some easier equations last night when my daughter borrowed my computer as a render mule for her video project, leaving me only with a pad of paper....
By definition:
SlopeH = x/z
SlopeV = y/z
From the camera baseline value (40mm) we also know:
xLeft - 20mm = xRight + 20mm
And we know that z
is the same for both cameras.
Substituting in the slope values for the two cameras to find z:
z * SlopeHLeft - 20 = z * SlopeHRight + 20
and working things out:
z = 40/(SlopeHRight - SlopeHLeft)
x = z * SlopeHLeft + 20 = z * SlopeHRight - 20
y = z * SlopeVLeft = z * SlopeVRight
Note that the x, y, z coordinates we have been using are relative to the camera coordinate system, not the Leap Motion coordinate system. To get the coordinate in Leap coordinates:
xLeap = xCamera
yLeap = -zCamera
zLeap = yCamera
And a code example. This code takes the finger tips, calculates the pixel in the camera images that where the finger tip is located. It then gets the slopes from those pixel locations using rectify()
and then recalculates the 3D positions (kind of pointless except for testing the math from end to end):
Leap::FingerList frameFingers = frame.fingers();
for(Leap::FingerList::const_iterator fl = frameFingers.begin(); fl != frameFingers.end(); fl++)
{
//Convert finger tip position to a ray from the camera POV
Leap::Vector tip = (*fl).tipPosition();
int i = 0;
float horizontal_slope_left = -(tip.x + 20 * (2 * i - 1))/tip.y;
float vertical_slope_left = -tip.z/tip.y;
i = 1;
float horizontal_slope_right = -(tip.x + 20 * (2 * i - 1))/tip.y;
float vertical_slope_right = -tip.z/tip.y;
Leap::Image image_left = frame.images()[0];
Leap::Image image_right = frame.images()[1];
Leap::Vector warped_left = image_left.warp(Leap::Vector(horizontal_slope_left, vertical_slope_left,0));
Leap::Vector warped_right = image_right.warp(Leap::Vector(horizontal_slope_right, vertical_slope_right,0));
Leap::Vector slopes_left = image_left.rectify(warped_left);
Leap::Vector slopes_right = image_right.rectify(warped_right);
//Do the triangulation from the rectify() slopes
std::cout << "Triangulate with rectified slopes: " << std::endl;
float z = 40/(slopes_right.x - slopes_left.x);
float y = z * slopes_right.y;
float x = z * slopes_right.x - 20;
Leap::Vector position = Leap::Vector(x, -z, y);
std::cout << "Tip: " << tip << " calculated: " << position << std::endl;
std::cout << "#############################" << std::endl;
}