Kinect depth conversion from mm to pixels - kinect

Does anybody knows how many pixels correspond for each millimeter of depth value in images taken from kinect for xbox360?
I'm using the standard resolution and settings...
Thanks!

1 pixel corresponds to a number of millimiters that depends on the depth value of that pixels (i.e. its level of gray).
The simplest way you can get the distance between two pixels in a depth image is to convert those pixels (which are expressed in Depth Space) in real world coordinates (i.e. in Skeleton Space)1. Then, you can calculate the distance between those points using a common euclidean distance formula.
So if you have two pixels P1 and P2, with depth values
respectively equal to D1 and D2, you can proceed as follows:
DepthImagePoint dip1 = new DepthImagePoint();
dip1.X = P1.x;
dip1.Y = P1.y;
dip1.Depth = D1;
DepthImagePoint dip2 = new DepthImagePoint();
dip2.X = P2.x;
dip2.Y = P2.y;
dip2.Depth = D2;
SkeletonPoint sp1 = CoordinateMapper.MapDepthPointToSkeletonPoint(DepthImageFormat.Resolution640x480Fps30, dip1);
SkeletonPoint sp2 = CoordinateMapper.MapDepthPointToSkeletonPoint(DepthImageFormat.Resolution640x480Fps30, dip2);
double dist = euclideanDistance(sp1, sp2);
1 See Coordinate Spaces for more information.

Related

Vulkan calculation of Barycentric coordinates? Is area function 2D or 3D?

In section 25.8.1 Basic Polygon Rasterization of the Vulkan spec it says:
Barycentric coordinates are a set of three numbers, a, b, and c, each in the range [0,1], with a + b + c
= 1. These coordinates uniquely specify any point p within the triangle or on the triangle’s
boundary as
p = a * p_a + b * p_b + c * p_c
where p_a , p_b , and p_c are the vertices of the triangle. a, b, and c are determined by:
a = A(p, p_b, p_c) / A(p_a, p_b, p_c)
b = A(p, p_a, p_c) / A(p_a, p_b, p_c)
c = A(p, p_a, p_b) / A(p_a, p_b, p_c)
where A(l,m,n) denotes the area in framebuffer coordinates of the triangle with vertices l, m, and n.
Framebuffer coordinates technically have three components. This is specified in 24.5 Controlling the Viewport as:
The vertex’s framebuffer coordinates (x_f , y_f , z_f ) are given by [snip]
What precisely is the formula of the A function?
Is it either:
(a) the same as the formula given to calculate whether the triangle is back-facing or front-facing in 25.8.1, namely:
a = -0.5 * sum_i(x_f[i] * y_f[i+1] - x_f[i+1] * y_f[i])
That is, is it taken as read that the forumla of A does not use the z_f components of its arguments, and is purely a function of the (x_f, y_f) components? (ie It is calculating the area of the two dimensional projection of the triangle onto the x-y plane in framebuffer-space)
or (b), does A use all three framebuffer components? ie Does A return the area of the triangle in the full three-dimensional framebuffer-space (like shown here for example)
or (c) something else?
It actually doesn't matter, mathematically speaking. Whichever function you pick, you'll find that the particulars of the math divide out when computing the barycentric coordinate.
A barycentric coordinate is computed by taking the ratio of two areas. If you linearly project two co-planar triangles from 3D space to 2D space with the same projection, the ratio of their areas is unchanged (assuming that they have an area post-projection).

orientation of normal surface/vertex vectors

Given a convex 3d polygon (convex hull) How can I determine the correct direction for normal surface/vertex vectors? As the polygon is convex, by correct I mean outward facing (away from the centroid).
def surface_normal(centroid, p1, p2, p3):
a = p2-p1
b = p3-p1
n = np.cross(a,b)
if **test including centroid?** :
return n
else:
return -n # change direction
I actually need the normal vertex vectors as I am exporting as a .obj file, but I am assuming that I would need to calculate the surface vectors before hand and combine them.
This solution should work under the assumption of a convex hull in 3d. You calculate the normal as shown in the question. You can normalize the normal vector with
n /= np.linalg.norm(n) # which should be sqrt(n[0]**2 + n[1]**2 + n[2]**2)
You can then calculate the center point of your input triangle:
pmid = (p1 + p2 + p3) / 3
After that you calculate the distance of the triangle-center to your surface centroid. This is
dist_centroid = np.linalg.norm(pmid - centroid)
The you can calculate the distance of your triangle_center + your normal with the length of the distance to the centroid.
dist_with_normal = np.linalg.norm(pmid + n * dist_centroid - centroid)
If this distance is larger than dist_centroid, then your normal is facing outwards. If it is smaller, it is pointing inwards. If you have a perfect sphere and point towards the centroid, it should almost be zero. This may not be the case for your general surface, but the convexity of the surface should make sure, that this is enough to check for its direction.
if(dist_centroid < dist_with_normal):
n *= -1
Another, nicer option is to use a scalar product.
pmid = (p1 + p2 + p3) / 3
if(np.dot(pmid - centroid, n) < 0):
n *= -1
This checks if your normal and the vector from the mid of your triangle to the centroid have the same direction. If that is not so, change the direction.

