浏览代码

Merge branch 'labeling-improvements' into tutorial_updates_nov2020rel

/main
Mohsen Kamalzadeh 4 年前
当前提交
1e7e9391
共有 7 个文件被更改,包括 282 次插入286 次删除
  1. 27
      com.unity.perception/Editor/AssetPreparation/AssetPreparationTools.cs
  2. 206
      com.unity.perception/Editor/GroundTruth/AddToConfigWindow.cs
  3. 36
      com.unity.perception/Editor/GroundTruth/IdLabelConfigEditor.cs
  4. 107
      com.unity.perception/Editor/GroundTruth/LabelConfigEditor.cs
  5. 162
      com.unity.perception/Editor/GroundTruth/LabelingEditor.cs
  6. 28
      com.unity.perception/Editor/GroundTruth/SemanticSegmentationLabelConfigEditor.cs
  7. 2
      com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs

27
com.unity.perception/Editor/AssetPreparation/AssetPreparationTools.cs


namespace UnityEditor.Perception.AssetPreparation
{
public class CreatePrefabFromSelectedAssets : MonoBehaviour
class AssetPreparationTools
/// <summary>
/// Function for creating prefabs from multiple models with one click. Created prefabs will be placed in the same folder as their corresponding model.
/// </summary>
[MenuItem("Assets/Perception/Create Prefabs from Selected Models")]
static void CreatePrefabsFromSelectedModels()
class AssetPreparationMenuFunctions : MonoBehaviour
foreach (var selection in Selection.gameObjects)
/// <summary>
/// Function for creating prefabs from multiple models with one click. Created prefabs will be placed in the same folder as their corresponding model.
/// </summary>
[MenuItem("Assets/Perception/Create Prefabs from Selected Models")]
static void CreatePrefabsFromSelectedModels()
var path = AssetDatabase.GetAssetPath(selection);
var tmpGameObject = Instantiate(selection);
var destinationPath = Path.GetDirectoryName(path) + "/" + selection.name + ".prefab";
PrefabUtility.SaveAsPrefabAsset(tmpGameObject, destinationPath);
DestroyImmediate(tmpGameObject);
foreach (var selection in Selection.gameObjects)
{
var path = AssetDatabase.GetAssetPath(selection);
var tmpGameObject = Instantiate(selection);
var destinationPath = Path.GetDirectoryName(path) + "/" + selection.name + ".prefab";
PrefabUtility.SaveAsPrefabAsset(tmpGameObject, destinationPath);
DestroyImmediate(tmpGameObject);
}
}
}
}

206
com.unity.perception/Editor/GroundTruth/AddToConfigWindow.cs


{
class AddToConfigWindow : EditorWindow
{
private VisualElement m_Root;
VisualElement m_Root;
private string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
private string m_UxmlPath;
const string k_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
string m_UxmlPath;
private static List<string> m_LabelValues = new List<string>();
private static Label m_TitleLabel;
private static Label m_Status;
static List<string> s_LabelValues = new List<string>();
static Label s_TitleLabel;
static Label s_Status;
m_Status.text = status;
m_Status.style.display = DisplayStyle.Flex;
s_Status.text = status;
s_Status.style.display = DisplayStyle.Flex;
private List<string> m_AllLabelConfigGuids = new List<string>();
private List<ScriptableObject> m_ConfigsContainingLabel = new List<ScriptableObject>();
private List<ScriptableObject> m_ConfigsNotContainingLabel = new List<ScriptableObject>();
List<string> m_AllLabelConfigGuids = new List<string>();
List<ScriptableObject> m_ConfigsContainingLabel = new List<ScriptableObject>();
List<ScriptableObject> m_ConfigsNotContainingLabel = new List<ScriptableObject>();
private static ListView m_PresentConfigsListview;
private static ListView m_NonPresentConfigsListview;
private static ListView m_SelectedLabelsListview;
private static Label m_CurrentlyPresentTitle;
private static Label m_OtherConfigsTitle;
static ListView s_PresentConfigsListview;
static ListView s_NonPresentConfigsListview;
static ListView s_SelectedLabelsListview;
static Label s_CurrentlyPresentTitle;
static Label s_OtherConfigsTitle;
private List<Type> m_LabelConfigTypes = new List<Type>();
List<Type> m_LabelConfigTypes = new List<Type>();
m_LabelValues.Clear();
m_LabelValues.Add(labelValue);
ShowWindow(m_LabelValues);
s_LabelValues.Clear();
s_LabelValues.Add(labelValue);
ShowWindow(s_LabelValues);
m_LabelValues = new List<string>(labelValues);
s_LabelValues = new List<string>(labelValues);
if (m_Status != null)
if (s_Status != null)
m_Status.style.display = DisplayStyle.None;
s_Status.style.display = DisplayStyle.None;
if(m_TitleLabel != null)
m_TitleLabel.text = "Label: \"" + m_LabelValues.First() + "\"";
if(s_TitleLabel != null)
s_TitleLabel.text = "Label: \"" + s_LabelValues.First() + "\"";
if (m_PresentConfigsListview != null)
if (s_PresentConfigsListview != null)
m_PresentConfigsListview.style.display = DisplayStyle.Flex;
s_PresentConfigsListview.style.display = DisplayStyle.Flex;
if (m_CurrentlyPresentTitle != null)
if (s_CurrentlyPresentTitle != null)
m_CurrentlyPresentTitle.style.display = DisplayStyle.Flex;
s_CurrentlyPresentTitle.style.display = DisplayStyle.Flex;
if (m_OtherConfigsTitle != null)
if (s_OtherConfigsTitle != null)
m_OtherConfigsTitle.text = "Other Label Configs in Project";
s_OtherConfigsTitle.text = "Other Label Configs in Project";
if (m_NonPresentConfigsListview != null)
if (s_NonPresentConfigsListview != null)
m_NonPresentConfigsListview.style.height = 150;
s_NonPresentConfigsListview.style.height = 150;
if (m_SelectedLabelsListview != null)
if (s_SelectedLabelsListview != null)
m_SelectedLabelsListview.style.display = DisplayStyle.None;
s_SelectedLabelsListview.style.display = DisplayStyle.None;
}
window.titleContent = new GUIContent("Manage Label");

else
{
if(m_TitleLabel != null)
m_TitleLabel.text = "Labels to Add";
if(s_TitleLabel != null)
s_TitleLabel.text = "Labels to Add";
if (m_PresentConfigsListview != null)
if (s_PresentConfigsListview != null)
m_PresentConfigsListview.style.display = DisplayStyle.None;
s_PresentConfigsListview.style.display = DisplayStyle.None;
if (m_CurrentlyPresentTitle != null)
if (s_CurrentlyPresentTitle != null)
m_CurrentlyPresentTitle.style.display = DisplayStyle.None;
s_CurrentlyPresentTitle.style.display = DisplayStyle.None;
if (m_OtherConfigsTitle != null)
if (s_OtherConfigsTitle != null)
m_OtherConfigsTitle.text = "All Label Configurations in Project";
s_OtherConfigsTitle.text = "All Label Configurations in Project";
if (m_NonPresentConfigsListview != null)
if (s_NonPresentConfigsListview != null)
m_NonPresentConfigsListview.style.height = 250;
s_NonPresentConfigsListview.style.height = 250;
if (m_SelectedLabelsListview != null)
if (s_SelectedLabelsListview != null)
m_SelectedLabelsListview.style.display = DisplayStyle.Flex;
s_SelectedLabelsListview.style.display = DisplayStyle.Flex;
}

m_LabelConfigTypes = FindAllSubTypes(typeof(LabelConfig<>));
RefreshConfigAssets();
CheckInclusionInConfigs(m_AllLabelConfigGuids, m_LabelValues.Count == 1? m_LabelValues.First() : null);
CheckInclusionInConfigs(m_AllLabelConfigGuids, s_LabelValues.Count == 1? s_LabelValues.First() : null);
SetupListViews();
}

