Skip to content

Commit

Permalink
Switching to version 1.3.0 of Sensor SDK. New method ConvertColor2DTo…
Browse files Browse the repository at this point in the history
…Depth2D in Calibration structure. Tests on this method.
  • Loading branch information
bibigone committed Oct 16, 2019
1 parent 3a8c1f4 commit 6375df6
Show file tree
Hide file tree
Showing 17 changed files with 348 additions and 32 deletions.
36 changes: 35 additions & 1 deletion K4AdotNet.Tests.Unit/Sensor/CalibrationTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using K4AdotNet.Sensor;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;

namespace K4AdotNet.Tests.Unit.Sensor
{
Expand Down Expand Up @@ -186,7 +187,6 @@ private void TestConvert3DTo2D(DepthMode depthMode, ColorResolution colorResolut
Calibration.CreateDummy(depthMode, colorResolution, out var calibration);

var depthCenter = new Float2(calibration.DepthCameraCalibration.Intrinsics.Parameters.Cx, calibration.DepthCameraCalibration.Intrinsics.Parameters.Cy);
var colorCenter = new Float2(calibration.ColorCameraCalibration.Intrinsics.Parameters.Cx, calibration.ColorCameraCalibration.Intrinsics.Parameters.Cy);

var point2d = calibration.Convert3DTo2D(new Float3(0f, 0f, 1000f), CalibrationGeometry.Depth, CalibrationGeometry.Depth);
Assert.IsNotNull(point2d);
Expand Down Expand Up @@ -221,5 +221,39 @@ private void TestConvert3DTo3D(DepthMode depthMode, ColorResolution colorResolut
}

#endregion

#region ConvertColor2DToDepth2D

[TestMethod]
public void TestConvertColor2DToDepth2D()
{
TestConvertColor2DToDepth2D(DepthMode.NarrowView2x2Binned, ColorResolution.R720p);
TestConvertColor2DToDepth2D(DepthMode.NarrowViewUnbinned, ColorResolution.R1080p);
TestConvertColor2DToDepth2D(DepthMode.WideView2x2Binned, ColorResolution.R1536p);
TestConvertColor2DToDepth2D(DepthMode.WideViewUnbinned, ColorResolution.R3072p);
}

private void TestConvertColor2DToDepth2D(DepthMode depthMode, ColorResolution colorResolution)
{
Calibration.CreateDummy(depthMode, colorResolution, 30, out var calibration);

var depth2d = new Float2(calibration.DepthCameraCalibration.Intrinsics.Parameters.Cx, calibration.DepthCameraCalibration.Intrinsics.Parameters.Cy);
var depthMm = (short)1800;
var color2d = calibration.Convert2DTo2D(depth2d, depthMm, CalibrationGeometry.Depth, CalibrationGeometry.Color).Value;

var depthImageBuffer = new short[depthMode.WidthPixels() * depthMode.HeightPixels()];
for (var i = 0; i < depthImageBuffer.Length; i++)
depthImageBuffer[i] = depthMm;
var depthImage = Image.CreateFromArray(depthImageBuffer, ImageFormat.Depth16, depthMode.WidthPixels(), depthMode.HeightPixels());

var point2d = calibration.ConvertColor2DToDepth2D(color2d, depthImage);
Assert.IsNotNull(point2d);
Assert.IsTrue(Math.Abs(depth2d.X - point2d.Value.X) < 1f);
Assert.IsTrue(Math.Abs(depth2d.Y - point2d.Value.Y) < 1f);

depthImage.Dispose();
}

#endregion
}
}
71 changes: 68 additions & 3 deletions K4AdotNet/K4AdotNet.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4189,6 +4189,17 @@
<param name="calibration">Result: created dummy calibration data for <paramref name="depthMode"/> and <paramref name="colorResolution"/> specified.</param>
<exception cref="T:System.ArgumentOutOfRangeException"><paramref name="depthMode"/> and <paramref name="colorResolution"/> cannot be equal to <c>Off</c> simultaneously.</exception>
</member>
<member name="M:K4AdotNet.Sensor.Calibration.CreateDummy(K4AdotNet.Sensor.DepthMode,K4AdotNet.Sensor.ColorResolution,System.Single,K4AdotNet.Sensor.Calibration@)">
<summary>
Creates dummy (no distortions, ideal pin-hole geometry, all sensors are aligned, there is specified distance between depth and color cameras) but valid calibration data.
This can be useful for testing and subbing needs.
</summary>
<param name="depthMode">Depth mode for which dummy calibration should be created. Can be <see cref="F:K4AdotNet.Sensor.DepthMode.Off"/>.</param>
<param name="distanceBetweenDepthAndColorMm">Distance (horizontal) between depth and color cameras.</param>
<param name="colorResolution">Color resolution for which dummy calibration should be created. Can be <see cref="F:K4AdotNet.Sensor.ColorResolution.Off"/>.</param>
<param name="calibration">Result: created dummy calibration data for <paramref name="depthMode"/> and <paramref name="colorResolution"/> specified.</param>
<exception cref="T:System.ArgumentOutOfRangeException"><paramref name="depthMode"/> and <paramref name="colorResolution"/> cannot be equal to <c>Off</c> simultaneously.</exception>
</member>
<member name="M:K4AdotNet.Sensor.Calibration.CreateFromRaw(System.Byte[],K4AdotNet.Sensor.DepthMode,K4AdotNet.Sensor.ColorResolution,K4AdotNet.Sensor.Calibration@)">
<summary>Gets the camera calibration for a device from a raw calibration blob.</summary>
<param name="rawCalibration">Raw calibration blob obtained from a device or recording. The raw calibration must be <c>0</c>-terminated. Cannot be <see langword="null"/>.</param>
Expand Down Expand Up @@ -4224,6 +4235,31 @@
Cannot perform transformation. Most likely, calibration data is invalid.
</exception>
</member>
<member name="M:K4AdotNet.Sensor.Calibration.ConvertColor2DToDepth2D(K4AdotNet.Float2,K4AdotNet.Sensor.Image)">
<summary>Transform a 2D pixel coordinate from color camera into a 2D pixel coordinate of the depth camera.</summary>
<param name="sourcePoint2D">The 2D pixel in color camera coordinates.</param>
<param name="depthImage">Input depth image. Not <see langword="null"/>.</param>
<returns>
The 2D pixel in depth camera coordinates or
<see langword="null"/> if <paramref name="sourcePoint2D"/> does not map to a valid 2D coordinate in the depth coordinate system.
</returns>
<remarks>
This function represents an alternative to <see cref="M:K4AdotNet.Sensor.Calibration.Convert2DTo2D(K4AdotNet.Float2,System.Single,K4AdotNet.Sensor.CalibrationGeometry,K4AdotNet.Sensor.CalibrationGeometry)"/> if the number of pixels that need to be transformed is small.
This function searches along an epipolar line in the depth image to find the corresponding
depth pixel. If a larger number of pixels need to be transformed, it might be computationally cheaper to call
<see cref="M:K4AdotNet.Sensor.Transformation.DepthImageToColorCamera(K4AdotNet.Sensor.Image,K4AdotNet.Sensor.Image)"/>
to get correspondence depth values for these color pixels, then call the function <see cref="M:K4AdotNet.Sensor.Calibration.Convert2DTo2D(K4AdotNet.Float2,System.Single,K4AdotNet.Sensor.CalibrationGeometry,K4AdotNet.Sensor.CalibrationGeometry)"/>.
</remarks>
<exception cref="T:System.ArgumentNullException">
<paramref name="depthImage"/> cannot be <see langword="null"/>.
</exception>
<exception cref="T:System.ArgumentException">
<paramref name="depthImage"/> has invalid format and/or resolution.
</exception>
<exception cref="T:System.InvalidOperationException">
Cannot perform transformation. Most likely, calibration data is invalid.
</exception>
</member>
<member name="M:K4AdotNet.Sensor.Calibration.Convert2DTo3D(K4AdotNet.Float2,System.Single,K4AdotNet.Sensor.CalibrationGeometry,K4AdotNet.Sensor.CalibrationGeometry)">
<summary>
Transform a 2D pixel coordinate with an associated depth value of the source camera
Expand Down Expand Up @@ -4448,13 +4484,13 @@
<summary>Calibration model is unknown.</summary>
</member>
<member name="F:K4AdotNet.Sensor.CalibrationModel.Theta">
<summary>Calibration model is Theta (arctan).</summary>
<summary>Deprecated (not supported). Calibration model is Theta (arctan).</summary>
</member>
<member name="F:K4AdotNet.Sensor.CalibrationModel.Polynomial3K">
<summary>Calibration model Polynomial 3K.</summary>
<summary>Deprecated (not supported). Calibration model Polynomial 3K.</summary>
</member>
<member name="F:K4AdotNet.Sensor.CalibrationModel.Rational6KT">
<summary>Calibration model Rational 6KT.</summary>
<summary>Deprecated (only supported early internal devices). Calibration model Rational 6KT.</summary>
</member>
<member name="F:K4AdotNet.Sensor.CalibrationModel.BrownConrady">
<summary>Calibration model Brown Conrady (compatible with OpenCV).</summary>
Expand Down Expand Up @@ -6849,6 +6885,35 @@
The user should not use the value of <paramref name="targetPoint2D"/> if <paramref name="valid"/> was set to 0.
</remarks>
</member>
<member name="M:K4AdotNet.Sensor.NativeApi.CalibrationColor2DToDepth2D(K4AdotNet.Sensor.Calibration@,K4AdotNet.Float2@,K4AdotNet.NativeHandles.ImageHandle,K4AdotNet.Float2@,System.Boolean@)">
<summary>Transform a 2D pixel coordinate from color camera into a 2D pixel coordinate of the depth camera.</summary>
<param name="calibration">Camera calibration data.</param>
<param name="sourcePoint2D">The 2D pixel in color camera coordinates.</param>
<param name="depthImage">Handle to input depth image.</param>
<param name="targetPoint2D">The 2D pixel in depth camera coordinates.</param>
<param name="valid">
The output parameter returns a value of <see langword="true"/> if the <paramref name="sourcePoint2D"/> is a valid coordinate in the depth camera
coordinate system, and will return <see langword="false"/> if the coordinate is not valid in the calibration model.
</param>
<returns>
<see cref="F:K4AdotNet.NativeCallResults.Result.Succeeded"/> if <paramref name="targetPoint2D"/> was successfully written.
<see cref="F:K4AdotNet.NativeCallResults.Result.Failed"/> if <paramref name="calibration"/> contained invalid transformation parameters.
If the function returns <see cref="F:K4AdotNet.NativeCallResults.Result.Succeeded"/>, but <paramref name="valid"/> valid is <see langword="false"/>,
the transformation was computed, but the results in <paramref name="targetPoint2D"/> are outside of the range of valid calibration
and should be ignored.
</returns>
<remarks>
This function represents an alternative to <see cref="M:K4AdotNet.Sensor.NativeApi.Calibration2DTo2D(K4AdotNet.Sensor.Calibration@,K4AdotNet.Float2@,System.Single,K4AdotNet.Sensor.CalibrationGeometry,K4AdotNet.Sensor.CalibrationGeometry,K4AdotNet.Float2@,System.Boolean@)"/>
if the number of pixels that need to be transformed is small. This function searches along an epipolar line in the depth image to find the corresponding
depth pixel. If a larger number of pixels need to be transformed, it might be computationally cheaper to call
<see cref="M:K4AdotNet.Sensor.NativeApi.TransformationDepthImageToColorCamera(K4AdotNet.NativeHandles.TransformationHandle,K4AdotNet.NativeHandles.ImageHandle,K4AdotNet.NativeHandles.ImageHandle)"/>
to get correspondence depth values for these color pixels, then call the function <see cref="M:K4AdotNet.Sensor.NativeApi.Calibration2DTo2D(K4AdotNet.Sensor.Calibration@,K4AdotNet.Float2@,System.Single,K4AdotNet.Sensor.CalibrationGeometry,K4AdotNet.Sensor.CalibrationGeometry,K4AdotNet.Float2@,System.Boolean@)"/>.