Numpy Line-Plane intersection

I have two planes in 3D space as shown below.
Point "e" on plane2 represents the intersection of the line which passes from point "P" of plane1 and has the direction vector of "S". Let P be the edge of plane 1.
Which are the "e" point coordinates (xe,ye, 0) with respect to the coordinates system of the plane it belongs (plane2), using Numpy?
I have the following data available:
Coordinates of the centers of each plane with respect of the global coordinate system "C".
x = np.array([x1, x2])
y = np.array([y1, y2])
z = np.array([z1, z2])
Sun direction vector S = np.array([Sz, Sx, Sy])
Point "P" location with respect to the coordinate system of plane1: P(xp,yp,0)
Each plane has the same width and length dimensions: Hw, Hl
Unit vectors normal to the plane surfaces
n = np.array([[n1z, n1x, n1y], [n2z, n2x, n2y]])
Also the azimuthial and elevation angles for both planes with respect to the global coordinate system "c" are known:
alphaH = np.array([alphaH1, alphaH2])
aH = np.array([aH1, aH2])
You have the position vector for c2 and the position vector for e in the global coordinate system then all you need to do is calculate c2-e and this will give you the position vector of e relative to c2.

Equation to find average of multiple velocities?

I need to find the average Edit: total 2D velocity given multiple 2D velocities (speed and direction). A few examples:
Example 1
Velocity 1 is 90° at a speed of 10 pixels or units per second.
Velocity 2 is 270° at a speed of 5 pixels or units per second.
The average velocity is 90° at 5 pixels or units per second.
Example 2
Velocity 1 is 0° at a speed of 10 pixels or units per second
Velocity 2 is 180° at a speed of 10 pixels or units per second
Velocity 3 is 90° at a speed of 8 pixels or units per second
The average velocity is 90° at 8 pixels or units per second
Example 3
Velocity 1 is 0° at 10 pixels or units per second
Velocity 2 is 90° at 10 pixels or units per second
The average velocity is 45° at 14.142 pixels or units per second
I am using JavaScript but it's mostly a language-independent question and I can convert it to JavaScript if necessary.
If you're going to be using a bunch of angles, I would just calculate each speed,
vx = v * cos(theta),
vy = v * sin(theta)
then sum the x velocities and the y velocities separately as vector components and divide by the total number of velocities,
sum(vx) / total v, sum(vy) / total v
and then finally calculate the final speed and direction with your final vx and vy. The magnitude of the speed can be found by a simple application of pythagorean theorem, and then final angle should just be tan-1(y/x).
Per example #3
vx = 10 * cos(90) + 10 * cos(0) = 10,
vy = 10 * sin(90) + 10 * sin(0) = 10
so, tan-1(10/10) = tan-1(1) = 45
then a final magnitude of sqrt(10^2 + 10^2) = 14.142
These are vectors, and you should use vector addition to add them. So right and up are positive, while left and down are negative.
Add your left-to-right vectors (x axis).
Example 1 = -10+5 = -5
Example 2 = -8 = -8
Example 3 = 10 = 10. (90 degrees is generally 90 degrees to the right)
Add you ups and downs similarly and you get these velocities, your left-to-right on the left in the brackets, and your up-to-down on the right.
(-5, 0)
(-8,0)
(10, 10)
These vectors contain all the information you need to plot the motion of an object, you do not need to calculate angles to plot the motion of the object. If for some reason you would rather use speeds (similar to velocity, but different) and angles, then you must first calculate the vectors as above and then use the Pythagorean theorem to find the speed and simple trigonometry to get the angle. Something like this:
var speed = Math.sqrt(x * x + y * y);
var tangeant = y / x;
var angleRadians = Math.atan(tangeant);
var angleDegrees = angleRadians * (180 / Math.PI);
I'll warn you that you should probably talk to someone who know trigonometry and test this well. There is potential for misleading bugs in work like this.
From your examples it sounds like you want addition of 2-dimensional vectors, not averages.
E.g. example 2 can be represented as
(0,10) + (0,-10) + (-8, 0) = (-8,0)
The speed is then equal to the length of the vector:
sqrt(x^2+y^2)
To get average:
add each speed, and then divide by the number of speeds.
10mph + 20mph / 2 = 15
12mph + 14mph + 13mph + 16mph / 4 = 14 (13,75)
This is not so much average as it is just basic vector addition. You're finding multiple "pixel vectors" and adding them together. If you have a velocity vector of 2 pixels to the right, and 1 up, and you add it to a velocity vector of 3 pixels to the left and 2 down, you will get a velocity vector of 1 pixel left, and 1 down.
So the speed is defined by
pij = pixels going up or (-)down
pii = pixels going right or (-)left
speedi = pii1 + pii2 = 2-3 = -1 (1 pixel left)
speedj = pij1 + pij2 = 1-2 = -1 (1 pixel down)
From there, you need to decide which directions are positive, and which are negative. I recommend that left is negative, and down is negative (like a mathematical graph).
The angle of the vector, would be the arctan(speedj/speedi)
arctan(-1/-1) = 45 degrees

