using System; using System.Diagnostics.CodeAnalysis; using System.Linq; using JetBrains.Annotations; using Newtonsoft.Json; using Unity.Collections; namespace UnityEngine.Perception.GroundTruth { /// /// A definition for how a should be resolved to a single label and id for ground truth generation. /// [CreateAssetMenu(fileName = "IdLabelConfig", menuName = "Perception/ID Label Config", order = 1)] public class IdLabelConfig : LabelConfig { /// /// Whether the inspector will auto-assign ids based on the id of the first element. /// public bool autoAssignIds = true; /// /// Whether the inspector will start label ids at zero or one when is enabled. /// public StartingLabelId startingLabelId = StartingLabelId.One; LabelEntryMatchCache m_LabelEntryMatchCache; /// /// Attempts to find the label id for the given instance id. /// /// The instanceId of the object for which the labelId should be found /// The LabelEntry associated with the object. default if not found /// True if a labelId is found for the given instanceId. public bool TryGetLabelEntryFromInstanceId(uint instanceId, out IdLabelEntry labelEntry) { return TryGetLabelEntryFromInstanceId(instanceId, out labelEntry, out var _); } /// /// Attempts to find the label id for the given instance id. /// /// The instanceId of the object for which the labelId should be found /// The LabelEntry associated with the object. default if not found /// The index of the found LabelEntry in . -1 if not found /// True if a labelId is found for the given instanceId. public bool TryGetLabelEntryFromInstanceId(uint instanceId, out IdLabelEntry labelEntry, out int index) { EnsureInitLabelEntryMatchCache(); return m_LabelEntryMatchCache.TryGetLabelEntryFromInstanceId(instanceId, out labelEntry, out index); } private void EnsureInitLabelEntryMatchCache() { if (m_LabelEntryMatchCache == null) m_LabelEntryMatchCache = new LabelEntryMatchCache(this, Allocator.Persistent); } /// protected override void OnInit() { if (m_LabelEntryMatchCache != null) { throw new InvalidOperationException("Init may not be called after TryGetLabelEntryFromInstanceId has been called for the first time."); } } void OnDisable() { m_LabelEntryMatchCache?.Dispose(); m_LabelEntryMatchCache = null; } [SuppressMessage("ReSharper", "InconsistentNaming")] internal struct LabelEntrySpec { /// /// The label id prepared for reporting in the annotation /// [UsedImplicitly] public int label_id; /// /// The label name prepared for reporting in the annotation /// [UsedImplicitly] public string label_name; } internal LabelEntrySpec[] GetAnnotationSpecification() { return labelEntries.Select((l) => new LabelEntrySpec() { label_id = l.id, label_name = l.label, }).ToArray(); } /// /// Creates a LabelEntryMatchCache from the currently registered labeled objects, which can be used to look up /// labeling information in future frames, even after the objects have been destroyed. Due to timing of labeled /// object registration, if this is called during or before LateUpdate, this cache may become invalid. /// /// It is recommended to only use this method in rendering, as the cache is guaranteed to be in its final state /// for ground truth generation. /// /// The allocator for creating the cache. /// The created cache. public LabelEntryMatchCache CreateLabelEntryMatchCache(Allocator allocator) { EnsureInitLabelEntryMatchCache(); return m_LabelEntryMatchCache.CloneCurrentState(allocator); } } }