void SetupListViews()
{
//configs containing label
if (m_LabelValues.Count == 1)
if (s_LabelValues.Count == 1)
m_PresentConfigsListview.itemsSource = m_ConfigsContainingLabel;
VisualElement MakeItem1() => new ConfigElementLabelPresent(this, m_LabelValues.First());
s_PresentConfigsListview.itemsSource = m_ConfigsContainingLabel;
VisualElement MakeItem1() => new ConfigElementLabelPresent(this, s_LabelValues.First());
element.m_Label.text = m_ConfigsContainingLabel[i].name;
element.m_LabelConfig = m_ConfigsContainingLabel[i];
element.labelElement.text = m_ConfigsContainingLabel[i].name;
element.labelConfig = m_ConfigsContainingLabel[i];
m_PresentConfigsListview.itemHeight = 30;
m_PresentConfigsListview.bindItem = BindItem1;
m_PresentConfigsListview.makeItem = MakeItem1;
m_PresentConfigsListview.selectionType = SelectionType.None;
s_PresentConfigsListview.itemHeight = 30;
s_PresentConfigsListview.bindItem = BindItem1;
s_PresentConfigsListview.makeItem = MakeItem1;
s_PresentConfigsListview.selectionType = SelectionType.None;
m_NonPresentConfigsListview.itemsSource = m_ConfigsNotContainingLabel;
VisualElement MakeItem2() => new ConfigElementLabelNotPresent(this, m_LabelValues);
s_NonPresentConfigsListview.itemsSource = m_ConfigsNotContainingLabel;
VisualElement MakeItem2() => new ConfigElementLabelNotPresent(this, s_LabelValues);
element.m_Label.text = m_ConfigsNotContainingLabel[i].name;
element.m_LabelConfig = m_ConfigsNotContainingLabel[i];
element.labelElement.text = m_ConfigsNotContainingLabel[i].name;
element.labelConfig = m_ConfigsNotContainingLabel[i];
m_NonPresentConfigsListview.itemHeight = 30;
m_NonPresentConfigsListview.bindItem = BindItem2;
m_NonPresentConfigsListview.makeItem = MakeItem2;
m_NonPresentConfigsListview.selectionType = SelectionType.None;
s_NonPresentConfigsListview.itemHeight = 30;
s_NonPresentConfigsListview.bindItem = BindItem2;
s_NonPresentConfigsListview.makeItem = MakeItem2;
s_NonPresentConfigsListview.selectionType = SelectionType.None;
m_SelectedLabelsListview.itemsSource = m_LabelValues;
s_SelectedLabelsListview.itemsSource = s_LabelValues;
VisualElement MakeItem3() => new Label();
void BindItem3(VisualElement e, int i)

label.text = m_LabelValues[i];
label.text = s_LabelValues[i];
m_SelectedLabelsListview.itemHeight = 20;
m_SelectedLabelsListview.bindItem = BindItem3;
m_SelectedLabelsListview.makeItem = MakeItem3;
m_SelectedLabelsListview.selectionType = SelectionType.None;
s_SelectedLabelsListview.itemHeight = 20;
s_SelectedLabelsListview.bindItem = BindItem3;
s_SelectedLabelsListview.makeItem = MakeItem3;
s_SelectedLabelsListview.selectionType = SelectionType.None;
CheckInclusionInConfigs(m_AllLabelConfigGuids, m_LabelValues.Count == 1? m_LabelValues.First() : null);
m_PresentConfigsListview.Refresh();
m_NonPresentConfigsListview.Refresh();
CheckInclusionInConfigs(m_AllLabelConfigGuids, s_LabelValues.Count == 1? s_LabelValues.First() : null);
s_PresentConfigsListview.Refresh();
s_NonPresentConfigsListview.Refresh();
m_UxmlPath = m_UxmlDir + "AddToConfigWindow.uxml";
m_UxmlPath = k_UxmlDir + "AddToConfigWindow.uxml";
m_TitleLabel = m_Root.Q<Label>("title");
m_CurrentlyPresentTitle = m_Root.Q<Label>("currently-present-label");
m_OtherConfigsTitle = m_Root.Q<Label>("other-configs-label");
m_PresentConfigsListview = m_Root.Q<ListView>("current-configs-listview");
m_NonPresentConfigsListview = m_Root.Q<ListView>("other-configs-listview");
m_SelectedLabelsListview = m_Root.Q<ListView>("selected-labels-list");
m_Status = m_Root.Q<Label>("status");
m_Status.style.display = DisplayStyle.None;
s_TitleLabel = m_Root.Q<Label>("title");
s_CurrentlyPresentTitle = m_Root.Q<Label>("currently-present-label");
s_OtherConfigsTitle = m_Root.Q<Label>("other-configs-label");
s_PresentConfigsListview = m_Root.Q<ListView>("current-configs-listview");
s_NonPresentConfigsListview = m_Root.Q<ListView>("other-configs-listview");
s_SelectedLabelsListview = m_Root.Q<ListView>("selected-labels-list");
s_Status = m_Root.Q<Label>("status");
s_Status.style.display = DisplayStyle.None;
}
void CheckInclusionInConfigs(List<string> configGuids, string label = null)

