// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
// Copyright (c) (2018-2022) Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Software License Agreement, located here: https://www.magicleap.com/software-license-agreement-ml2
// Terms and conditions applicable to third-party materials accompanying this distribution may also be found in the top-level NOTICE file appearing herein.
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
using System;
using System.Text;
namespace UnityEngine.XR.MagicLeap
{
public partial class MLMarkerTracker
{
///
/// Represents the different marker types supported by the API
///
[Flags]
public enum MarkerType
{
///
/// Represents no marker
///
None = 0,
///
/// QR code of Model 1 or 2
///
QR = 1,
///
/// Aruco marker and AprilTag
///
Aruco_April = 2,
///
/// EAN-13 (experimental)
///
EAN_13 = 4,
///
/// UPC-A (experimental)
///
UPC_A = 8,
///
/// All supported markers
///
All = 0x3FFFFFFF
}
///
/// Supported pre-defined ArUco dictionary and AprilTags.
/// Marker Tracker supports pre-defined ArUco dictionary and AprilTags.
/// ArUco dictionaries can be looked up and markers can be generated for them here:
/// http://chev.me/arucogen/
/// Note: Due to 4X4 dictionaries suffering from frequent false detections, we discourage their use.
///
public enum ArucoDictionaryName
{
///
/// Default value. Nothing will be detected.
///
NotInitialized = -1,
///
/// 4 by 4 pixel ArUco marker dictionary with 50 IDs.
///
DICT_4X4_50 = 0,
///
/// 4 by 4 pixel ArUco marker dictionary with 100 IDs.
///
DICT_4X4_100,
///
/// 4 by 4 pixel ArUco marker dictionary with 250 IDs.
///
DICT_4X4_250,
///
/// 4 by 4 pixel ArUco marker dictionary with 1000 IDs.
///
DICT_4X4_1000,
///
/// 5 by 5 pixel ArUco marker dictionary with 50 IDs.
///
DICT_5X5_50,
///
/// 5 by 5 pixel ArUco marker dictionary with 100 IDs.
///
DICT_5X5_100,
///
/// 5 by 5 pixel ArUco marker dictionary with 250 IDs.
///
DICT_5X5_250,
///
/// 5 by 5 pixel ArUco marker dictionary with 1000 IDs.
///
DICT_5X5_1000,
///
/// 6 by 6 pixel ArUco marker dictionary with 50 IDs.
///
DICT_6X6_50,
///
/// 6 by 6 pixel ArUco marker dictionary with 100 IDs.
///
DICT_6X6_100,
///
/// 6 by 6 pixel ArUco marker dictionary with 250 IDs.
///
DICT_6X6_250,
///
/// 6 by 6 pixel ArUco marker dictionary with 1000 IDs.
///
DICT_6X6_1000,
///
/// 7 by 7 pixel ArUco marker dictionary with 50 IDs.
///
DICT_7X7_50,
///
/// 7 by 7 pixel ArUco marker dictionary with 100 IDs.
///
DICT_7X7_100,
///
/// 7 by 7 pixel ArUco marker dictionary with 250 IDs.
///
DICT_7X7_250,
///
/// 7 by 7 pixel ArUco marker dictionary with 1000 IDs.
///
DICT_7X7_1000,
///
/// 5 by 5 pixel ArUco marker dictionary with 1024 IDs
///
DICT_ARUCO_ORIGINAL,
///
/// 4x4 bits, minimum hamming distance between any two codes = 5, 30 codes
///
DICT_APRILTAG_16h5,
///
/// 5x5 bits, minimum hamming distance between any two codes = 9, 35 codes
///
DICT_APRILTAG_25h9,
///
/// 6x6 bits, minimum hamming distance between any two codes = 10, 2320 codes
///
DICT_APRILTAG_36h10,
///
/// 6x6 bits, minimum hamming distance between any two codes = 11, 587 codes
///
DICT_APRILTAG_36h11,
}
///
/// Represents the different tracker profiles used to optimize marker tracking in difference use cases.
///
public enum Profile
{
///
/// Generic tracker profile.
/// Tracker profile that covers standard use cases. If this does not fit the
/// needs of the application try the other profiles listed below.
///
Default,
///
/// Application can define a custom tracker profiler.
///
Custom,
///
/// Use this profile to reduce the compute load and increase detection/tracker speed.
/// This can result poor poses.
///
Speed,
///
/// Use this profile to optimize for accurate marker poses.
/// This can cause increased load on the compute.
///
Accuracy,
///
/// Use this profile to optimize for markers that are small or for larger
/// markers that need to detected from far.
///
SmallTargets,
///
/// Use this profile to be able to detect markers across a larger Field Of View.
/// Marker Tracker system will attempt to use multiple cameras to detect the markers.
///
Large_FOV = 6
}
///
/// Used to hint to the back-end the max frames per second
/// that should be analyzed. This is set in the
/// MLMarkerTrackerCustomProfile structure and this setting
/// applies to all enabled trackers.
///
/// CPU load is a combination of enabled detector types,
/// FpsHint and ResolutionHint. More detectors with a higher FPS
/// and resolution hints will result in a higher CPU load. High CPU load can affect the
/// performance of your system.
///
public enum FPSHint
{
Low,
Medium,
High,
Max
}
///
/// The ResolutionHint enum values are
/// used to hint to the back-end the resolution
/// that should be used. This is set in the
/// MLMarkerTracker.CustomProfile structure and this setting
/// currently only applies to the QR, UPC and EAN detectors.
///
/// CPU load is a combination of enabled detector types,
/// FpsHint and ResolutionHint. More detectors and a higher
/// fps and resolution hints will result in a higher CPU load.
/// High CPU load can affect the performance of your system.
///
public enum ResolutionHint
{
Low,
Medium,
High
}
///
/// The CameraHint enum values are
/// used to hint to the camera
/// that should be used. This is set in the
/// MLMarkerTracker.CustomProfile structure and this setting
/// currently only applies to the aruco detectors.
///
/// RGB camera has higher resolution than world cameras and are better suited
/// for use cases where the target to be tracked is small or needs to be detected
/// from far.
///
/// World cameras make use of multiple world cameras to improve accuracy and
/// increase the FoV for detection.
/// from far.
///
public enum CameraHint
{
///
/// Single RGB Camera.
///
RGB,
///
/// One or more world cameras.
///
World
}
///
/// In order to improve performance, the detectors don't always run on the full
/// frame. Full frame analysis is however necessary to detect new markers that
/// weren't detected before. Use this option to control how often the detector may
/// detect new markers and its impact on tracking performance.
///
public enum FullAnalysisIntervalHint
{
///
/// Detector analyzes every frame fully.
///
Max,
///
/// Detector analyzes frame fully very often.
///
Fast,
///
/// Detector analyzes frame fully a few times per second.
///
Medium,
///
/// Detector analyzes frame fully about every second.
///
Slow
}
///
/// The Aruco/April tag detector comes with several corner refinement methods.
/// Choosing the right corner refinement method has an impact on the accuracy and
/// speed trade-off that comes with each detection pipeline.
/// Corner refinement only applies to Aruco and April tags, not QR codes.
///
public enum CornerRefineMethod
{
///
/// No refinement, may have inaccurate corners.
///
None,
///
/// Corners have subpixel coordinates.
/// High detection rate, very fast, reasonable accuracy.
///
Subpix,
///
/// High detection rate, fast, reasonable accuracy.
///
Contour,
///
/// Reasonable detection rate, slowest, but very accurate.
///
AprilTag
}
public readonly struct ArucoData
{
///
/// Dictionary used by the Aruco Marker.
///
public readonly ArucoDictionaryName Dictionary;
///
/// Type selector for the structure.
///
public readonly uint Id;
internal ArucoData(NativeBindings.MLMarkerTrackerDecodedArucoData nativeArucoData)
{
this.Dictionary = nativeArucoData.Dictionary;
this.Id = nativeArucoData.Id;
}
public override string ToString() =>
$"Id: {Id}\nDictionaryName: {this.Dictionary}";
}
public readonly struct BinaryData
{
public readonly byte[] Data;
internal BinaryData(byte[] data)
{
this.Data = data;
}
public override string ToString() => $"Data: {this.Data}";
}
///
/// Marker data as returned by the Magic Leap SDK
///
public readonly struct MarkerData
{
///
/// The type of marker that was detected.
///
public readonly MarkerType Type;
///
/// Aruco decoded data (if any exists).
///
public readonly ArucoData ArucoData;
///
/// Binary decoded data (if any exists).
///
public readonly BinaryData BinaryData;
///
/// The world-space position and rotation of the marker.
///
public readonly Pose Pose;
///
/// The reprojection error of this QR code detection in degrees.
///
/// The reprojection error is only useful when tracking QR codes. A high
/// reprojection error means that the estimated pose of the QR code doesn't match
/// well with the 2D detection on the processed video frame and thus the pose might
/// be inaccurate. The error is given in degrees, signifying by how much either
/// camera or QR code would have to be moved or rotated to create a perfect
/// reprojection. The further away your QR code is, the smaller this reprojection
/// error will be for the same displacement error of the code.
///
public readonly float ReprojectionError;
internal MarkerData(MarkerType Type, NativeBindings.MLMarkerTrackerDecodedArucoData NativeArucoData, byte[] BinaryDataResult, Pose Pose, float ReprojectionError)
{
this.Type = Type;
this.ArucoData = new ArucoData(NativeArucoData);
this.BinaryData = new BinaryData(BinaryDataResult);
this.Pose = Pose;
this.ReprojectionError = ReprojectionError;
}
public override string ToString()
{
string toString;
switch (this.Type)
{
case MarkerType.Aruco_April:
toString = $"\nType: {Enum.GetName(typeof(MLMarkerTracker.MarkerType), this.Type)}\nReprojection Error: {this.ReprojectionError}\n Data:\n {this.ArucoData}";
break;
case MarkerType.QR:
case MarkerType.EAN_13:
case MarkerType.UPC_A:
toString = $"\nType: {Enum.GetName(typeof(MLMarkerTracker.MarkerType), this.Type)}\nReprojection Error: {this.ReprojectionError}\n Data Length:\n{this.BinaryData.Data.Length} bytes";
break;
default:
toString = "Marker has no type.";
break;
}
return toString;
}
}
}
}