If <paramref name="sourcePoint2D"/> does not map to a valid 2D coordinate in the depth camera coordinate system, <paramref name="valid"/> is set
to <see langword="false"/>. If it is valid, <paramref name="valid"/> will be set to <see langword="true"/>.
The user should not use the value of <paramref name="targetPoint2D"/> if <paramref name="valid"/> was set to <see langword="false"/>.
</remarks>
</member>
<member name="M:K4AdotNet.Sensor.NativeApi.TransformationCreate(K4AdotNet.Sensor.Calibration@)">
<summary>Get handle to transformation.</summary>
<param name="calibration">Camera calibration data.</param>
Expand Down
62 changes: 62 additions & 0 deletions K4AdotNet/Sensor/Calibration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,29 @@ public static void CreateDummy(DepthMode depthMode, ColorResolution colorResolut
InitDummyExtrinsics(ref calibration.Extrinsics[i]);
}

/// <summary>
/// Creates dummy (no distortions, ideal pin-hole geometry, all sensors are aligned, there is specified distance between depth and color cameras) but valid calibration data.
/// This can be useful for testing and subbing needs.
/// </summary>
/// <param name="depthMode">Depth mode for which dummy calibration should be created. Can be <see cref="DepthMode.Off"/>.</param>
/// <param name="distanceBetweenDepthAndColorMm">Distance (horizontal) between depth and color cameras.</param>
/// <param name="colorResolution">Color resolution for which dummy calibration should be created. Can be <see cref="ColorResolution.Off"/>.</param>
/// <param name="calibration">Result: created dummy calibration data for <paramref name="depthMode"/> and <paramref name="colorResolution"/> specified.</param>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="depthMode"/> and <paramref name="colorResolution"/> cannot be equal to <c>Off</c> simultaneously.</exception>
public static void CreateDummy(DepthMode depthMode, ColorResolution colorResolution, float distanceBetweenDepthAndColorMm,
out Calibration calibration)
{
CreateDummy(depthMode, colorResolution, out calibration);

var extr = calibration.GetExtrinsics(CalibrationGeometry.Color, CalibrationGeometry.Depth);
extr.Translation = new Float3(distanceBetweenDepthAndColorMm, 0, 0);
calibration.SetExtrinsics(CalibrationGeometry.Color, CalibrationGeometry.Depth, extr);

extr = calibration.GetExtrinsics(CalibrationGeometry.Depth, CalibrationGeometry.Color);
extr.Translation = new Float3(-distanceBetweenDepthAndColorMm, 0, 0);
calibration.SetExtrinsics(CalibrationGeometry.Depth, CalibrationGeometry.Color, extr);
}