Quaternion from two vector pairs

I have two vector pairs (before and after rotation).
before rotation:
[x1,y1,z1]
[x2,y2,z2]
after rotation:
[x1',y1',z1']
[x2',y2',z2']
How to create a quaternion representing this rotation?
In most cases there is no rotation which transforms 2 vectors into 2 other vectors. Here is a simple way to visualize why: a rotation does not change the angle between vectors. If the angle between the 2 vectors before the rotation is different from the angle between the 2 vectors after the rotation, then there is no rotation which meets your criteria.
This said there may be an optimal quaternion with an acceptable error which "almost" rotates your 2 vector pairs. There are a number of algorithms which vary in speed and precision to find such a quaternion. I wrote a fast C++ algorithm for an Arduino application where the speed is critical but the precision is less important.
http://robokitchen.tumblr.com/post/67060392720/finding-a-rotation-quaternion-from-two-pairs-of-vectors
Before rotation: u0, v0. After rotation: u2, v2.
Quaternion q2 = Quaternion::fromTwoVectors(u0, u2);
Vector v1 = v2.rotate(q2.conjugate());
Vector v0_proj = v0.projectPlane(u0);
Vector v1_proj = v1.projectPlane(u0);
Quaternion q1 = Quaternion::fromTwoVectors(v0_proj, v1_proj);
return (q2 * q1).normalized();
If this does not meet the requirements of your own application try to google Wabha's problem.
Well, first you can find the rotation axis using vector-multiplication (cross-multiplication):
axis = v1 x v2;
Then you can compute the rotation angle:
sinA = |axis| / |v1|*|v2|
cosA = v1 . v2 / |v1|*|v2|
Here | | - is vector length operation, and . - is dot-multiplication
And finally, your quaternion is:
Q(w,x,y,z) = (cosA, axis.x * sinA, axis.y * sinA, axis.z * sinA)
I translated marcv81's very helpful blog post into Three.js:
const rotateVectorsSimultaneously = (u0, v0, u2, v2) => {
const q2 = new THREE.Quaternion().setFromUnitVectors(u0, u2);
const v1 = v2.clone().applyQuaternion(q2.clone().conjugate());
const v0_proj = v0.projectOnPlane(u0);
const v1_proj = v1.projectOnPlane(u0);
let angleInPlane = v0_proj.angleTo(v1_proj);
if (v1_proj.dot(new THREE.Vector3().crossVectors(u0, v0)) < 0) {
angleInPlane *= -1;
}
const q1 = new THREE.Quaternion().setFromAxisAngle(u0, angleInPlane);
const q = new THREE.Quaternion().multiplyQuaternions(q2, q1);
return q;
};
Because angleTo always returns a positive value, I manually flip the sign of the angle depending on which side of the u0-v0 plane v1 is on.
A mature solution to this problem is called Triad. Triad is one of the earliest and simplest solutions to the spacecraft attitude determination problem and is extremely efficient computationally.
With Triad, the idea is to replace your paired set of two vectors, with a paired set of three vectors, where the extra vector is generated with a cross-product. By normalizing the vectors, you can solve for a rotation matrix without a matrix inverse or an SVD (as is needed in more general instances of the problem -- see Wahba's Problem)
For full algorithm, see: https://en.wikipedia.org/wiki/Triad_method
You can then convert the solved rotation matrix from Triad to a rotation quaternion:
qw = √(1 + m00 + m11 + m22) /2
qx = (m21 - m12)/( 4 *qw)
qy = (m02 - m20)/( 4 *qw)
qz = (m10 - m01)/( 4 *qw)
In general to make the conversion to quaternion robust, you should consider looking at the matrix trace as discussed here: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
Finally, consider an alternative to Triad that directly computes the optimal quaternion called QUEST.
It is fine to find the quaternion from v1 to v2.
The final q = (cos A/2, sin A/2 * axis), where the A is the angle between v1 and v2, axis is the normed axis.
Multiply both side by 2 * cos A/2,
Then we have
2 * cos A/2 *q = (1+cos A, sin A * axis)
(where cos A = dot(v1, v2)/|v1|/|v2| and
axis = cross(v1, v2).normalize() = cross(v1, v2)/|v1|/|v2|/sin A.)
Then 2 * cos A/2 *q = (1+dot(v1, v2)/|v1|/|v2|, cross(v1, v2)/|v1|/|v2|)
Finally q = (1+dot(v1, v2)/|v1|/|v2|, cross(v1, v2)/|v1|/|v2|).normalize()