using System; using System.Diagnostics.CodeAnalysis; using System.Linq; using JetBrains.Annotations; 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 _); } public override void AddLabel(string labelToAdd) { m_LabelEntries.Add(new IdLabelEntry { label = labelToAdd }); if (autoAssignIds) { AutoAssignIds(); } } public override void RemoveLabel(string label) { base.RemoveLabel(label); if (autoAssignIds) { AutoAssignIds(); } } void AutoAssignIds() { var size = m_LabelEntries.Count; if (size == 0) return; var nextId = startingLabelId == StartingLabelId.One ? 1 : 0; for (int i = 0; i < size; i++) { var labelEntry = m_LabelEntries[i]; labelEntry.id = nextId; m_LabelEntries[i] = labelEntry; nextId++; } } /// /// 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) { if (m_LabelEntryMatchCache == null) m_LabelEntryMatchCache = new LabelEntryMatchCache(this); return m_LabelEntryMatchCache.TryGetLabelEntryFromInstanceId(instanceId, out labelEntry, out index); } /// 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(); } } }