// Ideal pin-hole camera. No distortions.
private static void InitDummyCameraCalibration(ref CameraCalibration cameraCalibration, int widthPixels, int heightPixels,
float hFovDegrees, float vFovDegrees)
Expand Down Expand Up @@ -209,6 +232,45 @@ public static void CreateFromRaw(byte[] rawCalibration, DepthMode depthMode, Col
return targetPoint2D;
}

/// <summary>Transform a 2D pixel coordinate from color camera into a 2D pixel coordinate of the depth camera.</summary>
/// <param name="sourcePoint2D">The 2D pixel in color camera coordinates.</param>
/// <param name="depthImage">Input depth image. Not <see langword="null"/>.</param>
/// <returns>
/// The 2D pixel in depth camera coordinates or
/// <see langword="null"/> if <paramref name="sourcePoint2D"/> does not map to a valid 2D coordinate in the depth coordinate system.
/// </returns>
/// <remarks>
/// This function represents an alternative to <see cref="Convert2DTo2D"/> if the number of pixels that need to be transformed is small.
/// This function searches along an epipolar line in the depth image to find the corresponding
/// depth pixel. If a larger number of pixels need to be transformed, it might be computationally cheaper to call
/// <see cref="Transformation.DepthImageToColorCamera"/>
/// to get correspondence depth values for these color pixels, then call the function <see cref="Convert2DTo2D"/>.
/// </remarks>
/// <exception cref="ArgumentNullException">
/// <paramref name="depthImage"/> cannot be <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="depthImage"/> has invalid format and/or resolution.
/// </exception>
/// <exception cref="InvalidOperationException">
/// Cannot perform transformation. Most likely, calibration data is invalid.
/// </exception>
public Float2? ConvertColor2DToDepth2D(Float2 sourcePoint2D, Image depthImage)
{
if (depthImage == null)
throw new ArgumentNullException(nameof(depthImage));
if (depthImage.IsDisposed)
throw new ObjectDisposedException(nameof(depthImage));
if (depthImage.Format != ImageFormat.Depth16 || depthImage.WidthPixels != DepthMode.WidthPixels() || depthImage.HeightPixels != DepthMode.HeightPixels())
throw new ArgumentException($"Invalid format or size of {nameof(depthImage)}", nameof(depthImage));
var res = NativeApi.CalibrationColor2DToDepth2D(ref this, ref sourcePoint2D, Image.ToHandle(depthImage), out var targetPoint2D, out var valid);
if (res != NativeCallResults.Result.Succeeded)
throw new InvalidOperationException("Cannot transform color 2D point to depth 2D point: invalid calibration data.");
if (!valid)
return null;
return targetPoint2D;
}