class ConfigElementLabelPresent : VisualElement
{
private string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
private VisualElement m_Root;
private ObjectField m_ConfigObjectField;
const string k_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
VisualElement m_Root;
ObjectField m_ConfigObjectField;
public Label m_Label;
public ScriptableObject m_LabelConfig;
public Label labelElement;
public ScriptableObject labelConfig;
var uxmlPath = m_UxmlDir + "ConfigElementLabelPresent.uxml";
var uxmlPath = k_UxmlDir + "ConfigElementLabelPresent.uxml";
m_Label = this.Q<Label>("config-name");
labelElement = this.Q<Label>("config-name");
var removeButton = this.Q<Button>("remove-from-config-button");
removeButton.text = "Remove Label";

Selection.SetActiveObjectWithContext(m_LabelConfig, null);
Selection.SetActiveObjectWithContext(labelConfig, null);
var editor = Editor.CreateEditor(m_LabelConfig);
var editor = Editor.CreateEditor(labelConfig);
if (editor is SemanticSegmentationLabelConfigEditor semanticEditor)
{
semanticEditor.RemoveLabel(targetLabel);

}
window.RefreshLists();
//AssetDatabase.SaveAssets();
Object.DestroyImmediate(editor);
};
}

class ConfigElementLabelNotPresent : VisualElement
{
private string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
private VisualElement m_Root;
private ObjectField m_ConfigObjectField;
public Label m_Label;
public ScriptableObject m_LabelConfig;
const string k_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
VisualElement m_Root;
ObjectField m_ConfigObjectField;
public Label labelElement;
public ScriptableObject labelConfig;
var uxmlPath = m_UxmlDir + "ConfigElementLabelPresent.uxml";
var uxmlPath = k_UxmlDir + "ConfigElementLabelPresent.uxml";
m_Label = this.Q<Label>("config-name");
labelElement = this.Q<Label>("config-name");
var addButton = this.Q<Button>("remove-from-config-button");
addButton.text = targetLabels.Count ==1 ? "Add Label" : "Add All Labels";

Selection.SetActiveObjectWithContext(m_LabelConfig, null);
Selection.SetActiveObjectWithContext(labelConfig, null);
var editor = Editor.CreateEditor(m_LabelConfig);
var editor = Editor.CreateEditor(labelConfig);
if (editor is SemanticSegmentationLabelConfigEditor semanticEditor)
{
foreach (var label in targetLabels)

if (targetLabels.Count > 1)
{
window.SetStatus("All Labels Added to " + m_LabelConfig.name);
window.SetStatus("All Labels Added to " + labelConfig.name);
//AssetDatabase.SaveAssets();
Object.DestroyImmediate(editor);
};
}

36
com.unity.perception/Editor/GroundTruth/IdLabelConfigEditor.cs


AutoAssignIdsIfNeeded();
}
private void MoveSelectedItemUp()
void MoveSelectedItemUp()
{
var selectedIndex = m_LabelListView.selectedIndex;
if (selectedIndex > 0)

}
}
private void MoveSelectedItemDown()
void MoveSelectedItemDown()
{
var selectedIndex = m_LabelListView.selectedIndex;
if (selectedIndex > -1 && selectedIndex < m_SerializedLabelsArray.arraySize - 1)

{
if (e is IdLabelElementInLabelConfig addedLabel)
{
addedLabel.m_IndexInList = i;
addedLabel.m_LabelTextField.BindProperty(m_SerializedLabelsArray.GetArrayElementAtIndex(i)
addedLabel.indexInList = i;
addedLabel.labelTextField.BindProperty(m_SerializedLabelsArray.GetArrayElementAtIndex(i)
addedLabel.m_LabelIdTextField.value = m_SerializedLabelsArray.GetArrayElementAtIndex(i)
addedLabel.labelIdTextField.value = m_SerializedLabelsArray.GetArrayElementAtIndex(i)
.FindPropertyRelative(nameof(IdLabelEntry.id)).intValue.ToString();
}
}

public bool AutoAssign => serializedObject.FindProperty(nameof(IdLabelConfig.autoAssignIds)).boolValue;
private void AutoAssignIds()
void AutoAssignIds()
{
var serializedProperty = serializedObject.FindProperty(IdLabelConfig.labelEntriesFieldName);
var size = serializedProperty.arraySize;

EditorUtility.SetDirty(target);
}
private void AutoAssignIdsIfNeeded()
void AutoAssignIdsIfNeeded()
{
if (AutoAssign)
{

}
}
internal class IdLabelElementInLabelConfig : LabelElementInLabelConfig<IdLabelEntry>
class IdLabelElementInLabelConfig : LabelElementInLabelConfig<IdLabelEntry>
protected override string UxmlPath => UxmlDir + "IdLabelElementInLabelConfig.uxml";
protected override string UxmlPath => k_UxmlDir + "IdLabelElementInLabelConfig.uxml";
public TextField m_LabelIdTextField;
public TextField labelIdTextField;
public IdLabelElementInLabelConfig(LabelConfigEditor<IdLabelEntry> editor, SerializedProperty labelsArray) :
base(editor, labelsArray)

protected override void InitExtended()
{
m_LabelIdTextField = this.Q<TextField>("label-id-value");
m_LabelIdTextField.isDelayed = true;
m_LabelIdTextField.SetEnabled(!((IdLabelConfigEditor) m_LabelConfigEditor).AutoAssign);
m_LabelIdTextField.RegisterValueChangedCallback(evt =>
labelIdTextField = this.Q<TextField>("label-id-value");
labelIdTextField.isDelayed = true;
labelIdTextField.SetEnabled(!((IdLabelConfigEditor) m_LabelConfigEditor).AutoAssign);
labelIdTextField.RegisterValueChangedCallback(evt =>
m_LabelsArray.GetArrayElementAtIndex(m_IndexInList).FindPropertyRelative(nameof(IdLabelEntry.id))
m_LabelsArray.GetArrayElementAtIndex(indexInList).FindPropertyRelative(nameof(IdLabelEntry.id))
.intValue = parsedId;
if (m_LabelsArray.serializedObject.hasModifiedProperties)
{

}
int index = ((IdLabelConfigEditor)m_LabelConfigEditor).IndexOfGivenIdInSerializedLabelsArray(parsedId);
var index = ((IdLabelConfigEditor)m_LabelConfigEditor).IndexOfGivenIdInSerializedLabelsArray(parsedId);
if (index != -1 && index != m_IndexInList)
if (index != -1 && index != indexInList)
{
//The listview recycles child visual elements and that causes the RegisterValueChangedCallback event to be called when scrolling.
//Therefore, we need to make sure we are not in this code block just because of scrolling, but because the user is actively changing one of the labels.

else
{
Debug.LogError("Provided id is not a valid integer. Please provide integer values.");
m_LabelIdTextField.value = evt.previousValue;
labelIdTextField.value = evt.previousValue;
}
});
}

107
com.unity.perception/Editor/GroundTruth/LabelConfigEditor.cs


{
abstract class LabelConfigEditor<T> : Editor where T : ILabelEntry
{
private string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
private string m_UxmlPath;
string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
string m_UxmlPath;
private int m_AddedLabelsItemHeight = 37;
private int m_OtherLabelsItemHeight = 27;
int m_AddedLabelsItemHeight = 37;
int m_OtherLabelsItemHeight = 27;
private List<string> m_AddedLabels = new List<string>();
List<string> m_AddedLabels = new List<string>();
private static HashSet<string> allLabelsInProject = new HashSet<string>();
private List<string> m_LabelsNotPresentInConfig = new List<string>();
private bool m_UiInitialized;
private bool m_EditorHasUi;
HashSet<string> m_AllLabelsInProject = new HashSet<string>();
List<string> m_LabelsNotPresentInConfig = new List<string>();
bool m_UiInitialized;
bool m_EditorHasUi;
private VisualElement m_Root;
VisualElement m_Root;
private Button m_SaveButton;
private Button m_AddNewLabelButton;
private Button m_RemoveAllButton;
private Button m_AddAllButton;
private Button m_ImportFromFileButton;
private Button m_ExportToFileButton;
private ListView m_NonPresentLabelsListView;
Button m_SaveButton;
Button m_AddNewLabelButton;
Button m_RemoveAllButton;
Button m_AddAllButton;
Button m_ImportFromFileButton;
Button m_ExportToFileButton;
ListView m_NonPresentLabelsListView;
protected ListView m_LabelListView;
protected Button m_MoveUpButton;

RefreshListDataAndPresentation();
}
private int m_PreviousLabelsArraySize = -1;
int m_PreviousLabelsArraySize = -1;
private void CheckForModelChanges()
void CheckForModelChanges()
{
if (ChangesHappeningInForeground)
{

return m_Root;
}
private void InitUi()
void InitUi()
{
m_EditorHasUi = true;

m_AddNewLabelButton.clicked += () => { AddNewLabel(m_AddedLabels); };
#if UNITY_2020_1_OR_NEWER
m_LabelListView.onSelectionChange += UpdateMoveButtonState;
#else
#endif
m_RemoveAllButton.clicked += () =>
{
m_SerializedLabelsArray.ClearArray();

m_Root.schedule.Execute(CheckForModelChanges).Every(30);
}
static void RefreshLabelsMasterList()
void RefreshLabelsMasterList()
allLabelsInProject.Clear();
m_AllLabelsInProject.Clear();
var allPrefabPaths = GetAllPrefabsInProject();
foreach (var path in allPrefabPaths)

if (labeling)
{
allLabelsInProject.UnionWith(labeling.labels);
m_AllLabelsInProject.UnionWith(labeling.labels);
private void RefreshNonPresentLabels()
void RefreshNonPresentLabels()
m_LabelsNotPresentInConfig.AddRange(allLabelsInProject);
m_LabelsNotPresentInConfig.AddRange(m_AllLabelsInProject);
private static IEnumerable<string> GetAllPrefabsInProject()
static IEnumerable<string> GetAllPrefabsInProject()
private void UpdateMoveButtonState(IEnumerable<object> objectList)
void UpdateMoveButtonState(IEnumerable<object> objectList)
{
var selectedIndex = m_LabelListView.selectedIndex;
m_MoveDownButton.SetEnabled(selectedIndex < m_LabelListView.itemsSource.Count - 1);

}
}
private void ScrollToBottomAndSelectLastItem()
void ScrollToBottomAndSelectLastItem()
{
m_LabelListView.selectedIndex = m_LabelListView.itemsSource.Count - 1;
UpdateMoveButtonState(null);

m_LabelListView.RegisterCallback<AttachToPanelEvent>(evt => { RefreshListViewHeight(); });
}
private void SetupNonPresentLabelsListView()
void SetupNonPresentLabelsListView()
{
m_NonPresentLabelsListView.itemsSource = m_LabelsNotPresentInConfig;

{
if (e is NonPresentLabelElement<T> nonPresentLabel)
{
nonPresentLabel.m_Label.text = m_LabelsNotPresentInConfig[i];
nonPresentLabel.label.text = m_LabelsNotPresentInConfig[i];
}
}

return label;
}
private void AddNewLabel(List<string> presentLabels)
void AddNewLabel(List<string> presentLabels)
{
AddLabel(FindNewLabelString(presentLabels));
}

JsonUtility.FromJsonOverwrite(jsonObj.ToString(), serializedObject.targetObject);
ChangesHappeningInForeground = true;
RefreshListDataAndPresentation();
private string ExportToJson()
string ExportToJson()
{
return JsonUtility.ToJson(serializedObject.targetObject);
}

}
}
internal abstract class LabelElementInLabelConfig<T> : VisualElement where T : ILabelEntry
abstract class LabelElementInLabelConfig<T> : VisualElement where T : ILabelEntry
protected const string UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
protected const string k_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
private Button m_RemoveButton;
Button m_RemoveButton;
public TextField m_LabelTextField;
public TextField labelTextField;
public int m_IndexInList;
public int indexInList;
protected SerializedProperty m_LabelsArray;

Init();
}
private void Init()
void Init()
m_LabelTextField = this.Q<TextField>("label-value");
labelTextField = this.Q<TextField>("label-value");
m_LabelTextField.isDelayed = true;
labelTextField.isDelayed = true;
m_LabelTextField.RegisterValueChangedCallback((cEvent) =>
labelTextField.RegisterValueChangedCallback((cEvent) =>
if (index != -1 && index != m_IndexInList)
if (index != -1 && index != indexInList)
{
//The listview recycles child visual elements and that causes the RegisterValueChangedCallback event to be called when scrolling.
//Therefore, we need to make sure we are not in this code block just because of scrolling, but because the user is actively changing one of the labels.

m_LabelsArray.GetArrayElementAtIndex(m_IndexInList).FindPropertyRelative(nameof(ILabelEntry.label))
.stringValue = cEvent.previousValue; //since the textfield is bound to this property, it has already changed the property, so we need to revert the proprty.
m_LabelsArray.GetArrayElementAtIndex(indexInList).FindPropertyRelative(nameof(ILabelEntry.label))
.stringValue = cEvent.previousValue; //since the textfield is bound to this property, it has already changed the property, so we need to revert the property.
m_LabelsArray.serializedObject.ApplyModifiedProperties();
m_LabelConfigEditor.ChangesHappeningInForeground = true;
m_LabelConfigEditor.RefreshListDataAndPresentation();

//even though the textfield is already bound to the relevant property, we need to explicitly set the
//property here too in order to make "hasModifiedProperties" return the right value in the next line. Otherwise it will always be false.
m_LabelsArray.GetArrayElementAtIndex(m_IndexInList).FindPropertyRelative(nameof(ILabelEntry.label))
m_LabelsArray.GetArrayElementAtIndex(indexInList).FindPropertyRelative(nameof(ILabelEntry.label))
.stringValue = cEvent.newValue;
if (m_LabelsArray.serializedObject.hasModifiedProperties)
{

m_RemoveButton.clicked += () =>
{
m_LabelsArray.DeleteArrayElementAtIndex(m_IndexInList);
m_LabelsArray.DeleteArrayElementAtIndex(indexInList);
m_LabelConfigEditor.PostRemoveOperations();
m_LabelConfigEditor.serializedObject.ApplyModifiedProperties();
m_LabelConfigEditor.ChangesHappeningInForeground = true;

class NonPresentLabelElement<T> : VisualElement where T : ILabelEntry
{
private string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
public Label m_Label;
string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
public Label label;
m_Label = this.Q<Label>("label-value");
label = this.Q<Label>("label-value");
addButton.clicked += () => { editor.AddLabel(m_Label.text); };
addButton.clicked += () => { editor.AddLabel(label.text); };
}
}
}

162
com.unity.perception/Editor/GroundTruth/LabelingEditor.cs


[CustomEditor(typeof(Labeling)), CanEditMultipleObjects]
class LabelingEditor : Editor
{
private VisualElement m_Root;
private VisualElement m_ManualLabelingContainer;
private VisualElement m_AutoLabelingContainer;
private VisualElement m_FromLabelConfigsContainer;
private VisualElement m_SuggestedLabelsContainer;
private VisualElement m_SuggestedOnNamePanel;
private VisualElement m_SuggestedOnPathPanel;
private ListView m_CurrentLabelsListView;
private ListView m_SuggestLabelsListView_FromName;
private ListView m_SuggestLabelsListView_FromPath;
private ScrollView m_LabelConfigsScrollView;
private PopupField<string> m_LabelingSchemesPopup;
private Button m_AddButton;
private Button m_AddAutoLabelToConfButton;
private Toggle m_AutoLabelingToggle;
private Label m_CurrentAutoLabel;
private Label m_CurrentAutoLabelTitle;
private Label m_AddManualLabelsTitle;
VisualElement m_Root;
VisualElement m_ManualLabelingContainer;
VisualElement m_AutoLabelingContainer;
VisualElement m_FromLabelConfigsContainer;
VisualElement m_SuggestedLabelsContainer;
VisualElement m_SuggestedOnNamePanel;
VisualElement m_SuggestedOnPathPanel;
ListView m_CurrentLabelsListView;
ListView m_SuggestedLabelsListViewFromName;
ListView m_SuggestedLabelsListViewFromPath;
ScrollView m_LabelConfigsScrollView;
PopupField<string> m_LabelingSchemesPopup;
Button m_AddButton;
Button m_AddAutoLabelToConfButton;
Toggle m_AutoLabelingToggle;
Label m_CurrentAutoLabel;
Label m_CurrentAutoLabelTitle;
Label m_AddManualLabelsTitle;
private Labeling m_Labeling;
Labeling m_Labeling;
private string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
private string m_UxmlPath;
string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
string m_UxmlPath;
private List<string> m_SuggestedLabelsBasedOnName = new List<string>();
private List<string> m_SuggestedLabelsBasedOnPath = new List<string>();
List<string> m_SuggestedLabelsBasedOnName = new List<string>();
List<string> m_SuggestedLabelsBasedOnPath = new List<string>();
private List<Type> m_LabelConfigTypes;
private readonly List<ScriptableObject> m_AllLabelConfigsInProject = new List<ScriptableObject>();
List<Type> m_LabelConfigTypes;
readonly List<ScriptableObject> m_AllLabelConfigsInProject = new List<ScriptableObject>();
private readonly List<AssetLabelingScheme> m_LabelingSchemes = new List<AssetLabelingScheme>();
readonly List<AssetLabelingScheme> m_LabelingSchemes = new List<AssetLabelingScheme>();
/// <summary>
/// List of separator characters used for parsing asset names for auto labeling or label suggestion purposes

/// </summary>
public static readonly string[] PathSeparators = {"/"};
private void OnEnable()
void OnEnable()
{
m_LabelConfigTypes = AddToConfigWindow.FindAllSubTypes(typeof(LabelConfig<>));

m_Root = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(m_UxmlPath).CloneTree();
m_CurrentLabelsListView = m_Root.Q<ListView>("current-labels-listview");
m_SuggestLabelsListView_FromName = m_Root.Q<ListView>("suggested-labels-name-listview");
m_SuggestLabelsListView_FromPath = m_Root.Q<ListView>("suggested-labels-path-listview");
m_SuggestedLabelsListViewFromName = m_Root.Q<ListView>("suggested-labels-name-listview");
m_SuggestedLabelsListViewFromPath = m_Root.Q<ListView>("suggested-labels-path-listview");
m_LabelConfigsScrollView = m_Root.Q<ScrollView>("label-configs-scrollview");
m_SuggestedOnNamePanel = m_Root.Q<VisualElement>("suggested-labels-from-name");
m_SuggestedOnPathPanel = m_Root.Q<VisualElement>("suggested-labels-from-path");

m_Root.schedule.Execute(CheckForModelChanges).Every(30);
}
private int m_PreviousLabelsArraySize = -1;
int m_PreviousLabelsArraySize = -1;
/// <summary>
/// This boolean is used to signify when changes in the model are triggered directly from the inspector UI by the user.
/// In these cases, the scheduled model checker does not need to update the UI again.

private SerializedProperty m_FirstItemLabelsArray;
private void CheckForModelChanges()
SerializedProperty m_FirstItemLabelsArray;
void CheckForModelChanges()
{
if (ChangesHappeningInForeground)
{

}
}
private bool SerializedObjectHasValidLabelingScheme(SerializedObject serObj)
bool SerializedObjectHasValidLabelingScheme(SerializedObject serObj)
private bool IsValidLabelingSchemeName(string schemeName)
bool IsValidLabelingSchemeName(string schemeName)
private bool m_ItIsPossibleToAddMultipleAutoLabelsToConfig;
private void UpdateUiAspects()
bool m_ItIsPossibleToAddMultipleAutoLabelsToConfig;
void UpdateUiAspects()
{
m_ManualLabelingContainer.SetEnabled(!m_AutoLabelingToggle.value);
m_AutoLabelingContainer.SetEnabled(m_AutoLabelingToggle.value);

}
}
private void UpdateCurrentAutoLabelValue(SerializedObject serObj)
void UpdateCurrentAutoLabelValue(SerializedObject serObj)
{
var array = serObj.FindProperty(nameof(Labeling.labels));
if (array.arraySize > 0)

}
private bool AreSelectedAssetsCompatibleWithAutoLabelScheme(AssetLabelingScheme scheme)
bool AreSelectedAssetsCompatibleWithAutoLabelScheme(AssetLabelingScheme scheme)
{
foreach (var asset in serializedObject.targetObjects)
{

return true;
}
private void InitializeLabelingSchemes(VisualElement parent)
void InitializeLabelingSchemes(VisualElement parent)
{
//this function should be called only once during the lifecycle of the editor element
AssetLabelingScheme labelingScheme = new AssetNameLabelingScheme();

m_LabelingSchemesPopup.RegisterValueChangedCallback(evt => AssignAutomaticLabelToSelectedAssets());
}
private void AutoLabelToggleChanged()
void AutoLabelToggleChanged()
{
UpdateUiAspects();

RefreshManualLabelingData();
}
private void AssignAutomaticLabelToSelectedAssets()
void AssignAutomaticLabelToSelectedAssets()
{
//the 0th index of this popup is "<Select Scheme>" and should not do anything
if (m_LabelingSchemesPopup.index == 0)

RefreshManualLabelingData();
}
private void AssesAutoLabelingStatus()
void AssesAutoLabelingStatus()
{
var enabledOrNot = true;
if (serializedObject.targetObjects.Length == 1)

UpdateUiAspects();
}
private HashSet<string> CreateUnionOfAllLabels()
HashSet<string> CreateUnionOfAllLabels()
{
HashSet<String> result = new HashSet<string>();
foreach (var obj in targets)

}
return result;
}
private string FindNewLabelValue(HashSet<string> labels)
string FindNewLabelValue(HashSet<string> labels)
{
string baseLabel = "New Label";
string label = baseLabel;

}
}
public void RemoveAddedLabelsFromSuggestedLists()
void RemoveAddedLabelsFromSuggestedLists()
public void RefreshSuggestedLabelLists()
void RefreshSuggestedLabelLists()
{
m_SuggestedLabelsBasedOnName.Clear();
m_SuggestedLabelsBasedOnPath.Clear();

{
if (e is AddedLabelEditor addedLabel)
{
addedLabel.m_IndexInList = i;
addedLabel.m_LabelTextField.value = CommonLabels[i];
addedLabel.indexInList = i;
addedLabel.labelTextField.value = CommonLabels[i];
}
}

void SetupSuggestedLabelsListViews()
{
SetupSuggestedLabelsBasedOnFlatList(m_SuggestLabelsListView_FromName, m_SuggestedLabelsBasedOnName);
SetupSuggestedLabelsBasedOnFlatList(m_SuggestLabelsListView_FromPath, m_SuggestedLabelsBasedOnPath);
SetupSuggestedLabelsBasedOnFlatList(m_SuggestedLabelsListViewFromName, m_SuggestedLabelsBasedOnName);
SetupSuggestedLabelsBasedOnFlatList(m_SuggestedLabelsListViewFromPath, m_SuggestedLabelsBasedOnPath);
}
void SetupSuggestedLabelsBasedOnFlatList(ListView labelsListView, List<string> stringList)

{
if (e is SuggestedLabelElement suggestedLabel)
{
suggestedLabel.m_Label.text = stringList[i];
suggestedLabel.label.text = stringList[i];
}
}

}
}
internal class AddedLabelEditor : VisualElement
class AddedLabelEditor : VisualElement
private string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
public TextField m_LabelTextField;
public int m_IndexInList;
public TextField labelTextField;
public int indexInList;
m_LabelTextField = this.Q<TextField>("label-value");
labelTextField = this.Q<TextField>("label-value");
m_LabelTextField.isDelayed = true;
labelTextField.isDelayed = true;
m_LabelTextField.RegisterValueChangedCallback((cEvent) =>
labelTextField.RegisterValueChangedCallback((cEvent) =>
if (editor.CommonLabels.Contains(cEvent.newValue) && editor.CommonLabels.IndexOf(cEvent.newValue) != m_IndexInList)
if (editor.CommonLabels.Contains(cEvent.newValue) && editor.CommonLabels.IndexOf(cEvent.newValue) != indexInList)
{
//The listview recycles child visual elements and that causes the RegisterValueChangedCallback event to be called when scrolling.
//Therefore, we need to make sure we are not in this code block just because of scrolling, but because the user is actively changing one of the labels.

if (targetObject is Labeling labeling)
{
var indexToModifyInTargetLabelList =
labeling.labels.IndexOf(editor.CommonLabels[m_IndexInList]);
labeling.labels.IndexOf(editor.CommonLabels[indexInList]);
var serializedLabelingObject2 = new SerializedObject(labeling);

addToConfigButton.clicked += () =>
{
AddToConfigWindow.ShowWindow(m_LabelTextField.value);
AddToConfigWindow.ShowWindow(labelTextField.value);
};
removeButton.clicked += () =>

var serializedLabelingObject2 = new SerializedObject(labeling);
var serializedLabelArray2 = serializedLabelingObject2.FindProperty("labels");
serializedLabelArray2.DeleteArrayElementAtIndex(commonsIndexToLabelsIndex[m_IndexInList]);
serializedLabelArray2.DeleteArrayElementAtIndex(commonsIndexToLabelsIndex[indexInList]);
internal class SuggestedLabelElement : VisualElement
class SuggestedLabelElement : VisualElement
private string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
public Label m_Label;
string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
public Label label;
m_Label = this.Q<Label>("label-value");
label = this.Q<Label>("label-value");
var addButton = this.Q<Button>("add-button");
addButton.clicked += () =>

if (targetObject is Labeling labeling)
{
if (labeling.labels.Contains(m_Label.text))
if (labeling.labels.Contains(label.text))
serializedLabelArray2.GetArrayElementAtIndex(serializedLabelArray2.arraySize-1).stringValue = m_Label.text;
serializedLabelArray2.GetArrayElementAtIndex(serializedLabelArray2.arraySize-1).stringValue = label.text;
serializedLabelingObject2.ApplyModifiedProperties();
serializedLabelingObject2.SetIsDifferentCacheDirty();
editor.serializedObject.SetIsDifferentCacheDirty();

}
}
internal class LabelConfigElement : VisualElement
class LabelConfigElement : VisualElement
private string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
private bool m_Collapsed = true;
string m_UxmlDir = "Packages/com.unity.perception/Editor/GroundTruth/Uxml/";
bool m_Collapsed = true;
private ListView m_LabelsListView;
private VisualElement m_CollapseToggle;
ListView m_LabelsListView;
VisualElement m_CollapseToggle;
public LabelConfigElement(LabelingEditor editor, ScriptableObject config)
{

{
if (e is SuggestedLabelElement suggestedLabel)
{
suggestedLabel.m_Label.text = labelList[i];
suggestedLabel.label.text = labelList[i];
}
}

/// <summary>
/// A labeling scheme based on which an automatic label can be produced for a given asset. E.g. based on asset name, asset path, etc.
/// </summary>
internal abstract class AssetLabelingScheme
abstract class AssetLabelingScheme
{
/// <summary>
/// The description of how this scheme generates labels. Used in the dropdown menu in the UI.

/// <summary>
/// Asset labeling scheme that outputs the given asset's name as its automatic label
/// </summary>
internal class AssetNameLabelingScheme : AssetLabelingScheme
class AssetNameLabelingScheme : AssetLabelingScheme
{
///<inheritdoc/>
public override string Description => "Use asset name";

/// <summary>
/// Asset labeling scheme that outputs the given asset's file name, including extension, as its automatic label
/// </summary>
internal class AssetFileNameLabelingScheme : AssetLabelingScheme
class AssetFileNameLabelingScheme : AssetLabelingScheme
{
///<inheritdoc/>
public override string Description => "Use file name with extension";

/// <summary>
/// Asset labeling scheme that outputs the given asset's folder name as its automatic label
/// </summary>
internal class CurrentOrParentsFolderNameLabelingScheme : AssetLabelingScheme
class CurrentOrParentsFolderNameLabelingScheme : AssetLabelingScheme
{
///<inheritdoc/>
public override string Description => "Use the asset's folder name";

28
com.unity.perception/Editor/GroundTruth/SemanticSegmentationLabelConfigEditor.cs


{
if (e is ColoredLabelElementInLabelConfig addedLabel)
{
addedLabel.m_IndexInList = i;
addedLabel.m_LabelTextField.BindProperty(m_SerializedLabelsArray.GetArrayElementAtIndex(i)
addedLabel.indexInList = i;
addedLabel.labelTextField.BindProperty(m_SerializedLabelsArray.GetArrayElementAtIndex(i)
addedLabel.m_ColorField.BindProperty(m_SerializedLabelsArray.GetArrayElementAtIndex(i)
addedLabel.colorField.BindProperty(m_SerializedLabelsArray.GetArrayElementAtIndex(i)
.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.color)));
}
}

standardColorList.Remove(item.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.color)).colorValue);
}
Color foundColor;
if (standardColorList.Any())
foundColor = standardColorList.First();
else
foundColor = Random.ColorHSV(0, 1, .5f, 1, 1, 1);
var foundColor = standardColorList.Any() ? standardColorList.First() : Random.ColorHSV(0, 1, .5f, 1, 1, 1);
return new SemanticSegmentationLabelEntry
{

}
}
internal class ColoredLabelElementInLabelConfig : LabelElementInLabelConfig<SemanticSegmentationLabelEntry>
class ColoredLabelElementInLabelConfig : LabelElementInLabelConfig<SemanticSegmentationLabelEntry>
protected override string UxmlPath => UxmlDir + "ColoredLabelElementInLabelConfig.uxml";
protected override string UxmlPath => k_UxmlDir + "ColoredLabelElementInLabelConfig.uxml";
public ColorField m_ColorField;
public ColorField colorField;
private Color previousColor;
m_ColorField = this.Q<ColorField>("label-color-value");
colorField = this.Q<ColorField>("label-color-value");
m_ColorField.RegisterValueChangedCallback((cEvent) =>
colorField.RegisterValueChangedCallback((cEvent) =>
int index = ((SemanticSegmentationLabelConfigEditor)m_LabelConfigEditor).IndexOfGivenColorInSerializedLabelsArray(cEvent.newValue);
var index = ((SemanticSegmentationLabelConfigEditor)m_LabelConfigEditor).IndexOfGivenColorInSerializedLabelsArray(cEvent.newValue);
if (index != -1 && index != m_IndexInList)
if (index != -1 && index != indexInList)
{
//The listview recycles child visual elements and that causes the RegisterValueChangedCallback event to be called when scrolling.
//Therefore, we need to make sure we are not in this code block just because of scrolling, but because the user is actively changing one of the labels.

2
com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs


m_AsyncAnnotations[Time.frameCount] = perceptionCamera.SensorHandle.ReportAnnotationAsync(m_BoundingBoxAnnotationDefinition);
}
private int count = 0;
void OnRenderedObjectInfosCalculated(int frameCount, NativeArray<RenderedObjectInfo> renderedObjectInfos)
{
if (!m_AsyncAnnotations.TryGetValue(frameCount, out var asyncAnnotation))

count++;
using (s_BoundingBoxCallback.Auto())
{
m_BoundingBoxValues.Clear();

正在加载...
取消
保存