Skip to content

Commit 706ae03

Browse files
committed
Merged PR 69077: December 2022 release
1 parent 419d35f commit 706ae03

File tree

317 files changed

+12161
-6876
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

317 files changed

+12161
-6876
lines changed

Directory.Build.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<Company>Microsoft Corporation</Company>
77
<Owners>microsoft,psi</Owners>
88
<Authors>Microsoft</Authors>
9-
<AssemblyVersion>0.17.52.1</AssemblyVersion>
9+
<AssemblyVersion>0.18.72.1</AssemblyVersion>
1010
<FileVersion>$(AssemblyVersion)</FileVersion>
1111
<Version>$(AssemblyVersion)-beta</Version>
1212
<SignAssembly>false</SignAssembly>

Psi.sln

-7
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{4026C2BE
152152
Build\Test.Psi.ruleset = Build\Test.Psi.ruleset
153153
EndProjectSection
154154
EndProject
155-
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Psi.Media.Native.x64", "Sources\Media\Microsoft.Psi.Media.Native.x64\Microsoft.Psi.Media.Native.x64.vcxproj", "{C50F7F21-BEB0-4366-B73F-859EEBC3ED42}"
156-
EndProject
157155
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RealSense", "RealSense", "{64BBFFEA-7CFB-49F9-AC74-3AD1D13245FC}"
158156
EndProject
159157
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Psi.RealSense.Windows.x64", "Sources\RealSense\Microsoft.Psi.RealSense.Windows.x64\Microsoft.Psi.RealSense.Windows.x64.csproj", "{7B73D864-9997-4637-8765-44C17FD09CE1}"
@@ -393,10 +391,6 @@ Global
393391
{4478A162-4FE9-4737-A630-3899DC5935C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
394392
{4478A162-4FE9-4737-A630-3899DC5935C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
395393
{4478A162-4FE9-4737-A630-3899DC5935C6}.Release|Any CPU.Build.0 = Release|Any CPU
396-
{C50F7F21-BEB0-4366-B73F-859EEBC3ED42}.Debug|Any CPU.ActiveCfg = Debug|x64
397-
{C50F7F21-BEB0-4366-B73F-859EEBC3ED42}.Debug|Any CPU.Build.0 = Debug|x64
398-
{C50F7F21-BEB0-4366-B73F-859EEBC3ED42}.Release|Any CPU.ActiveCfg = Release|x64
399-
{C50F7F21-BEB0-4366-B73F-859EEBC3ED42}.Release|Any CPU.Build.0 = Release|x64
400394
{7B73D864-9997-4637-8765-44C17FD09CE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
401395
{7B73D864-9997-4637-8765-44C17FD09CE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
402396
{7B73D864-9997-4637-8765-44C17FD09CE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -582,7 +576,6 @@ Global
582576
{B9F00634-88A1-40EF-9DAD-814A307AD81F} = {C6976E06-9D12-4398-8096-C23D04E63F61}
583577
{BE194924-7162-405D-BF6E-E6086BAA12F1} = {3F77CC04-2E58-452B-8107-0C93E7944D4E}
584578
{4478A162-4FE9-4737-A630-3899DC5935C6} = {CB8286F5-167B-4416-8FE9-9B97FCF146D5}
585-
{C50F7F21-BEB0-4366-B73F-859EEBC3ED42} = {AD8FE445-240A-4791-8C64-A5E2D6E67FF9}
586579
{64BBFFEA-7CFB-49F9-AC74-3AD1D13245FC} = {A0856299-D28A-4513-B964-3FA5290FF160}
587580
{7B73D864-9997-4637-8765-44C17FD09CE1} = {64BBFFEA-7CFB-49F9-AC74-3AD1D13245FC}
588581
{DAB8847B-DE0A-45E2-A7DA-30432A36525B} = {64BBFFEA-7CFB-49F9-AC74-3AD1D13245FC}

Sources/Calibration/Microsoft.Psi.Calibration/CalibrationExtensions.cs

+59-57
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace Microsoft.Psi.Calibration
77
using System.Collections.Generic;
88
using MathNet.Numerics.LinearAlgebra;
99
using MathNet.Spatial.Euclidean;
10+
using MathNet.Spatial.Units;
1011
using Microsoft.Psi;
1112
using Microsoft.Psi.Imaging;
1213

@@ -196,8 +197,8 @@ public static ICameraIntrinsics CreateCameraIntrinsics(this ImageBase image, dou
196197
double z = pointInCameraSpace.X * colorExtrinsicsInverse[2, 0] + pointInCameraSpace.Y * colorExtrinsicsInverse[2, 1] + pointInCameraSpace.Z * colorExtrinsicsInverse[2, 2] + colorExtrinsicsInverse[2, 3];
197198
var pointInDepthCameraSpace = new Point3D(x, y, z);
198199
var colorCameraOriginInDepthCameraSpace = new Point3D(colorExtrinsicsInverse[0, 3], colorExtrinsicsInverse[1, 3], colorExtrinsicsInverse[2, 3]);
199-
var searchLine = new Line3D(colorCameraOriginInDepthCameraSpace, pointInDepthCameraSpace);
200-
return IntersectLineWithDepthMesh(depthDeviceCalibrationInfo.DepthIntrinsics, searchLine, depthImage.Resource);
200+
var searchRay = new Ray3D(colorCameraOriginInDepthCameraSpace, pointInDepthCameraSpace - colorCameraOriginInDepthCameraSpace);
201+
return depthImage.Resource.ComputeRayIntersection(depthDeviceCalibrationInfo.DepthIntrinsics, searchRay);
201202
}
202203

203204
/// <summary>
@@ -213,41 +214,6 @@ public static IProducer<List<Point3D>> ProjectTo3D(
213214
string name = nameof(ProjectTo3D))
214215
=> source.PipeTo(new ProjectTo3D(source.Out.Pipeline, name), deliveryPolicy);
215216

216-
/// <summary>
217-
/// Performs a ray/mesh intersection with the depth map.
218-
/// </summary>
219-
/// <param name="depthIntrinsics">The intrinsics for the depth camera.</param>
220-
/// <param name="line">Ray to intersect against depth map.</param>
221-
/// <param name="depthImage">Depth map to ray cast against.</param>
222-
/// <param name="maxDistance">The maximum distance to search for.</param>
223-
/// <param name="skipFactor">Distance to march on each step along ray.</param>
224-
/// <param name="undistort">Whether undistortion should be applied to the point.</param>
225-
/// <returns>Returns point of intersection.</returns>
226-
public static Point3D? IntersectLineWithDepthMesh(ICameraIntrinsics depthIntrinsics, Line3D line, DepthImage depthImage, double maxDistance = 5, double skipFactor = 0.05, bool undistort = true)
227-
{
228-
// max distance to check for intersection with the scene
229-
var delta = skipFactor * (line.EndPoint - line.StartPoint).Normalize();
230-
231-
// size of increment along the ray
232-
int maxSteps = (int)(maxDistance / delta.Length);
233-
var hypothesisPoint = line.StartPoint;
234-
for (int i = 0; i < maxSteps; i++)
235-
{
236-
hypothesisPoint += delta;
237-
238-
// get the mesh distance at the extended point
239-
float meshDistance = GetMeshDepthAtPoint(depthIntrinsics, depthImage, hypothesisPoint, undistort);
240-
241-
// if the mesh distance is less than the distance to the point we've hit the mesh
242-
if (!float.IsNaN(meshDistance) && (meshDistance < hypothesisPoint.X))
243-
{
244-
return hypothesisPoint;
245-
}
246-
}
247-
248-
return null;
249-
}
250-
251217
/// <summary>
252218
/// Use the Rodrigues formula for transforming a given rotation from axis-angle representation to a 3x3 matrix.
253219
/// Where 'r' is a rotation vector:
@@ -299,13 +265,15 @@ public static Matrix<double> AxisAngleToMatrix(Vector<double> vectorRotation)
299265
}
300266

301267
/// <summary>
302-
/// Convert a rotation matrix to axis-angle representation (a unit vector scaled by the angular distance to rotate).
268+
/// Convert a rotation matrix to axis-angle representation (a unit vector scaled by the angular distance in radians to rotate).
303269
/// </summary>
304270
/// <param name="m">Input rotation matrix.</param>
305-
/// <returns>Same rotation in axis-angle representation (L2-Norm of the vector represents angular distance).</returns>
306271
/// <param name="epsilon">An optional angle epsilon parameter used to determine when the specified matrix contains a zero-rotation (by default 0.01 degrees).</param>
307-
public static Vector<double> MatrixToAxisAngle(Matrix<double> m, double epsilon = 0.01 * Math.PI / 180)
272+
/// <returns>Same rotation in axis-angle representation (L2-Norm of the vector represents angular distance in radians).</returns>
273+
public static Vector<double> MatrixToAxisAngle(Matrix<double> m, Angle? epsilon = null)
308274
{
275+
epsilon ??= Angle.FromDegrees(0.01);
276+
309277
if (m.RowCount != 3 || m.ColumnCount != 3)
310278
{
311279
throw new InvalidOperationException("The input must be a valid 3x3 rotation matrix in order to compute its axis-angle representation.");
@@ -317,7 +285,7 @@ public static Vector<double> MatrixToAxisAngle(Matrix<double> m, double epsilon
317285
// Create the axis vector.
318286
var v = Vector<double>.Build.Dense(3, 0);
319287

320-
if (double.IsNaN(angle) || angle < epsilon)
288+
if (double.IsNaN(angle) || angle < epsilon.Value.Radians)
321289
{
322290
// If the angular distance to rotate is 0, we just return a vector of all zeroes.
323291
return v;
@@ -427,28 +395,62 @@ public static void Project(Matrix<double> cameraMatrix, Vector<double> distCoeff
427395
projectedPoint = new Point2D(fx * xpp + cx, fy * ypp + cy);
428396
}
429397

430-
private static float GetMeshDepthAtPoint(ICameraIntrinsics depthIntrinsics, DepthImage depthImage, Point3D point, bool undistort)
398+
/// <summary>
399+
/// Computes a ray intersection with a depth image mesh.
400+
/// </summary>
401+
/// <param name="depthImage">Depth image mesh to ray cast against.</param>
402+
/// <param name="depthIntrinsics">The intrinsics for the depth camera.</param>
403+
/// <param name="ray">Ray to intersect against depth image mesh.</param>
404+
/// <param name="maxDistance">The maximum distance to search for (default is 5 meters).</param>
405+
/// <param name="skipFactor">Distance to march on each step along ray (default is 5 cm).</param>
406+
/// <param name="undistort">Whether undistortion should be applied to the point.</param>
407+
/// <returns>Returns point of intersection, or null if no intersection was found.</returns>
408+
/// <remarks>
409+
/// The ray is assumed to be defined relative to the pose of the depth camera,
410+
/// i.e., (0, 0, 0) is the position of the camera itself.
411+
/// </remarks>
412+
public static Point3D? ComputeRayIntersection(this DepthImage depthImage, ICameraIntrinsics depthIntrinsics, Ray3D ray, double maxDistance = 5, double skipFactor = 0.05, bool undistort = true)
431413
{
432-
if (!depthIntrinsics.TryGetPixelPosition(point, undistort, out var depthPixel))
433-
{
434-
return float.NaN;
435-
}
414+
// max distance to check for intersection with the scene
415+
int maxSteps = (int)(maxDistance / skipFactor);
436416

437-
int x = (int)Math.Round(depthPixel.X);
438-
int y = (int)Math.Round(depthPixel.Y);
439-
if ((x < 0) || (x >= depthImage.Width) || (y < 0) || (y >= depthImage.Height))
440-
{
441-
return float.NaN;
442-
}
417+
// size of increment along the ray
418+
var delta = skipFactor * ray.Direction;
443419

444-
int byteOffset = (int)((y * depthImage.Stride) + (x * 2));
445-
var depth = BitConverter.ToUInt16(depthImage.ReadBytes(2, byteOffset), 0);
446-
if (depth == 0)
420+
var hypothesisPoint = ray.ThroughPoint;
421+
for (int i = 0; i < maxSteps; i++)
447422
{
448-
return float.NaN;
423+
hypothesisPoint += delta;
424+
425+
// get the mesh distance at the hypothesis point
426+
if (depthIntrinsics.TryGetPixelPosition(hypothesisPoint, undistort, out var depthPixel) &&
427+
depthImage.TryGetPixel((int)Math.Floor(depthPixel.X), (int)Math.Floor(depthPixel.Y), out var depthValue) &&
428+
depthValue != 0)
429+
{
430+
// if the mesh distance is less than the distance to the point we've hit the mesh
431+
var meshDistanceMeters = (double)depthValue * depthImage.DepthValueToMetersScaleFactor;
432+
if (depthImage.DepthValueSemantics == DepthValueSemantics.DistanceToPlane)
433+
{
434+
if (meshDistanceMeters < hypothesisPoint.X)
435+
{
436+
return hypothesisPoint;
437+
}
438+
}
439+
else if (depthImage.DepthValueSemantics == DepthValueSemantics.DistanceToPoint)
440+
{
441+
if (meshDistanceMeters < hypothesisPoint.ToVector3D().Length)
442+
{
443+
return hypothesisPoint;
444+
}
445+
}
446+
else
447+
{
448+
throw new ArgumentException($"Unhandled {nameof(DepthValueSemantics)}: {depthImage.DepthValueSemantics}");
449+
}
450+
}
449451
}
450452

451-
return (float)depth / 1000;
453+
return null;
452454
}
453455

454456
private static double CalibrateCamera(

Sources/Calibration/Microsoft.Psi.Calibration/CameraIntrinsics.cs

+7
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,13 @@ private set
141141
public Point2D? GetPixelPosition(Point3D point3D, bool distort, bool nullIfOutsideFieldOfView = true)
142142
{
143143
// X points in the depth dimension. Y points to the left, and Z points up.
144+
145+
// If the point is not in front of the camera, we cannot compute the projection
146+
if (point3D.X <= 0)
147+
{
148+
return null;
149+
}
150+
144151
var point2D = new Point2D(-point3D.Y / point3D.X, -point3D.Z / point3D.X);
145152
if (distort)
146153
{

Sources/Calibration/Microsoft.Psi.Calibration/ICameraIntrinsics.cs

+4
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ public interface ICameraIntrinsics : IEquatable<ICameraIntrinsics>
7777
/// <param name="distort">Indicates whether to apply distortion.</param>
7878
/// <param name="nullIfOutsideFieldOfView">Optional flag indicating whether to return null if point is outside the field of view (default true).</param>
7979
/// <returns>Point containing the pixel position.</returns>
80+
/// <remarks>Points that are behind the camera, i.e., with the X value below zero lead to null returns,
81+
/// regardless of value of the <paramref name="nullIfOutsideFieldOfView"/> parameter.</remarks>
8082
Point2D? GetPixelPosition(Point3D point3D, bool distort, bool nullIfOutsideFieldOfView = true);
8183

8284
/// <summary>
@@ -87,6 +89,8 @@ public interface ICameraIntrinsics : IEquatable<ICameraIntrinsics>
8789
/// <param name="pixelPosition">Output point containing the pixel position.</param>
8890
/// <param name="nullIfOutsideFieldOfView">Optional flag indicating whether to return null if point is outside the field of view (default true).</param>
8991
/// <returns>True if <paramref name="pixelPosition"/> is within field of view, otherwise false.</returns>
92+
/// <remarks>Points that are behind the camera, i.e., with the X value below zero lead to a return value of false,
93+
/// regardless of value of the <paramref name="nullIfOutsideFieldOfView"/> parameter.</remarks>
9094
bool TryGetPixelPosition(Point3D point3D, bool distort, out Point2D pixelPosition, bool nullIfOutsideFieldOfView = true);
9195

9296
/// <summary>

0 commit comments

Comments
 (0)