/// <summary>
/// Transform a 2D pixel coordinate with an associated depth value of the source camera
/// into a 3D point of the target coordinate system.
Expand Down
13 changes: 9 additions & 4 deletions K4AdotNet/Sensor/CalibrationModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace K4AdotNet.Sensor
using System;

namespace K4AdotNet.Sensor
{
// Defined in k4atypes.h:
// typedef enum
Expand All @@ -16,13 +18,16 @@ public enum CalibrationModel
/// <summary>Calibration model is unknown.</summary>
Unknown = 0,

/// <summary>Calibration model is Theta (arctan).</summary>
/// <summary>Deprecated (not supported). Calibration model is Theta (arctan).</summary>
[Obsolete]
Theta,

/// <summary>Calibration model Polynomial 3K.</summary>
/// <summary>Deprecated (not supported). Calibration model Polynomial 3K.</summary>
[Obsolete]
Polynomial3K,

/// <summary>Calibration model Rational 6KT.</summary>
/// <summary>Deprecated (only supported early internal devices). Calibration model Rational 6KT.</summary>
[Obsolete]
Rational6KT,

/// <summary>Calibration model Brown Conrady (compatible with OpenCV).</summary>
Expand Down
Loading

0 comments on commit 6375df6

Please sign in to comment.