浏览代码
Extensible labelers (#28)
Extensible labelers (#28)
* Refactor PerceptionCamera into CameraLabeler and its subclasses/main
GitHub
5 年前
当前提交
4caee75b
共有 91 个文件被更改,包括 3643 次插入 和 1700 次删除
-
139TestProjects/PerceptionHDRP/Assets/Scenes/SampleScene.unity
-
5TestProjects/PerceptionHDRP/Packages/manifest.json
-
2TestProjects/PerceptionHDRP/ProjectSettings/EditorSettings.asset
-
4TestProjects/PerceptionHDRP/ProjectSettings/ProjectVersion.txt
-
124TestProjects/PerceptionURP/Assets/Scenes/SampleScene.unity
-
5TestProjects/PerceptionURP/Packages/manifest.json
-
2TestProjects/PerceptionURP/ProjectSettings/EditorSettings.asset
-
4TestProjects/PerceptionURP/ProjectSettings/ProjectVersion.txt
-
2TestProjects/PerceptionURP/ProjectSettings/QualitySettings.asset
-
12com.unity.perception/Editor/GroundTruth/LabelingEditor.cs
-
2com.unity.perception/Editor/GroundTruth/SemanticSegmentationPassEditor.cs
-
6com.unity.perception/Editor/Unity.Perception.Editor.asmdef
-
4com.unity.perception/Runtime/GroundTruth/Ego.cs
-
9com.unity.perception/Runtime/GroundTruth/GroundTruthRendererFeature.cs
-
2com.unity.perception/Runtime/GroundTruth/Labeling/StartingLabelId.cs
-
559com.unity.perception/Runtime/GroundTruth/PerceptionCamera.cs
-
13com.unity.perception/Runtime/GroundTruth/RenderedObjectInfo.cs
-
77com.unity.perception/Runtime/GroundTruth/RenderedObjectInfoGenerator.cs
-
8com.unity.perception/Runtime/GroundTruth/Resources/SemanticSegmentation.shader
-
20com.unity.perception/Runtime/GroundTruth/SemanticSegmentationCrossPipelinePass.cs
-
8com.unity.perception/Runtime/GroundTruth/SemanticSegmentationPass.cs
-
3com.unity.perception/Runtime/GroundTruth/SimulationState.cs
-
143com.unity.perception/Tests/Editor/PerceptionCameraEditorTests.cs
-
8com.unity.perception/Tests/Editor/Unity.Perception.Editor.Tests.asmdef
-
50com.unity.perception/Tests/Runtime/GroundTruthTests/PerceptionCameraIntegrationTests.cs
-
128com.unity.perception/Tests/Runtime/GroundTruthTests/SegmentationGroundTruthTests.cs
-
2com.unity.perception/Tests/Runtime/Unity.Perception.Runtime.Tests.asmdef
-
2com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureSensorSchedulingTests.cs.meta
-
2com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs.meta
-
2com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureTests.cs.meta
-
23TestProjects/PerceptionHDRP/Assets/IdLabelConfig.asset
-
8TestProjects/PerceptionHDRP/Assets/IdLabelConfig.asset.meta
-
21TestProjects/PerceptionHDRP/Assets/SemanticSegmentationLabelingConfiguration.asset
-
8TestProjects/PerceptionHDRP/Assets/SemanticSegmentationLabelingConfiguration.asset.meta
-
541TestProjects/PerceptionHDRP/Packages/packages-lock.json
-
2TestProjects/PerceptionHDRP/PerceptionHDRP.sln.DotSettings
-
23TestProjects/PerceptionURP/Assets/IdLabelConfig.asset
-
8TestProjects/PerceptionURP/Assets/IdLabelConfig.asset.meta
-
8TestProjects/PerceptionURP/Assets/Resources.meta
-
21TestProjects/PerceptionURP/Assets/SemanticSegmentationLabelingConfiguration.asset
-
8TestProjects/PerceptionURP/Assets/SemanticSegmentationLabelingConfiguration.asset.meta
-
519TestProjects/PerceptionURP/Packages/packages-lock.json
-
2TestProjects/PerceptionURP/PerceptionURP.sln.DotSettings
-
156com.unity.perception/Editor/GroundTruth/CameraLabelerDrawer.cs
-
3com.unity.perception/Editor/GroundTruth/CameraLabelerDrawer.cs.meta
-
23com.unity.perception/Editor/GroundTruth/CameraLabelerDrawerAttribute.cs
-
3com.unity.perception/Editor/GroundTruth/CameraLabelerDrawerAttribute.cs.meta
-
146com.unity.perception/Editor/GroundTruth/IdLabelConfigEditor.cs
-
131com.unity.perception/Editor/GroundTruth/PerceptionCameraEditor.cs
-
3com.unity.perception/Editor/GroundTruth/PerceptionCameraEditor.cs.meta
-
91com.unity.perception/Editor/GroundTruth/SemanticSegmentationLabelConfigEditor.cs
-
3com.unity.perception/Editor/GroundTruth/SemanticSegmentationLabelConfigEditor.cs.meta
-
3com.unity.perception/Runtime/GroundTruth/Labelers.meta
-
106com.unity.perception/Runtime/GroundTruth/Labeling/IdLabelConfig.cs
-
3com.unity.perception/Runtime/GroundTruth/Labeling/IdLabelConfig.cs.meta
-
104com.unity.perception/Runtime/GroundTruth/Labeling/LabelConfig.cs
-
3com.unity.perception/Runtime/GroundTruth/Labeling/LabelConfig.cs.meta
-
55com.unity.perception/Runtime/GroundTruth/Labeling/LabelEntryMatchCache.cs
-
3com.unity.perception/Runtime/GroundTruth/Labeling/LabelEntryMatchCache.cs.meta
-
28com.unity.perception/Runtime/GroundTruth/Labeling/SemanticSegmentationLabelConfig.cs
-
3com.unity.perception/Runtime/GroundTruth/Labeling/SemanticSegmentationLabelConfig.cs.meta
-
83com.unity.perception/Runtime/GroundTruth/PerceptionCamera_InstanceSegmentation.cs
-
3com.unity.perception/Runtime/GroundTruth/PerceptionCamera_InstanceSegmentation.cs.meta
-
125com.unity.perception/Tests/Runtime/GroundTruthTests/ObjectCountLabelerTests.cs
-
159com.unity.perception/Tests/Runtime/GroundTruthTests/RenderedObjectInfoTests.cs
-
115com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs
-
71com.unity.perception/Runtime/GroundTruth/Labelers/CameraLabeler.cs
-
3com.unity.perception/Runtime/GroundTruth/Labelers/CameraLabeler.cs.meta
-
138com.unity.perception/Runtime/GroundTruth/Labelers/ObjectCountLabeler.cs
-
3com.unity.perception/Runtime/GroundTruth/Labelers/ObjectCountLabeler.cs.meta
-
125com.unity.perception/Runtime/GroundTruth/Labelers/RenderedObjectInfoLabeler.cs
-
11com.unity.perception/Runtime/GroundTruth/Labelers/RenderedObjectInfoLabeler.cs.meta
-
216com.unity.perception/Runtime/GroundTruth/Labelers/SemanticSegmentationLabeler.cs
-
11com.unity.perception/Runtime/GroundTruth/Labelers/SemanticSegmentationLabeler.cs.meta
-
8TestProjects/PerceptionHDRP/Assets/LabelingConfiguration.asset.meta
-
26TestProjects/PerceptionHDRP/Assets/LabelingConfiguration.asset
-
26TestProjects/PerceptionURP/Assets/ExampleLabelingConfiguration.asset
-
8TestProjects/PerceptionURP/Assets/ExampleLabelingConfiguration.asset.meta
-
21com.unity.perception/Editor/GroundTruth/ObjectCountPassEditor.cs
-
157com.unity.perception/Editor/GroundTruth/LabelingConfigurationEditor.cs
-
108com.unity.perception/Runtime/GroundTruth/Labeling/LabelingConfiguration.cs
-
181com.unity.perception/Runtime/GroundTruth/ObjectCountPass.cs
-
192com.unity.perception/Tests/Runtime/GroundTruthTests/BoundingBox2DTests.cs
-
147com.unity.perception/Tests/Runtime/GroundTruthTests/ObjectCountTests.cs
-
0/com.unity.perception/Editor/GroundTruth/IdLabelConfigEditor.cs.meta
-
0/com.unity.perception/Tests/Runtime/GroundTruthTests/RenderedObjectInfoTests.cs.meta
-
0/com.unity.perception/Tests/Runtime/GroundTruthTests/ObjectCountLabelerTests.cs.meta
-
0/com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureSensorSchedulingTests.cs.meta
-
0/com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs.meta
-
0/com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureTests.cs.meta
|
|||
m_EditorVersion: 2019.3.13f1 |
|||
m_EditorVersionWithRevision: 2019.3.13f1 (d4ddf0d95db9) |
|||
m_EditorVersion: 2019.4.1f1 |
|||
m_EditorVersionWithRevision: 2019.4.1f1 (e6c045e14e4e) |
|
|||
m_EditorVersion: 2019.3.13f1 |
|||
m_EditorVersionWithRevision: 2019.3.13f1 (d4ddf0d95db9) |
|||
m_EditorVersion: 2019.4.1f1 |
|||
m_EditorVersionWithRevision: 2019.4.1f1 (e6c045e14e4e) |
|
|||
%YAML 1.1 |
|||
%TAG !u! tag:unity3d.com,2011: |
|||
--- !u!114 &11400000 |
|||
MonoBehaviour: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 0} |
|||
m_Enabled: 1 |
|||
m_EditorHideFlags: 0 |
|||
m_Script: {fileID: 0} |
|||
m_Name: IdLabelConfig |
|||
m_EditorClassIdentifier: Unity.Perception.Runtime:UnityEngine.Perception.GroundTruth:IdLabelConfig |
|||
m_LabelEntries: |
|||
- label: Box |
|||
id: 1 |
|||
- label: Cube |
|||
id: 2 |
|||
- label: Crate |
|||
id: 3 |
|||
autoAssignIds: 1 |
|||
startingLabelId: 1 |
|
|||
fileFormatVersion: 2 |
|||
guid: 034ffd4e09ffb7348b2fe6634259058a |
|||
NativeFormatImporter: |
|||
externalObjects: {} |
|||
mainObjectFileID: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
%YAML 1.1 |
|||
%TAG !u! tag:unity3d.com,2011: |
|||
--- !u!114 &11400000 |
|||
MonoBehaviour: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 0} |
|||
m_Enabled: 1 |
|||
m_EditorHideFlags: 0 |
|||
m_Script: {fileID: 11500000, guid: a9d0176327854820ab53adc46cbec7c1, type: 3} |
|||
m_Name: SemanticSegmentationLabelingConfiguration |
|||
m_EditorClassIdentifier: |
|||
LabelEntries: |
|||
- label: Box |
|||
color: {r: 1, g: 0, b: 0, a: 1} |
|||
- label: Cube |
|||
color: {r: 0, g: 0.024693727, b: 1, a: 1} |
|||
- label: Crate |
|||
color: {r: 0, g: 1, b: 0.16973758, a: 1} |
|
|||
fileFormatVersion: 2 |
|||
guid: c140c5aa05dd09e4fadaa26de31b1f39 |
|||
NativeFormatImporter: |
|||
externalObjects: {} |
|||
mainObjectFileID: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
{ |
|||
"dependencies": { |
|||
"com.unity.burst": { |
|||
"version": "1.3.0-preview.5", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.mathematics": "1.1.0" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.collab-proxy": { |
|||
"version": "1.2.16", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.collections": { |
|||
"version": "0.7.0-preview.2", |
|||
"depth": 3, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.test-framework.performance": "1.3.3-preview", |
|||
"com.unity.burst": "1.3.0-preview.5" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.entities": { |
|||
"version": "0.8.0-preview.8", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.burst": "1.3.0-preview.5", |
|||
"com.unity.properties": "0.10.4-preview", |
|||
"com.unity.mathematics": "1.1.0", |
|||
"com.unity.serialization": "0.6.4-preview", |
|||
"com.unity.test-framework.performance": "1.3.3-preview", |
|||
"nuget.mono-cecil": "0.1.5-preview", |
|||
"com.unity.jobs": "0.2.7-preview.11", |
|||
"com.unity.scriptablebuildpipeline": "1.6.4-preview", |
|||
"com.unity.platforms": "0.2.1-preview.4" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.ext.nunit": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.ide.rider": { |
|||
"version": "1.1.4", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.test-framework": "1.1.1" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.ide.vscode": { |
|||
"version": "1.2.1", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.jobs": { |
|||
"version": "0.2.7-preview.11", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.collections": "0.7.0-preview.2", |
|||
"com.unity.mathematics": "1.1.0" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.mathematics": { |
|||
"version": "1.1.0", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.nuget.newtonsoft-json": { |
|||
"version": "1.1.2", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.package-validation-suite": { |
|||
"version": "0.9.1-preview", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"nuget.mono-cecil": "0.1.6-preview" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.perception": { |
|||
"version": "file:../../../com.unity.perception", |
|||
"depth": 0, |
|||
"source": "local", |
|||
"dependencies": { |
|||
"com.unity.nuget.newtonsoft-json": "1.1.2", |
|||
"com.unity.render-pipelines.core": "7.1.6", |
|||
"com.unity.entities": "0.8.0-preview.8", |
|||
"com.unity.simulation.capture": "0.0.10-preview.6", |
|||
"com.unity.simulation.core": "0.0.10-preview.8" |
|||
} |
|||
}, |
|||
"com.unity.platforms": { |
|||
"version": "0.2.1-preview.4", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.nuget.newtonsoft-json": "1.1.2", |
|||
"com.unity.properties": "0.10.4-preview", |
|||
"com.unity.searcher": "4.0.9", |
|||
"com.unity.serialization": "0.6.4-preview" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.properties": { |
|||
"version": "0.10.4-preview", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.collections": "0.1.1-preview", |
|||
"com.unity.test-framework.performance": "1.0.9-preview" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.render-pipelines.core": { |
|||
"version": "7.3.1", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.ugui": "1.0.0" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.render-pipelines.high-definition": { |
|||
"version": "7.3.1", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.render-pipelines.core": "7.3.1", |
|||
"com.unity.shadergraph": "7.3.1", |
|||
"com.unity.visualeffectgraph": "7.3.1", |
|||
"com.unity.render-pipelines.high-definition-config": "7.3.1" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.render-pipelines.high-definition-config": { |
|||
"version": "7.3.1", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.render-pipelines.core": "7.3.1" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.scriptablebuildpipeline": { |
|||
"version": "1.6.4-preview", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.searcher": { |
|||
"version": "4.0.9", |
|||
"depth": 3, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.serialization": { |
|||
"version": "0.6.4-preview", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.burst": "1.1.2", |
|||
"com.unity.collections": "0.1.1-preview", |
|||
"com.unity.jobs": "0.1.1-preview", |
|||
"com.unity.mathematics": "1.1.0", |
|||
"com.unity.properties": "0.10.4-preview", |
|||
"com.unity.test-framework.performance": "1.0.9-preview" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.shadergraph": { |
|||
"version": "7.3.1", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.render-pipelines.core": "7.3.1" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.simulation.capture": { |
|||
"version": "0.0.10-preview.6", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.simulation.core": "0.0.10-preview.8" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.simulation.core": { |
|||
"version": "0.0.10-preview.8", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.test-framework": { |
|||
"version": "1.1.14", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.ext.nunit": "1.0.0", |
|||
"com.unity.modules.imgui": "1.0.0", |
|||
"com.unity.modules.jsonserialize": "1.0.0" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.test-framework.performance": { |
|||
"version": "1.3.3-preview", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.test-framework": "1.1.0", |
|||
"com.unity.modules.jsonserialize": "1.0.0" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.testtools.codecoverage": { |
|||
"version": "0.2.2-preview", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.test-framework": "1.0.16" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.textmeshpro": { |
|||
"version": "2.0.1", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.ugui": "1.0.0" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.ugui": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.ui": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.visualeffectgraph": { |
|||
"version": "7.3.1", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.shadergraph": "7.3.1" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"nuget.castle-core": { |
|||
"version": "1.0.1", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"nuget.mono-cecil": { |
|||
"version": "0.1.6-preview", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"nuget.moq": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"nuget.castle-core": "1.0.1" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.modules.ai": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.androidjni": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.animation": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.assetbundle": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.audio": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.cloth": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.physics": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.director": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.audio": "1.0.0", |
|||
"com.unity.modules.animation": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.imageconversion": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.imgui": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.jsonserialize": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.particlesystem": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.physics": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.physics2d": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.screencapture": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.imageconversion": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.subsystems": { |
|||
"version": "1.0.0", |
|||
"depth": 1, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.jsonserialize": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.terrain": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.terrainphysics": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.physics": "1.0.0", |
|||
"com.unity.modules.terrain": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.tilemap": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.physics2d": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.ui": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.uielements": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.imgui": "1.0.0", |
|||
"com.unity.modules.jsonserialize": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.umbra": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.unityanalytics": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.unitywebrequest": "1.0.0", |
|||
"com.unity.modules.jsonserialize": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.unitywebrequest": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.unitywebrequestassetbundle": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.assetbundle": "1.0.0", |
|||
"com.unity.modules.unitywebrequest": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.unitywebrequestaudio": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.unitywebrequest": "1.0.0", |
|||
"com.unity.modules.audio": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.unitywebrequesttexture": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.unitywebrequest": "1.0.0", |
|||
"com.unity.modules.imageconversion": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.unitywebrequestwww": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.unitywebrequest": "1.0.0", |
|||
"com.unity.modules.unitywebrequestassetbundle": "1.0.0", |
|||
"com.unity.modules.unitywebrequestaudio": "1.0.0", |
|||
"com.unity.modules.audio": "1.0.0", |
|||
"com.unity.modules.assetbundle": "1.0.0", |
|||
"com.unity.modules.imageconversion": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.vehicles": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.physics": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.video": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.audio": "1.0.0", |
|||
"com.unity.modules.ui": "1.0.0", |
|||
"com.unity.modules.unitywebrequest": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.vr": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.jsonserialize": "1.0.0", |
|||
"com.unity.modules.physics": "1.0.0", |
|||
"com.unity.modules.xr": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.wind": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.xr": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.physics": "1.0.0", |
|||
"com.unity.modules.jsonserialize": "1.0.0", |
|||
"com.unity.modules.subsystems": "1.0.0" |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Property/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String></wpf:ResourceDictionary> |
|
|||
%YAML 1.1 |
|||
%TAG !u! tag:unity3d.com,2011: |
|||
--- !u!114 &11400000 |
|||
MonoBehaviour: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 0} |
|||
m_Enabled: 1 |
|||
m_EditorHideFlags: 0 |
|||
m_Script: {fileID: 0} |
|||
m_Name: IdLabelConfig |
|||
m_EditorClassIdentifier: Unity.Perception.Runtime:UnityEngine.Perception.GroundTruth:IdLabelConfig |
|||
m_LabelEntries: |
|||
- label: Box |
|||
id: 1 |
|||
- label: Cube |
|||
id: 2 |
|||
- label: Crate |
|||
id: 3 |
|||
autoAssignIds: 1 |
|||
startingLabelId: 1 |
|
|||
fileFormatVersion: 2 |
|||
guid: cedcacfb1d9beb34fbbb231166c472fe |
|||
NativeFormatImporter: |
|||
externalObjects: {} |
|||
mainObjectFileID: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: a9ac6d4ef2846ce4cbb891bbf2650223 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
%YAML 1.1 |
|||
%TAG !u! tag:unity3d.com,2011: |
|||
--- !u!114 &11400000 |
|||
MonoBehaviour: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 0} |
|||
m_Enabled: 1 |
|||
m_EditorHideFlags: 0 |
|||
m_Script: {fileID: 11500000, guid: a9d0176327854820ab53adc46cbec7c1, type: 3} |
|||
m_Name: SemanticSegmentationLabelingConfiguration |
|||
m_EditorClassIdentifier: |
|||
m_LabelEntries: |
|||
- label: Box |
|||
color: {r: 1, g: 0, b: 0, a: 1} |
|||
- label: Cube |
|||
color: {r: 0, g: 1, b: 0.14507627, a: 1} |
|||
- label: Crate |
|||
color: {r: 0, g: 0, b: 1, a: 1} |
|
|||
fileFormatVersion: 2 |
|||
guid: c140c5aa05dd09e4fadaa26de31b1f39 |
|||
NativeFormatImporter: |
|||
externalObjects: {} |
|||
mainObjectFileID: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
{ |
|||
"dependencies": { |
|||
"com.unity.burst": { |
|||
"version": "1.3.0-preview.5", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.mathematics": "1.1.0" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.collab-proxy": { |
|||
"version": "1.2.16", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.collections": { |
|||
"version": "0.7.0-preview.2", |
|||
"depth": 3, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.test-framework.performance": "1.3.3-preview", |
|||
"com.unity.burst": "1.3.0-preview.5" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.entities": { |
|||
"version": "0.8.0-preview.8", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.burst": "1.3.0-preview.5", |
|||
"com.unity.properties": "0.10.4-preview", |
|||
"com.unity.mathematics": "1.1.0", |
|||
"com.unity.serialization": "0.6.4-preview", |
|||
"com.unity.test-framework.performance": "1.3.3-preview", |
|||
"nuget.mono-cecil": "0.1.5-preview", |
|||
"com.unity.jobs": "0.2.7-preview.11", |
|||
"com.unity.scriptablebuildpipeline": "1.6.4-preview", |
|||
"com.unity.platforms": "0.2.1-preview.4" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.ext.nunit": { |
|||
"version": "1.0.0", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.ide.rider": { |
|||
"version": "1.1.4", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.test-framework": "1.1.1" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.ide.vscode": { |
|||
"version": "1.2.1", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.jobs": { |
|||
"version": "0.2.7-preview.11", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.collections": "0.7.0-preview.2", |
|||
"com.unity.mathematics": "1.1.0" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.mathematics": { |
|||
"version": "1.1.0", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.nuget.newtonsoft-json": { |
|||
"version": "1.1.2", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.package-validation-suite": { |
|||
"version": "0.9.1-preview", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"nuget.mono-cecil": "0.1.6-preview" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.perception": { |
|||
"version": "file:../../../com.unity.perception", |
|||
"depth": 0, |
|||
"source": "local", |
|||
"dependencies": { |
|||
"com.unity.nuget.newtonsoft-json": "1.1.2", |
|||
"com.unity.render-pipelines.core": "7.1.6", |
|||
"com.unity.entities": "0.8.0-preview.8", |
|||
"com.unity.simulation.capture": "0.0.10-preview.6", |
|||
"com.unity.simulation.core": "0.0.10-preview.8" |
|||
} |
|||
}, |
|||
"com.unity.platforms": { |
|||
"version": "0.2.1-preview.4", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.nuget.newtonsoft-json": "1.1.2", |
|||
"com.unity.properties": "0.10.4-preview", |
|||
"com.unity.searcher": "4.0.9", |
|||
"com.unity.serialization": "0.6.4-preview" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.properties": { |
|||
"version": "0.10.4-preview", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.collections": "0.1.1-preview", |
|||
"com.unity.test-framework.performance": "1.0.9-preview" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.render-pipelines.core": { |
|||
"version": "7.3.1", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.ugui": "1.0.0" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.render-pipelines.universal": { |
|||
"version": "7.3.1", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.render-pipelines.core": "7.3.1", |
|||
"com.unity.shadergraph": "7.3.1" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.scriptablebuildpipeline": { |
|||
"version": "1.6.4-preview", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.searcher": { |
|||
"version": "4.0.9", |
|||
"depth": 3, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.serialization": { |
|||
"version": "0.6.4-preview", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.burst": "1.1.2", |
|||
"com.unity.collections": "0.1.1-preview", |
|||
"com.unity.jobs": "0.1.1-preview", |
|||
"com.unity.mathematics": "1.1.0", |
|||
"com.unity.properties": "0.10.4-preview", |
|||
"com.unity.test-framework.performance": "1.0.9-preview" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.shadergraph": { |
|||
"version": "7.3.1", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.render-pipelines.core": "7.3.1" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.simulation.capture": { |
|||
"version": "0.0.10-preview.6", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.simulation.core": "0.0.10-preview.8" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.simulation.core": { |
|||
"version": "0.0.10-preview.8", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.test-framework": { |
|||
"version": "1.1.14", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.ext.nunit": "1.0.0", |
|||
"com.unity.modules.imgui": "1.0.0", |
|||
"com.unity.modules.jsonserialize": "1.0.0" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.test-framework.performance": { |
|||
"version": "1.3.3-preview", |
|||
"depth": 2, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.test-framework": "1.1.0", |
|||
"com.unity.modules.jsonserialize": "1.0.0" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.textmeshpro": { |
|||
"version": "2.0.1", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"com.unity.ugui": "1.0.0" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.timeline": { |
|||
"version": "1.2.12", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.ugui": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.ui": "1.0.0" |
|||
} |
|||
}, |
|||
"nuget.castle-core": { |
|||
"version": "1.0.1", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"nuget.mono-cecil": { |
|||
"version": "0.1.6-preview", |
|||
"depth": 1, |
|||
"source": "registry", |
|||
"dependencies": {}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"nuget.moq": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "registry", |
|||
"dependencies": { |
|||
"nuget.castle-core": "1.0.1" |
|||
}, |
|||
"url": "https://packages.unity.com" |
|||
}, |
|||
"com.unity.modules.ai": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.androidjni": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.animation": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.assetbundle": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.audio": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.cloth": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.physics": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.director": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.audio": "1.0.0", |
|||
"com.unity.modules.animation": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.imageconversion": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.imgui": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.jsonserialize": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.particlesystem": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.physics": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.physics2d": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.screencapture": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.imageconversion": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.subsystems": { |
|||
"version": "1.0.0", |
|||
"depth": 1, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.jsonserialize": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.terrain": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.terrainphysics": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.physics": "1.0.0", |
|||
"com.unity.modules.terrain": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.tilemap": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.physics2d": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.ui": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.uielements": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.imgui": "1.0.0", |
|||
"com.unity.modules.jsonserialize": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.umbra": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.unityanalytics": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.unitywebrequest": "1.0.0", |
|||
"com.unity.modules.jsonserialize": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.unitywebrequest": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.unitywebrequestassetbundle": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.assetbundle": "1.0.0", |
|||
"com.unity.modules.unitywebrequest": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.unitywebrequestaudio": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.unitywebrequest": "1.0.0", |
|||
"com.unity.modules.audio": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.unitywebrequesttexture": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.unitywebrequest": "1.0.0", |
|||
"com.unity.modules.imageconversion": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.unitywebrequestwww": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.unitywebrequest": "1.0.0", |
|||
"com.unity.modules.unitywebrequestassetbundle": "1.0.0", |
|||
"com.unity.modules.unitywebrequestaudio": "1.0.0", |
|||
"com.unity.modules.audio": "1.0.0", |
|||
"com.unity.modules.assetbundle": "1.0.0", |
|||
"com.unity.modules.imageconversion": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.vehicles": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.physics": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.video": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.audio": "1.0.0", |
|||
"com.unity.modules.ui": "1.0.0", |
|||
"com.unity.modules.unitywebrequest": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.vr": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.jsonserialize": "1.0.0", |
|||
"com.unity.modules.physics": "1.0.0", |
|||
"com.unity.modules.xr": "1.0.0" |
|||
} |
|||
}, |
|||
"com.unity.modules.wind": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": {} |
|||
}, |
|||
"com.unity.modules.xr": { |
|||
"version": "1.0.0", |
|||
"depth": 0, |
|||
"source": "builtin", |
|||
"dependencies": { |
|||
"com.unity.modules.physics": "1.0.0", |
|||
"com.unity.modules.jsonserialize": "1.0.0", |
|||
"com.unity.modules.subsystems": "1.0.0" |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Property/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String></wpf:ResourceDictionary> |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Reflection; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
|
|||
namespace UnityEditor.Perception.GroundTruth { |
|||
/// <summary>
|
|||
/// Base class for all inspector drawers for <see cref="CameraLabeler"/> types. To override the inspector for a
|
|||
/// CameraLabeler, derive from this class and decorate the class with a <see cref="CameraLabelerDrawerAttribute"/>
|
|||
/// </summary>
|
|||
[CameraLabelerDrawer(typeof(CameraLabeler))] |
|||
public class CameraLabelerDrawer |
|||
{ |
|||
SerializedProperty m_Enabled; |
|||
|
|||
bool m_IsInitialized; |
|||
List<SerializedProperty> m_LabelerUserProperties = new List<SerializedProperty>(); |
|||
|
|||
/// <summary>
|
|||
/// The cameraLabeler instance
|
|||
/// </summary>
|
|||
public CameraLabeler cameraLabeler { get; internal set; } |
|||
|
|||
/// <summary>
|
|||
/// The cameraLabeler instance
|
|||
/// </summary>
|
|||
public SerializedProperty cameraLabelerProperty { get; private set; } |
|||
|
|||
void FetchProperties() |
|||
{ |
|||
m_Enabled = cameraLabelerProperty.FindPropertyRelative(nameof(cameraLabeler.enabled)); |
|||
} |
|||
|
|||
void LoadUserProperties() |
|||
{ |
|||
foreach (var field in cameraLabeler.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) |
|||
{ |
|||
var serializeField = field.GetCustomAttribute<SerializeField>(); |
|||
var hideInInspector = field.GetCustomAttribute<HideInInspector>(); |
|||
var nonSerialized = field.GetCustomAttribute<NonSerializedAttribute>(); |
|||
|
|||
if (nonSerialized != null || hideInInspector != null) |
|||
continue; |
|||
|
|||
if (!field.IsPublic && serializeField == null) |
|||
continue; |
|||
|
|||
if (field.Name == nameof(cameraLabeler.enabled)) |
|||
continue; |
|||
|
|||
var prop = cameraLabelerProperty.FindPropertyRelative(field.Name); |
|||
if (prop != null) |
|||
m_LabelerUserProperties.Add(prop); |
|||
} |
|||
} |
|||
|
|||
void EnsureInitialized(SerializedProperty property) |
|||
{ |
|||
if (m_IsInitialized) |
|||
return; |
|||
|
|||
cameraLabelerProperty = property; |
|||
FetchProperties(); |
|||
Initialize(); |
|||
LoadUserProperties(); |
|||
m_IsInitialized = true; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Use this function to initialize the local SerializedProperty you will use in your labeler.
|
|||
/// </summary>
|
|||
protected virtual void Initialize() { } |
|||
|
|||
internal void OnGUI(Rect rect, SerializedProperty property) |
|||
{ |
|||
rect.height = EditorGUIUtility.singleLineHeight; |
|||
EditorGUI.BeginChangeCheck(); |
|||
|
|||
EnsureInitialized(property); |
|||
|
|||
DoHeaderGUI(ref rect); |
|||
|
|||
EditorGUI.BeginDisabledGroup(!m_Enabled.boolValue); |
|||
{ |
|||
DoLabelerGUI(rect); |
|||
} |
|||
EditorGUI.EndDisabledGroup(); |
|||
|
|||
if (EditorGUI.EndChangeCheck()) |
|||
property.serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Implement this function to draw your custom GUI.
|
|||
/// </summary>
|
|||
/// <param name="rect">space available for you to draw the UI</param>
|
|||
protected virtual void DoLabelerGUI(Rect rect) |
|||
{ |
|||
foreach (var prop in m_LabelerUserProperties) |
|||
{ |
|||
EditorGUI.PropertyField(rect, prop); |
|||
rect.y += Styles.defaultLineSpace; |
|||
} |
|||
} |
|||
|
|||
void DoHeaderGUI(ref Rect rect) |
|||
{ |
|||
var enabledSize = EditorStyles.boldLabel.CalcSize(Styles.enabled) + new Vector2(Styles.reorderableListHandleIndentWidth, 0); |
|||
var headerRect = new Rect(rect.x, |
|||
rect.y + EditorGUIUtility.standardVerticalSpacing, |
|||
rect.width - enabledSize.x, |
|||
EditorGUIUtility.singleLineHeight); |
|||
rect.y += Styles.defaultLineSpace; |
|||
var enabledRect = headerRect; |
|||
enabledRect.x = rect.xMax - enabledSize.x; |
|||
enabledRect.width = enabledSize.x; |
|||
|
|||
EditorGUI.LabelField(headerRect, $"{cameraLabeler.GetType().Name}", EditorStyles.boldLabel); |
|||
EditorGUIUtility.labelWidth = enabledRect.width - 14; |
|||
m_Enabled.boolValue = EditorGUI.Toggle(enabledRect, Styles.enabled, m_Enabled.boolValue); |
|||
EditorGUIUtility.labelWidth = 0; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Implement this functions if you implement <see cref="DoLabelerGUI"/>. The result of this function must match the number of lines displayed in your custom GUI.
|
|||
/// Note that this height can be dynamic.
|
|||
/// </summary>
|
|||
/// <returns>The height in pixels of tour camera labeler GUI</returns>
|
|||
protected virtual float GetHeight() |
|||
{ |
|||
var height = 0f; |
|||
|
|||
foreach (var prop in m_LabelerUserProperties) |
|||
{ |
|||
height += EditorGUI.GetPropertyHeight(prop); |
|||
height += EditorGUIUtility.standardVerticalSpacing; |
|||
} |
|||
|
|||
return height; |
|||
} |
|||
|
|||
internal float GetElementHeight(SerializedProperty property) |
|||
{ |
|||
EnsureInitialized(property); |
|||
return Styles.defaultLineSpace + GetHeight(); |
|||
} |
|||
|
|||
class Styles |
|||
{ |
|||
public static float defaultLineSpace = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; |
|||
public static float reorderableListHandleIndentWidth = 12; |
|||
public static GUIContent enabled = new GUIContent("Enabled", "Enable or Disable the camera labeler"); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: a9aa79de1f2f402aa15ef42f82c3d334 |
|||
timeCreated: 1593613195 |
|
|||
using System; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
|
|||
namespace UnityEditor.Perception.GroundTruth { |
|||
/// <summary>
|
|||
/// Attribute for <see cref="CameraLabelerDrawer"/> types which specifies the <see cref="CameraLabeler"/> type
|
|||
/// whose inspector should be drawn using the decorated type.
|
|||
/// </summary>
|
|||
[AttributeUsage(AttributeTargets.Class)] |
|||
public class CameraLabelerDrawerAttribute : Attribute |
|||
{ |
|||
internal Type targetLabelerType; |
|||
|
|||
/// <summary>
|
|||
/// Creates a new CameraLabelerDrawerAttribute specifying the <see cref="CameraLabeler"/> type to be drawn
|
|||
/// </summary>
|
|||
/// <param name="targetLabelerType">The type whose inspector should be drawn by the decorated type</param>
|
|||
public CameraLabelerDrawerAttribute(Type targetLabelerType) |
|||
{ |
|||
this.targetLabelerType = targetLabelerType; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b7dfd54d7de84ca6a06e36f0e09de906 |
|||
timeCreated: 1593613460 |
|
|||
using System; |
|||
using Unity.Mathematics; |
|||
using UnityEditorInternal; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
|
|||
namespace UnityEditor.Perception.GroundTruth |
|||
{ |
|||
[CustomEditor(typeof(IdLabelConfig))] |
|||
class IdLabelConfigEditor : Editor |
|||
{ |
|||
ReorderableList m_LabelsList; |
|||
const float k_Margin = 5f; |
|||
|
|||
public void OnEnable() |
|||
{ |
|||
m_LabelsList = new ReorderableList(this.serializedObject, this.serializedObject.FindProperty(IdLabelConfig.labelEntriesFieldName), true, false, true, true); |
|||
m_LabelsList.elementHeight = EditorGUIUtility.singleLineHeight * 2 + k_Margin; |
|||
m_LabelsList.drawElementCallback = DrawElement; |
|||
m_LabelsList.onAddCallback += OnAdd; |
|||
m_LabelsList.onRemoveCallback += OnRemove; |
|||
m_LabelsList.onReorderCallbackWithDetails += OnReorder; |
|||
} |
|||
|
|||
void OnReorder(ReorderableList list, int oldIndex, int newIndex) |
|||
{ |
|||
if (!autoAssign) |
|||
return; |
|||
|
|||
AutoAssignIds(); |
|||
} |
|||
|
|||
void OnRemove(ReorderableList list) |
|||
{ |
|||
if (list.index != -1) |
|||
list.serializedProperty.DeleteArrayElementAtIndex(list.index); |
|||
|
|||
if (autoAssign) |
|||
AutoAssignIds(); |
|||
|
|||
this.serializedObject.ApplyModifiedProperties(); |
|||
EditorUtility.SetDirty(target); |
|||
} |
|||
|
|||
void OnAdd(ReorderableList list) |
|||
{ |
|||
int maxLabel = Int32.MinValue; |
|||
if (list.serializedProperty.arraySize == 0) |
|||
maxLabel = -1; |
|||
|
|||
for (int i = 0; i < list.serializedProperty.arraySize; i++) |
|||
{ |
|||
var item = list.serializedProperty.GetArrayElementAtIndex(i); |
|||
maxLabel = math.max(maxLabel, item.FindPropertyRelative(nameof(IdLabelEntry.id)).intValue); |
|||
} |
|||
var index = list.serializedProperty.arraySize; |
|||
list.serializedProperty.InsertArrayElementAtIndex(index); |
|||
var element = list.serializedProperty.GetArrayElementAtIndex(index); |
|||
var idProperty = element.FindPropertyRelative(nameof(IdLabelEntry.id)); |
|||
idProperty.intValue = maxLabel + 1; |
|||
var labelProperty = element.FindPropertyRelative(nameof(IdLabelEntry.label)); |
|||
labelProperty.stringValue = ""; |
|||
|
|||
if (autoAssign) |
|||
AutoAssignIds(); |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
EditorUtility.SetDirty(target); |
|||
} |
|||
|
|||
void DrawElement(Rect rect, int index, bool isactive, bool isfocused) |
|||
{ |
|||
var element = m_LabelsList.serializedProperty.GetArrayElementAtIndex(index); |
|||
var idProperty = element.FindPropertyRelative(nameof(IdLabelEntry.id)); |
|||
var labelProperty = element.FindPropertyRelative(nameof(IdLabelEntry.label)); |
|||
using (var change = new EditorGUI.ChangeCheckScope()) |
|||
{ |
|||
var contentRect = new Rect(rect.position, new Vector2(rect.width, EditorGUIUtility.singleLineHeight)); |
|||
using (new EditorGUI.DisabledScope(autoAssign)) |
|||
{ |
|||
var newLabel = EditorGUI.IntField(contentRect, nameof(IdLabelEntry.id), idProperty.intValue); |
|||
if (change.changed) |
|||
{ |
|||
idProperty.intValue = newLabel; |
|||
if (autoAssign) |
|||
AutoAssignIds(); |
|||
} |
|||
} |
|||
} |
|||
using (var change = new EditorGUI.ChangeCheckScope()) |
|||
{ |
|||
var contentRect = new Rect(rect.position + new Vector2(0, EditorGUIUtility.singleLineHeight), new Vector2(rect.width, EditorGUIUtility.singleLineHeight)); |
|||
var newLabel = EditorGUI.TextField(contentRect, nameof(IdLabelEntry.label), labelProperty.stringValue); |
|||
if (change.changed) |
|||
{ |
|||
labelProperty.stringValue = newLabel; |
|||
} |
|||
} |
|||
} |
|||
|
|||
bool autoAssign => serializedObject.FindProperty(nameof(IdLabelConfig.autoAssignIds)).boolValue; |
|||
|
|||
public override void OnInspectorGUI() |
|||
{ |
|||
serializedObject.Update(); |
|||
var autoAssignIdsProperty = serializedObject.FindProperty(nameof(IdLabelConfig.autoAssignIds)); |
|||
using (var change = new EditorGUI.ChangeCheckScope()) |
|||
{ |
|||
EditorGUILayout.PropertyField(autoAssignIdsProperty, new GUIContent("Auto Assign IDs")); |
|||
if (change.changed && autoAssignIdsProperty.boolValue) |
|||
AutoAssignIds(); |
|||
} |
|||
|
|||
if (autoAssignIdsProperty.boolValue) |
|||
{ |
|||
using (var change = new EditorGUI.ChangeCheckScope()) |
|||
{ |
|||
var startingLabelIdProperty = serializedObject.FindProperty(nameof(IdLabelConfig.startingLabelId)); |
|||
EditorGUILayout.PropertyField(startingLabelIdProperty, new GUIContent("Starting Label ID")); |
|||
if (change.changed) |
|||
AutoAssignIds(); |
|||
} |
|||
} |
|||
|
|||
m_LabelsList.DoLayoutList(); |
|||
this.serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
|
|||
void AutoAssignIds() |
|||
{ |
|||
var serializedProperty = serializedObject.FindProperty(IdLabelConfig.labelEntriesFieldName); |
|||
var size = serializedProperty.arraySize; |
|||
if (size == 0) |
|||
return; |
|||
|
|||
var startingLabelId = (StartingLabelId)serializedObject.FindProperty(nameof(IdLabelConfig.startingLabelId)).enumValueIndex; |
|||
|
|||
var nextId = startingLabelId == StartingLabelId.One ? 1 : 0; |
|||
for (int i = 0; i < size; i++) |
|||
{ |
|||
serializedProperty.GetArrayElementAtIndex(i).FindPropertyRelative(nameof(IdLabelEntry.id)).intValue = nextId; |
|||
nextId++; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEditorInternal; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
|
|||
namespace UnityEditor.Perception.GroundTruth |
|||
{ |
|||
[CustomEditor(typeof(PerceptionCamera))] |
|||
sealed class PerceptionCameraEditor : Editor |
|||
{ |
|||
Dictionary<SerializedProperty, CameraLabelerDrawer> m_CameraLabelerDrawers = new Dictionary<SerializedProperty, CameraLabelerDrawer>(); |
|||
ReorderableList m_LabelersList; |
|||
|
|||
SerializedProperty labelersProperty => this.serializedObject.FindProperty("m_Labelers"); |
|||
|
|||
PerceptionCamera perceptionCamera => ((PerceptionCamera)this.target); |
|||
|
|||
public void OnEnable() |
|||
{ |
|||
m_LabelersList = new ReorderableList(this.serializedObject, labelersProperty, true, false, true, true); |
|||
m_LabelersList.drawHeaderCallback = (rect) => |
|||
{ |
|||
EditorGUI.LabelField(rect, "Camera Labelers", EditorStyles.largeLabel); |
|||
}; |
|||
m_LabelersList.elementHeightCallback = GetElementHeight; |
|||
m_LabelersList.drawElementCallback = DrawElement; |
|||
m_LabelersList.onAddCallback += OnAdd; |
|||
m_LabelersList.onRemoveCallback += OnRemove; |
|||
} |
|||
|
|||
float GetElementHeight(int index) |
|||
{ |
|||
var serializedProperty = labelersProperty; |
|||
var element = serializedProperty.GetArrayElementAtIndex(index); |
|||
var editor = GetCameraLabelerDrawer(element, index); |
|||
return editor.GetElementHeight(element); |
|||
} |
|||
|
|||
void DrawElement(Rect rect, int index, bool isactive, bool isfocused) |
|||
{ |
|||
var element = labelersProperty.GetArrayElementAtIndex(index); |
|||
var editor = GetCameraLabelerDrawer(element, index); |
|||
editor.OnGUI(rect, element); |
|||
} |
|||
|
|||
void OnRemove(ReorderableList list) |
|||
{ |
|||
labelersProperty.DeleteArrayElementAtIndex(list.index); |
|||
serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
|
|||
void OnAdd(ReorderableList list) |
|||
{ |
|||
Undo.RegisterCompleteObjectUndo(target, "Remove camera labeler"); |
|||
var labelers = labelersProperty; |
|||
|
|||
var dropdownOptions = TypeCache.GetTypesDerivedFrom<CameraLabeler>(); |
|||
var menu = new GenericMenu(); |
|||
foreach (var option in dropdownOptions) |
|||
{ |
|||
var localOption = option; |
|||
menu.AddItem(new GUIContent(option.Name), |
|||
false, |
|||
() => AddLabeler(labelers, localOption)); |
|||
} |
|||
|
|||
menu.ShowAsContext(); |
|||
} |
|||
|
|||
void AddLabeler(SerializedProperty labelers, Type labelerType) |
|||
{ |
|||
var labeler = (CameraLabeler)Activator.CreateInstance(labelerType); |
|||
labeler.enabled = true; |
|||
perceptionCamera.AddLabeler(labeler); |
|||
// var insertIndex = labelers.arraySize;
|
|||
// labelers.InsertArrayElementAtIndex(insertIndex);
|
|||
// serializedObject.ApplyModifiedProperties();
|
|||
// var element = labelers.GetArrayElementAtIndex(insertIndex);
|
|||
// element.managedReferenceValue = labeler;
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
|
|||
public override void OnInspectorGUI() |
|||
{ |
|||
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(perceptionCamera.description))); |
|||
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(perceptionCamera.period))); |
|||
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(perceptionCamera.startTime))); |
|||
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(perceptionCamera.captureRgbImages))); |
|||
|
|||
//EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(PerceptionCamera.labelers)));
|
|||
m_LabelersList.DoLayoutList(); |
|||
|
|||
if (EditorSettings.asyncShaderCompilation) |
|||
{ |
|||
EditorGUILayout.HelpBox("Asynchronous shader compilation may result in invalid data in beginning frames. This can be disabled in Project Settings -> Edtior -> Asynchronous Shader Compilation", MessageType.Warning); |
|||
} |
|||
} |
|||
|
|||
CameraLabelerDrawer GetCameraLabelerDrawer(SerializedProperty element, int listIndex) |
|||
{ |
|||
CameraLabelerDrawer drawer; |
|||
|
|||
if (m_CameraLabelerDrawers.TryGetValue(element, out drawer)) |
|||
return drawer; |
|||
|
|||
var labeler = perceptionCamera.labelers[listIndex]; |
|||
|
|||
foreach (var drawerType in TypeCache.GetTypesWithAttribute(typeof(CameraLabelerDrawerAttribute))) |
|||
{ |
|||
var attr = (CameraLabelerDrawerAttribute)drawerType.GetCustomAttributes(typeof(CameraLabelerDrawerAttribute), true)[0]; |
|||
if (attr.targetLabelerType == labeler.GetType()) |
|||
{ |
|||
drawer = (CameraLabelerDrawer)Activator.CreateInstance(drawerType); |
|||
drawer.cameraLabeler = labeler; |
|||
break; |
|||
} |
|||
|
|||
if (attr.targetLabelerType.IsAssignableFrom(labeler.GetType())) |
|||
{ |
|||
drawer = (CameraLabelerDrawer)Activator.CreateInstance(drawerType); |
|||
drawer.cameraLabeler = labeler; |
|||
} |
|||
} |
|||
|
|||
m_CameraLabelerDrawers[element] = drawer; |
|||
|
|||
return drawer; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: d6936a1fe4b946a8b72f33ac7c4906e4 |
|||
timeCreated: 1589372488 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEditorInternal; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
using Random = UnityEngine.Random; |
|||
|
|||
namespace UnityEditor.Perception.GroundTruth |
|||
{ |
|||
[CustomEditor(typeof(SemanticSegmentationLabelConfig))] |
|||
class SemanticSegmentationLabelConfigEditor : Editor |
|||
{ |
|||
ReorderableList m_LabelsList; |
|||
const float k_Margin = 5f; |
|||
|
|||
static List<Color> s_StandardColors = new List<Color>() |
|||
{ |
|||
Color.blue, |
|||
Color.green, |
|||
Color.red, |
|||
Color.white, |
|||
Color.yellow, |
|||
Color.gray |
|||
}; |
|||
|
|||
public void OnEnable() |
|||
{ |
|||
m_LabelsList = new ReorderableList(this.serializedObject, this.serializedObject.FindProperty(IdLabelConfig.labelEntriesFieldName), true, false, true, true); |
|||
m_LabelsList.elementHeight = EditorGUIUtility.singleLineHeight * 2 + k_Margin; |
|||
m_LabelsList.drawElementCallback = DrawElement; |
|||
m_LabelsList.onAddCallback += OnAdd; |
|||
} |
|||
|
|||
void OnAdd(ReorderableList list) |
|||
{ |
|||
var standardColorList = new List<Color>(s_StandardColors); |
|||
for (int i = 0; i < list.serializedProperty.arraySize; i++) |
|||
{ |
|||
var item = list.serializedProperty.GetArrayElementAtIndex(i); |
|||
standardColorList.Remove(item.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.color)).colorValue); |
|||
} |
|||
var index = list.serializedProperty.arraySize; |
|||
list.serializedProperty.InsertArrayElementAtIndex(index); |
|||
var element = list.serializedProperty.GetArrayElementAtIndex(index); |
|||
var labelProperty = element.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.label)); |
|||
labelProperty.stringValue = ""; |
|||
var colorProperty = element.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.color)); |
|||
if (standardColorList.Any()) |
|||
colorProperty.colorValue = standardColorList.First(); |
|||
else |
|||
colorProperty.colorValue = Random.ColorHSV(0, 1, .5f, 1, 1, 1); |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
EditorUtility.SetDirty(target); |
|||
} |
|||
|
|||
void DrawElement(Rect rect, int index, bool isactive, bool isfocused) |
|||
{ |
|||
var element = m_LabelsList.serializedProperty.GetArrayElementAtIndex(index); |
|||
var colorProperty = element.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.color)); |
|||
var labelProperty = element.FindPropertyRelative(nameof(SemanticSegmentationLabelEntry.label)); |
|||
using (var change = new EditorGUI.ChangeCheckScope()) |
|||
{ |
|||
var contentRect = new Rect(rect.position, new Vector2(rect.width, EditorGUIUtility.singleLineHeight)); |
|||
var newLabel = EditorGUI.TextField(contentRect, nameof(SemanticSegmentationLabelEntry.label), labelProperty.stringValue); |
|||
if (change.changed) |
|||
{ |
|||
labelProperty.stringValue = newLabel; |
|||
} |
|||
} |
|||
using (var change = new EditorGUI.ChangeCheckScope()) |
|||
{ |
|||
var contentRect = new Rect(rect.position + new Vector2(0, EditorGUIUtility.singleLineHeight), new Vector2(rect.width, EditorGUIUtility.singleLineHeight)); |
|||
var newLabel = EditorGUI.ColorField(contentRect, nameof(SemanticSegmentationLabelEntry.color), colorProperty.colorValue); |
|||
if (change.changed) |
|||
{ |
|||
colorProperty.colorValue = newLabel; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public override void OnInspectorGUI() |
|||
{ |
|||
serializedObject.Update(); |
|||
|
|||
m_LabelsList.DoLayoutList(); |
|||
this.serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e8cb4fead5b34d41884c1c9a77308c72 |
|||
timeCreated: 1593454492 |
|
|||
fileFormatVersion: 2 |
|||
guid: 021a5e99d6664a188c5c78599587a08c |
|||
timeCreated: 1589374593 |
|
|||
using System; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
using System.Linq; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth { |
|||
/// <summary>
|
|||
/// An entry for <see cref="IdLabelConfig"/> mapping a label to an integer id.
|
|||
/// </summary>
|
|||
[Serializable] |
|||
public struct IdLabelEntry : ILabelEntry |
|||
{ |
|||
string ILabelEntry.label => this.label; |
|||
/// <summary>
|
|||
/// The label string to associate with the id.
|
|||
/// </summary>
|
|||
public string label; |
|||
/// <summary>
|
|||
/// The id to associate with the label.
|
|||
/// </summary>
|
|||
public int id; |
|||
} |
|||
/// <summary>
|
|||
/// A definition for how a <see cref="Labeling"/> should be resolved to a single label and id for ground truth generation.
|
|||
/// </summary>
|
|||
[CreateAssetMenu(fileName = "IdLabelConfig", menuName = "Perception/ID Label Config", order = 1)] |
|||
public sealed class IdLabelConfig : LabelConfig<IdLabelEntry> |
|||
{ |
|||
/// <summary>
|
|||
/// Whether the inspector will auto-assign ids based on the id of the first element.
|
|||
/// </summary>
|
|||
public bool autoAssignIds = true; |
|||
|
|||
/// <summary>
|
|||
/// Whether the inspector will start label ids at zero or one when <see cref="autoAssignIds"/> is enabled.
|
|||
/// </summary>
|
|||
public StartingLabelId startingLabelId = StartingLabelId.One; |
|||
|
|||
LabelEntryMatchCache m_LabelEntryMatchCache; |
|||
|
|||
/// <summary>
|
|||
/// Attempts to find the label id for the given instance id.
|
|||
/// </summary>
|
|||
/// <param name="instanceId">The instanceId of the object for which the labelId should be found</param>
|
|||
/// <param name="labelEntry">The LabelEntry associated with the object. default if not found</param>
|
|||
/// <returns>True if a labelId is found for the given instanceId.</returns>
|
|||
public bool TryGetLabelEntryFromInstanceId(uint instanceId, out IdLabelEntry labelEntry) |
|||
{ |
|||
return TryGetLabelEntryFromInstanceId(instanceId, out labelEntry, out var _); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Attempts to find the label id for the given instance id.
|
|||
/// </summary>
|
|||
/// <param name="instanceId">The instanceId of the object for which the labelId should be found</param>
|
|||
/// <param name="labelEntry">The LabelEntry associated with the object. default if not found</param>
|
|||
/// <param name="index">The index of the found LabelEntry in <see cref="LabelConfig{T}.labelEntries"/>. -1 if not found</param>
|
|||
/// <returns>True if a labelId is found for the given instanceId.</returns>
|
|||
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); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
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 |
|||
{ |
|||
/// <summary>
|
|||
/// The label id prepared for reporting in the annotation
|
|||
/// </summary>
|
|||
[UsedImplicitly] |
|||
public int label_id; |
|||
/// <summary>
|
|||
/// The label name prepared for reporting in the annotation
|
|||
/// </summary>
|
|||
[UsedImplicitly] |
|||
public string label_name; |
|||
} |
|||
|
|||
internal LabelEntrySpec[] GetAnnotationSpecification() |
|||
{ |
|||
return labelEntries.Select((l) => new LabelEntrySpec() |
|||
{ |
|||
label_id = l.id, |
|||
label_name = l.label, |
|||
}).ToArray(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2f09f279848e42cea259348b13bce4c5 |
|||
timeCreated: 1593552475 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine.Serialization; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth |
|||
{ |
|||
/// <summary>
|
|||
/// Required interface for entries in a <see cref="LabelConfig{T}"/>. Exposes the string label which is the "key"
|
|||
/// for the entry.
|
|||
/// </summary>
|
|||
public interface ILabelEntry |
|||
{ |
|||
/// <summary>
|
|||
/// The label to use as the key for the entry. This label will be matched with the labels in the GameObject's
|
|||
/// <see cref="Labeling"/> component.
|
|||
/// </summary>
|
|||
string label { get; } |
|||
} |
|||
/// <summary>
|
|||
/// A definition for how a <see cref="Labeling"/> should be resolved to a single label and id for ground truth generation.
|
|||
/// </summary>
|
|||
/// <typeparam name="T"> The entry type. Must derive from <see cref="ILabelEntry"/> </typeparam>
|
|||
public class LabelConfig<T> : ScriptableObject where T : ILabelEntry |
|||
{ |
|||
/// <summary>
|
|||
/// The name of the serialized field for label entries.
|
|||
/// </summary>
|
|||
public const string labelEntriesFieldName = nameof(m_LabelEntries); |
|||
|
|||
[FormerlySerializedAs("LabelEntries")] |
|||
[FormerlySerializedAs("LabelingConfigurations")] |
|||
[SerializeField] |
|||
List<T> m_LabelEntries = new List<T>(); |
|||
|
|||
/// <summary>
|
|||
/// A sequence of <see cref="ILabelEntry"/> which defines the labels relevant for this configuration and their values.
|
|||
/// </summary>
|
|||
public IReadOnlyList<T> labelEntries => m_LabelEntries; |
|||
|
|||
/// <summary>
|
|||
/// Attempts to find the matching index in <see cref="m_LabelEntries"/> for the given <see cref="Labeling"/>.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// The matching index is the first class name in the given Labeling which matches an entry in <see cref="m_LabelEntries"/>.
|
|||
/// </remarks>
|
|||
/// <param name="labeling">The <see cref="Labeling"/> to match </param>
|
|||
/// <param name="labelEntry">When this method returns, contains the matching <see cref="ILabelEntry"/>, or <code>default</code> if no match was found.</param>
|
|||
/// <returns>Returns true if a match was found. False if not.</returns>
|
|||
public bool TryGetMatchingConfigurationEntry(Labeling labeling, out T labelEntry) |
|||
{ |
|||
return TryGetMatchingConfigurationEntry(labeling, out labelEntry, out int _); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initialize the list of LabelEntries on this LabelingConfiguration. Should only be called immediately after instantiation.
|
|||
/// </summary>
|
|||
/// <param name="newLabelEntries">The LabelEntry values to associate with this LabelingConfiguration</param>
|
|||
/// <exception cref="InvalidOperationException">Thrown once the LabelConfig has been used at runtime.
|
|||
/// The specific timing of this depends on the LabelConfig implementation.</exception>
|
|||
public void Init(IEnumerable<T> newLabelEntries) |
|||
{ |
|||
m_LabelEntries = new List<T>(newLabelEntries); |
|||
OnInit(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Called when the labelEntries list is assigned using <see cref="Init"/>
|
|||
/// </summary>
|
|||
protected virtual void OnInit() |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Attempts to find the matching index in <see cref="m_LabelEntries"/> for the given <see cref="Labeling"/>.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// The matching index is the first class name in the given Labeling which matches an entry in <see cref="m_LabelEntries"/>.
|
|||
/// </remarks>
|
|||
/// <param name="labeling">The <see cref="Labeling"/> to match </param>
|
|||
/// <param name="labelEntry">When this method returns, contains the matching <see cref="ILabelEntry"/>, or <code>default</code> if no match was found.</param>
|
|||
/// <param name="labelEntryIndex">When this method returns, contains the index of the matching <see cref="ILabelEntry"/>, or <code>-1</code> if no match was found.</param>
|
|||
/// <returns>Returns true if a match was found. False if not.</returns>
|
|||
public bool TryGetMatchingConfigurationEntry(Labeling labeling, out T labelEntry, out int labelEntryIndex) |
|||
{ |
|||
foreach (var labelingClass in labeling.labels) |
|||
{ |
|||
for (var i = 0; i < m_LabelEntries.Count; i++) |
|||
{ |
|||
var entry = m_LabelEntries[i]; |
|||
if (string.Equals(entry.label, labelingClass)) |
|||
{ |
|||
labelEntry = m_LabelEntries[i]; |
|||
labelEntryIndex = i; |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
labelEntryIndex = -1; |
|||
labelEntry = default; |
|||
return false; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: ef6f93cc88964359a505ccc75835fd5a |
|||
timeCreated: 1589581072 |
|
|||
using System; |
|||
using Unity.Collections; |
|||
using Unity.Entities; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth |
|||
{ |
|||
/// <summary>
|
|||
/// Cache of instance id -> label entry index for a LabelConfig. This is not well optimized and is the source of
|
|||
/// a known memory leak for apps that create new instances frequently
|
|||
/// </summary>
|
|||
class LabelEntryMatchCache : IGroundTruthGenerator, IDisposable |
|||
{ |
|||
// The initial size of the cache. Large enough to avoid resizing small lists multiple times
|
|||
const int k_StartingObjectCount = 1 << 8; |
|||
NativeList<ushort> m_InstanceIdToLabelEntryIndexLookup; |
|||
IdLabelConfig m_IdLabelConfig; |
|||
|
|||
public LabelEntryMatchCache(IdLabelConfig idLabelConfig) |
|||
{ |
|||
m_IdLabelConfig = idLabelConfig; |
|||
m_InstanceIdToLabelEntryIndexLookup = new NativeList<ushort>(k_StartingObjectCount, Allocator.Persistent); |
|||
World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<GroundTruthLabelSetupSystem>().Activate(this); |
|||
} |
|||
|
|||
public bool TryGetLabelEntryFromInstanceId(uint instanceId, out IdLabelEntry labelEntry, out int index) |
|||
{ |
|||
labelEntry = default; |
|||
index = -1; |
|||
if (m_InstanceIdToLabelEntryIndexLookup.Length <= instanceId) |
|||
return false; |
|||
|
|||
index = m_InstanceIdToLabelEntryIndexLookup[(int)instanceId]; |
|||
labelEntry = m_IdLabelConfig.labelEntries[index]; |
|||
return true; |
|||
} |
|||
|
|||
void IGroundTruthGenerator.SetupMaterialProperties(MaterialPropertyBlock mpb, Renderer renderer, Labeling labeling, uint instanceId) |
|||
{ |
|||
if (m_IdLabelConfig.TryGetMatchingConfigurationEntry(labeling, out _, out var index)) |
|||
{ |
|||
if (m_InstanceIdToLabelEntryIndexLookup.Length <= instanceId) |
|||
{ |
|||
m_InstanceIdToLabelEntryIndexLookup.Resize((int)instanceId + 1, NativeArrayOptions.ClearMemory); |
|||
} |
|||
m_InstanceIdToLabelEntryIndexLookup[(int)instanceId] = (ushort)index; |
|||
} |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
World.DefaultGameObjectInjectionWorld?.GetExistingSystem<GroundTruthLabelSetupSystem>()?.Deactivate(this); |
|||
m_InstanceIdToLabelEntryIndexLookup.Dispose(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e736a5078e0a44d69bdc643b3157f670 |
|||
timeCreated: 1593182152 |
|
|||
using System; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth { |
|||
/// <summary>
|
|||
/// A definition for how a <see cref="Labeling"/> should be resolved to a single label and id for ground truth generation.
|
|||
/// </summary>
|
|||
[CreateAssetMenu(fileName = "SemanticSegmentationLabelgConfig", menuName = "Perception/Semantic Segmentation Label Config", order = 1)] |
|||
public class SemanticSegmentationLabelConfig : LabelConfig<SemanticSegmentationLabelEntry> |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// LabelEntry for <see cref="SemanticSegmentationLabelConfig"/>. Maps a label to a color.
|
|||
/// </summary>
|
|||
[Serializable] |
|||
public struct SemanticSegmentationLabelEntry : ILabelEntry |
|||
{ |
|||
string ILabelEntry.label => this.label; |
|||
/// <summary>
|
|||
/// The label this entry should match.
|
|||
/// </summary>
|
|||
public string label; |
|||
/// <summary>
|
|||
/// The color to be drawn in the semantic segmentation image
|
|||
/// </summary>
|
|||
public Color color; |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: a9d0176327854820ab53adc46cbec7c1 |
|||
timeCreated: 1593444493 |
|
|||
using System; |
|||
using Unity.Collections; |
|||
using UnityEngine; |
|||
using UnityEngine.Experimental.Rendering; |
|||
#if HDRP_PRESENT
|
|||
using UnityEngine.Rendering.HighDefinition; |
|||
#endif
|
|||
#if URP_PRESENT
|
|||
|
|||
#endif
|
|||
|
|||
namespace UnityEngine.Perception.GroundTruth |
|||
{ |
|||
partial class PerceptionCamera |
|||
{ |
|||
/// <summary>
|
|||
/// Invoked when instance segmentation images are read back from the graphics system. The first parameter is the
|
|||
/// Time.frameCount at which the objects were rendered. May be invoked many frames after the objects were rendered.
|
|||
/// </summary>
|
|||
public event Action<int, NativeArray<uint>, RenderTexture> InstanceSegmentationImageReadback; |
|||
|
|||
/// <summary>
|
|||
/// Invoked when RenderedObjectInfos are calculated. The first parameter is the Time.frameCount at which the
|
|||
/// objects were rendered. This may be called many frames after the objects were rendered.
|
|||
/// </summary>
|
|||
public event Action<int, NativeArray<RenderedObjectInfo>> RenderedObjectInfosCalculated; |
|||
|
|||
RenderedObjectInfoGenerator m_RenderedObjectInfoGenerator; |
|||
RenderTexture m_InstanceSegmentationTexture; |
|||
RenderTextureReader<uint> m_InstanceSegmentationReader; |
|||
|
|||
void SetupInstanceSegmentation() |
|||
{ |
|||
var myCamera = GetComponent<Camera>(); |
|||
var width = myCamera.pixelWidth; |
|||
var height = myCamera.pixelHeight; |
|||
m_InstanceSegmentationTexture = new RenderTexture(new RenderTextureDescriptor(width, height, GraphicsFormat.R8G8B8A8_UNorm, 8)); |
|||
m_InstanceSegmentationTexture.name = "InstanceSegmentation"; |
|||
|
|||
m_RenderedObjectInfoGenerator = new RenderedObjectInfoGenerator(); |
|||
|
|||
#if HDRP_PRESENT
|
|||
var customPassVolume = this.GetComponent<CustomPassVolume>() ?? gameObject.AddComponent<CustomPassVolume>(); |
|||
customPassVolume.injectionPoint = CustomPassInjectionPoint.BeforeRendering; |
|||
customPassVolume.isGlobal = true; |
|||
var instanceSegmentationPass = new InstanceSegmentationPass() |
|||
{ |
|||
name = "Instance segmentation pass", |
|||
targetCamera = GetComponent<Camera>(), |
|||
targetTexture = m_InstanceSegmentationTexture |
|||
}; |
|||
instanceSegmentationPass.EnsureInit(); |
|||
customPassVolume.customPasses.Add(instanceSegmentationPass); |
|||
#endif
|
|||
#if URP_PRESENT
|
|||
AddScriptableRenderPass(new InstanceSegmentationUrpPass(myCamera, m_InstanceSegmentationTexture)); |
|||
#endif
|
|||
|
|||
m_InstanceSegmentationReader = new RenderTextureReader<uint>(m_InstanceSegmentationTexture, myCamera, (frameCount, data, tex) => |
|||
{ |
|||
InstanceSegmentationImageReadback?.Invoke(frameCount, data, tex); |
|||
if (RenderedObjectInfosCalculated != null) |
|||
{ |
|||
m_RenderedObjectInfoGenerator.Compute(data, tex.width, BoundingBoxOrigin.TopLeft, out var renderedObjectInfos, Allocator.Temp); |
|||
RenderedObjectInfosCalculated?.Invoke(frameCount, renderedObjectInfos); |
|||
renderedObjectInfos.Dispose(); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
void CleanUpInstanceSegmentation() |
|||
{ |
|||
if (m_InstanceSegmentationTexture != null) |
|||
m_InstanceSegmentationTexture.Release(); |
|||
|
|||
m_InstanceSegmentationTexture = null; |
|||
|
|||
m_InstanceSegmentationReader?.WaitForAllImages(); |
|||
m_InstanceSegmentationReader?.Dispose(); |
|||
m_InstanceSegmentationReader = null; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: ee9eab40cf054cd6ad5da120c84881d7 |
|||
timeCreated: 1593126137 |
|
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using NUnit.Framework; |
|||
using Unity.Collections; |
|||
#if UNITY_EDITOR
|
|||
#endif
|
|||
using UnityEngine; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
using UnityEngine.TestTools; |
|||
using Object = UnityEngine.Object; |
|||
#if HDRP_PRESENT
|
|||
using UnityEngine.Experimental.Rendering; |
|||
using UnityEngine.Rendering.HighDefinition; |
|||
#endif
|
|||
|
|||
namespace GroundTruthTests |
|||
{ |
|||
//Graphics issues with OpenGL Linux Editor. https://jira.unity3d.com/browse/AISV-422
|
|||
[UnityPlatform(exclude = new[] {RuntimePlatform.LinuxEditor, RuntimePlatform.LinuxPlayer})] |
|||
[TestFixture] |
|||
class ObjectCountLabelerTests : GroundTruthTestBase |
|||
{ |
|||
[Test] |
|||
public void NullLabelingConfiguration_ProducesInvalidOperationException() |
|||
{ |
|||
// ReSharper disable once ObjectCreationAsStatement
|
|||
Assert.Throws<ArgumentNullException>(() => new ObjectCountLabeler(null)); |
|||
} |
|||
[UnityTest] |
|||
public IEnumerator ProducesCorrectValuesWithChangingObjects() |
|||
{ |
|||
var label = "label"; |
|||
var labelingConfiguration = ScriptableObject.CreateInstance<IdLabelConfig>(); |
|||
|
|||
labelingConfiguration.Init(new List<IdLabelEntry> |
|||
{ |
|||
new IdLabelEntry |
|||
{ |
|||
id = 1, |
|||
label = label |
|||
} |
|||
}); |
|||
|
|||
var receivedResults = new List<(uint[] counts, IdLabelEntry[] labels, int frameCount)>(); |
|||
|
|||
var cameraObject = SetupCamera(labelingConfiguration, (frameCount, counts, labels) => |
|||
{ |
|||
receivedResults.Add((counts.ToArray(), labels.ToArray(), frameCount)); |
|||
}); |
|||
AddTestObjectForCleanup(cameraObject); |
|||
|
|||
//TestHelper.LoadAndStartRenderDocCapture(out EditorWindow gameView);
|
|||
var startFrameCount = Time.frameCount; |
|||
var expectedFramesAndCounts = new Dictionary<int, int>() |
|||
{ |
|||
{Time.frameCount , 0}, |
|||
{startFrameCount + 1, 1}, |
|||
{startFrameCount + 2, 1}, |
|||
{startFrameCount + 3, 2}, |
|||
{startFrameCount + 4, 1}, |
|||
{startFrameCount + 5, 1}, |
|||
}; |
|||
|
|||
yield return null; |
|||
//Put a plane in front of the camera
|
|||
var planeObject = TestHelper.CreateLabeledPlane(.1f, label); |
|||
yield return null; |
|||
Object.DestroyImmediate(planeObject); |
|||
planeObject = TestHelper.CreateLabeledPlane(.1f, label); |
|||
yield return null; |
|||
var planeObject2 = TestHelper.CreateLabeledPlane(.1f, label); |
|||
planeObject2.transform.Translate(.5f, 0, 0); |
|||
|
|||
yield return null; |
|||
Object.DestroyImmediate(planeObject); |
|||
yield return null; |
|||
yield return null; |
|||
|
|||
Object.DestroyImmediate(planeObject2); |
|||
//destroy the object to force all pending segmented image readbacks to finish and events to be fired.
|
|||
DestroyTestObject(cameraObject); |
|||
|
|||
//RenderDoc.EndCaptureRenderDoc(gameView);
|
|||
|
|||
foreach (var result in receivedResults) |
|||
{ |
|||
Assert.AreEqual(1, result.counts.Length); |
|||
Assert.AreEqual(1, result.labels.Length); |
|||
Assert.Contains(result.frameCount, expectedFramesAndCounts.Keys, "Received event with unexpected frameCount."); |
|||
|
|||
var expectedCount = expectedFramesAndCounts[result.frameCount]; |
|||
|
|||
var errorString = $"Wrong count in frame {result.frameCount - startFrameCount}. {string.Join(", ", receivedResults.Select(r => $"count: {r.counts[0]}"))}"; |
|||
Assert.AreEqual(expectedCount, result.counts[0], errorString); |
|||
|
|||
expectedFramesAndCounts.Remove(result.frameCount); |
|||
} |
|||
|
|||
CollectionAssert.IsEmpty(expectedFramesAndCounts); |
|||
} |
|||
|
|||
static GameObject SetupCamera(IdLabelConfig idLabelConfig, |
|||
Action<int, NativeSlice<uint>, IReadOnlyList<IdLabelEntry>> onClassCountsReceived) |
|||
{ |
|||
var cameraObject = new GameObject(); |
|||
cameraObject.SetActive(false); |
|||
var camera = cameraObject.AddComponent<Camera>(); |
|||
camera.orthographic = true; |
|||
camera.orthographicSize = 1; |
|||
|
|||
var perceptionCamera = cameraObject.AddComponent<PerceptionCamera>(); |
|||
perceptionCamera.captureRgbImages = false; |
|||
var classCountLabeler = new ObjectCountLabeler(idLabelConfig); |
|||
if (onClassCountsReceived != null) |
|||
classCountLabeler.ObjectCountsComputed += onClassCountsReceived; |
|||
|
|||
perceptionCamera.AddLabeler(classCountLabeler); |
|||
cameraObject.SetActive(true); |
|||
|
|||
return cameraObject; |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using NUnit.Framework; |
|||
using Unity.Collections; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
using UnityEngine.TestTools; |
|||
|
|||
namespace GroundTruthTests |
|||
{ |
|||
[TestFixture] |
|||
public class RenderedObjectInfoTests : GroundTruthTestBase |
|||
{ |
|||
public class ProducesCorrectObjectInfoData |
|||
{ |
|||
public RenderedObjectInfo[] renderedObjectInfosExpected; |
|||
public uint[] data; |
|||
public BoundingBoxOrigin boundingBoxOrigin; |
|||
public int stride; |
|||
public string name; |
|||
public ProducesCorrectObjectInfoData(uint[] data, RenderedObjectInfo[] renderedObjectInfosExpected, int stride, BoundingBoxOrigin boundingBoxOrigin, string name) |
|||
{ |
|||
this.data = data; |
|||
this.renderedObjectInfosExpected = renderedObjectInfosExpected; |
|||
this.stride = stride; |
|||
this.name = name; |
|||
this.boundingBoxOrigin = boundingBoxOrigin; |
|||
} |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return name; |
|||
} |
|||
} |
|||
public static IEnumerable ProducesCorrectBoundingBoxesTestCases() |
|||
{ |
|||
yield return new ProducesCorrectObjectInfoData( |
|||
new uint[] |
|||
{ |
|||
1, 1, |
|||
1, 1 |
|||
}, new[] |
|||
{ |
|||
new RenderedObjectInfo() |
|||
{ |
|||
boundingBox = new Rect(0, 0, 2, 2), |
|||
instanceId = 1, |
|||
pixelCount = 4 |
|||
} |
|||
}, |
|||
2, |
|||
BoundingBoxOrigin.BottomLeft, |
|||
"SimpleBox"); |
|||
yield return new ProducesCorrectObjectInfoData( |
|||
new uint[] |
|||
{ |
|||
1, 0, 2, |
|||
1, 0, 0 |
|||
}, new[] |
|||
{ |
|||
new RenderedObjectInfo() |
|||
{ |
|||
boundingBox = new Rect(0, 0, 1, 2), |
|||
instanceId = 1, |
|||
pixelCount = 2 |
|||
}, |
|||
new RenderedObjectInfo() |
|||
{ |
|||
boundingBox = new Rect(2, 0, 1, 1), |
|||
instanceId = 2, |
|||
pixelCount = 1 |
|||
} |
|||
}, |
|||
3, |
|||
BoundingBoxOrigin.BottomLeft, |
|||
"WithGaps"); |
|||
yield return new ProducesCorrectObjectInfoData( |
|||
new uint[] |
|||
{ |
|||
1, 2, 1, |
|||
1, 2, 1 |
|||
}, new[] |
|||
{ |
|||
new RenderedObjectInfo() |
|||
{ |
|||
boundingBox = new Rect(0, 0, 3, 2), |
|||
instanceId = 1, |
|||
pixelCount = 4 |
|||
}, |
|||
new RenderedObjectInfo() |
|||
{ |
|||
boundingBox = new Rect(1, 0, 1, 2), |
|||
instanceId = 2, |
|||
pixelCount = 2 |
|||
} |
|||
}, |
|||
3, |
|||
BoundingBoxOrigin.BottomLeft, |
|||
"Interleaved"); |
|||
yield return new ProducesCorrectObjectInfoData( |
|||
new uint[] |
|||
{ |
|||
0, 0, |
|||
0, 0, |
|||
0, 1 |
|||
}, new[] |
|||
{ |
|||
new RenderedObjectInfo() |
|||
{ |
|||
boundingBox = new Rect(1, 0, 1, 1), |
|||
instanceId = 1, |
|||
pixelCount = 1 |
|||
}, |
|||
}, |
|||
2, |
|||
BoundingBoxOrigin.TopLeft, |
|||
"TopLeft"); |
|||
} |
|||
|
|||
[UnityTest] |
|||
public IEnumerator ProducesCorrectBoundingBoxes([ValueSource(nameof(ProducesCorrectBoundingBoxesTestCases))] ProducesCorrectObjectInfoData producesCorrectObjectInfoData) |
|||
{ |
|||
var label = "label"; |
|||
var label2 = "label2"; |
|||
var labelingConfiguration = ScriptableObject.CreateInstance<IdLabelConfig>(); |
|||
|
|||
labelingConfiguration.Init(new List<IdLabelEntry> |
|||
{ |
|||
new IdLabelEntry |
|||
{ |
|||
id = 1, |
|||
label = label |
|||
}, |
|||
new IdLabelEntry |
|||
{ |
|||
id = 2, |
|||
label = label2 |
|||
} |
|||
}); |
|||
|
|||
var renderedObjectInfoGenerator = new RenderedObjectInfoGenerator(); |
|||
|
|||
//Put a plane in front of the camera
|
|||
AddTestObjectForCleanup(TestHelper.CreateLabeledPlane(.1f, label)); |
|||
AddTestObjectForCleanup(TestHelper.CreateLabeledPlane(.1f, label2)); |
|||
yield return null; |
|||
|
|||
var dataNativeArray = new NativeArray<uint>(producesCorrectObjectInfoData.data, Allocator.Persistent); |
|||
|
|||
renderedObjectInfoGenerator.Compute(dataNativeArray, producesCorrectObjectInfoData.stride, producesCorrectObjectInfoData.boundingBoxOrigin, out var boundingBoxes, Allocator.Temp); |
|||
|
|||
CollectionAssert.AreEqual(producesCorrectObjectInfoData.renderedObjectInfosExpected, boundingBoxes.ToArray()); |
|||
|
|||
dataNativeArray.Dispose(); |
|||
boundingBoxes.Dispose(); |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
using Unity.Collections; |
|||
using Unity.Profiling; |
|||
using UnityEngine.Serialization; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth |
|||
{ |
|||
/// <summary>
|
|||
/// Produces 2d bounding box annotations for all visible objects each frame.
|
|||
/// </summary>
|
|||
[Serializable] |
|||
public sealed class BoundingBox2DLabeler : CameraLabeler |
|||
{ |
|||
[SuppressMessage("ReSharper", "InconsistentNaming")] |
|||
[SuppressMessage("ReSharper", "NotAccessedField.Local")] |
|||
struct BoundingBoxValue |
|||
{ |
|||
public int label_id; |
|||
public string label_name; |
|||
public uint instance_id; |
|||
public float x; |
|||
public float y; |
|||
public float width; |
|||
public float height; |
|||
} |
|||
|
|||
static ProfilerMarker s_BoundingBoxCallback = new ProfilerMarker("OnBoundingBoxesReceived"); |
|||
|
|||
/// <summary>
|
|||
/// The GUID id to associate with the annotations produced by this labeler.
|
|||
/// </summary>
|
|||
public string annotationId = "F9F22E05-443F-4602-A422-EBE4EA9B55CB"; |
|||
/// <summary>
|
|||
/// The <see cref="IdLabelConfig"/> which associates objects with labels.
|
|||
/// </summary>
|
|||
[FormerlySerializedAs("labelingConfiguration")] |
|||
public IdLabelConfig idLabelConfig; |
|||
|
|||
Dictionary<int, AsyncAnnotation> m_AsyncAnnotations; |
|||
AnnotationDefinition m_BoundingBoxAnnotationDefinition; |
|||
BoundingBoxValue[] m_BoundingBoxValues; |
|||
|
|||
/// <summary>
|
|||
/// Creates a new BoundingBox2DLabeler. Be sure to assign <see cref="idLabelConfig"/> before adding to a <see cref="PerceptionCamera"/>.
|
|||
/// </summary>
|
|||
public BoundingBox2DLabeler() |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a new BoundingBox2DLabeler with the given <see cref="IdLabelConfig"/>.
|
|||
/// </summary>
|
|||
/// <param name="labelConfig">The label config for resolving the label for each object.</param>
|
|||
public BoundingBox2DLabeler(IdLabelConfig labelConfig) |
|||
{ |
|||
this.idLabelConfig = labelConfig; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void Setup() |
|||
{ |
|||
if (idLabelConfig == null) |
|||
throw new InvalidOperationException("BoundingBox2DLabeler's idLabelConfig field must be assigned"); |
|||
|
|||
m_AsyncAnnotations = new Dictionary<int, AsyncAnnotation>(); |
|||
|
|||
m_BoundingBoxAnnotationDefinition = DatasetCapture.RegisterAnnotationDefinition("bounding box", idLabelConfig.GetAnnotationSpecification(), |
|||
"Bounding box for each labeled object visible to the sensor", id: new Guid(annotationId)); |
|||
|
|||
perceptionCamera.RenderedObjectInfosCalculated += OnRenderedObjectInfosCalculated; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void OnBeginRendering() |
|||
{ |
|||
m_AsyncAnnotations[Time.frameCount] = perceptionCamera.SensorHandle.ReportAnnotationAsync(m_BoundingBoxAnnotationDefinition); |
|||
} |
|||
|
|||
void OnRenderedObjectInfosCalculated(int frameCount, NativeArray<RenderedObjectInfo> renderedObjectInfos) |
|||
{ |
|||
if (!m_AsyncAnnotations.TryGetValue(frameCount, out var asyncAnnotation)) |
|||
return; |
|||
|
|||
m_AsyncAnnotations.Remove(frameCount); |
|||
|
|||
using (s_BoundingBoxCallback.Auto()) |
|||
{ |
|||
if (m_BoundingBoxValues == null || m_BoundingBoxValues.Length != renderedObjectInfos.Length) |
|||
m_BoundingBoxValues = new BoundingBoxValue[renderedObjectInfos.Length]; |
|||
|
|||
for (var i = 0; i < renderedObjectInfos.Length; i++) |
|||
{ |
|||
var objectInfo = renderedObjectInfos[i]; |
|||
if (!idLabelConfig.TryGetLabelEntryFromInstanceId(objectInfo.instanceId, out var labelEntry)) |
|||
continue; |
|||
|
|||
m_BoundingBoxValues[i] = new BoundingBoxValue |
|||
{ |
|||
label_id = labelEntry.id, |
|||
label_name = labelEntry.label, |
|||
instance_id = objectInfo.instanceId, |
|||
x = objectInfo.boundingBox.x, |
|||
y = objectInfo.boundingBox.y, |
|||
width = objectInfo.boundingBox.width, |
|||
height = objectInfo.boundingBox.height, |
|||
}; |
|||
} |
|||
|
|||
asyncAnnotation.ReportValues(m_BoundingBoxValues); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth |
|||
{ |
|||
/// <summary>
|
|||
/// Abstract class for defining custom annotation and metric generation to be run by <see cref="PerceptionCamera"/>.
|
|||
/// Instances of CameraLabeler on <see cref="PerceptionCamera.labelers"/> will be invoked each frame the camera is
|
|||
/// set to capture data (see <see cref="SensorHandle.ShouldCaptureThisFrame"/>).
|
|||
/// </summary>
|
|||
[Serializable] |
|||
public abstract class CameraLabeler |
|||
{ |
|||
/// <summary>
|
|||
/// Whether the CameraLabeler should be set up and called each frame.
|
|||
/// </summary>
|
|||
public bool enabled = true; |
|||
|
|||
internal bool isInitialized { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// The <see cref="PerceptionCamera"/> that contains this labeler.
|
|||
/// </summary>
|
|||
protected PerceptionCamera perceptionCamera { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// The SensorHandle for the <see cref="PerceptionCamera"/> that contains this labeler. Use this to report
|
|||
/// annotations and metrics.
|
|||
/// </summary>
|
|||
protected SensorHandle sensorHandle { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// Called just before the first call to <see cref="OnUpdate"/> or <see cref="OnBeginRendering"/>. Implement this
|
|||
/// to initialize state.
|
|||
/// </summary>
|
|||
protected virtual void Setup() { } |
|||
/// <summary>
|
|||
/// Called during the Update each frame the the labeler is enabled and <see cref="SensorHandle.ShouldCaptureThisFrame"/> is true.
|
|||
/// </summary>
|
|||
protected virtual void OnUpdate() {} |
|||
/// <summary>
|
|||
/// Called just before the camera renders each frame the the labeler is enabled and <see cref="SensorHandle.ShouldCaptureThisFrame"/> is true.
|
|||
/// </summary>
|
|||
protected virtual void OnBeginRendering() {} |
|||
|
|||
/// <summary>
|
|||
/// Called when the Labeler is about to be destroyed or removed from the PerceptionCamera. Use this to clean up to state.
|
|||
/// </summary>
|
|||
protected virtual void Cleanup() {} |
|||
|
|||
internal void InternalSetup() => Setup(); |
|||
internal void InternalOnUpdate() => OnUpdate(); |
|||
internal void InternalOnBeginRendering() => OnBeginRendering(); |
|||
internal void InternalCleanup() => Cleanup(); |
|||
|
|||
internal void Init(PerceptionCamera newPerceptionCamera) |
|||
{ |
|||
try |
|||
{ |
|||
this.perceptionCamera = newPerceptionCamera; |
|||
sensorHandle = newPerceptionCamera.SensorHandle; |
|||
Setup(); |
|||
isInitialized = true; |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
this.enabled = false; |
|||
throw; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1f21ae5ed3374b7288ad9bd4ad367c59 |
|||
timeCreated: 1593188098 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
using Unity.Collections; |
|||
using Unity.Profiling; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth |
|||
{ |
|||
/// <summary>
|
|||
/// Labeler which produces object counts for each label in the associated <see cref="IdLabelConfig"/> each frame.
|
|||
/// </summary>
|
|||
[Serializable] |
|||
public sealed class ObjectCountLabeler : CameraLabeler |
|||
{ |
|||
/// <summary>
|
|||
/// The ID to use for object count annotations in the resulting dataset
|
|||
/// </summary>
|
|||
public string objectCountMetricId = "51DA3C27-369D-4929-AEA6-D01614635CE2"; |
|||
|
|||
/// <summary>
|
|||
/// The <see cref="IdLabelConfig"/> which associates objects with labels.
|
|||
/// </summary>
|
|||
public IdLabelConfig labelConfig => m_LabelConfig; |
|||
|
|||
/// <summary>
|
|||
/// Fired when the object counts are computed for a frame.
|
|||
/// </summary>
|
|||
public event Action<int, NativeSlice<uint>,IReadOnlyList<IdLabelEntry>> ObjectCountsComputed; |
|||
|
|||
[SerializeField] |
|||
IdLabelConfig m_LabelConfig; |
|||
|
|||
static ProfilerMarker s_ClassCountCallback = new ProfilerMarker("OnClassLabelsReceived"); |
|||
|
|||
ClassCountValue[] m_ClassCountValues; |
|||
|
|||
Dictionary<int, AsyncMetric> m_ObjectCountAsyncMetrics; |
|||
MetricDefinition m_ObjectCountMetricDefinition; |
|||
|
|||
/// <summary>
|
|||
/// Creates a new ObjectCountLabeler. This constructor should only be used by serialization. For creation from
|
|||
/// user code, use <see cref="ObjectCountLabeler(IdLabelConfig)"/>.
|
|||
/// </summary>
|
|||
public ObjectCountLabeler() |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a new ObjectCountLabeler with the given <see cref="IdLabelConfig"/>.
|
|||
/// </summary>
|
|||
/// <param name="labelConfig">The label config for resolving the label for each object.</param>
|
|||
public ObjectCountLabeler(IdLabelConfig labelConfig) |
|||
{ |
|||
if (labelConfig == null) |
|||
throw new ArgumentNullException(nameof(labelConfig)); |
|||
|
|||
m_LabelConfig = labelConfig; |
|||
} |
|||
|
|||
[SuppressMessage("ReSharper", "InconsistentNaming")] |
|||
[SuppressMessage("ReSharper", "NotAccessedField.Local")] |
|||
struct ClassCountValue |
|||
{ |
|||
public int label_id; |
|||
public string label_name; |
|||
public uint count; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void Setup() |
|||
{ |
|||
if (labelConfig == null) |
|||
throw new InvalidOperationException("The ObjectCountLabeler idLabelConfig field must be assigned"); |
|||
|
|||
m_ObjectCountAsyncMetrics = new Dictionary<int, AsyncMetric>(); |
|||
|
|||
perceptionCamera.RenderedObjectInfosCalculated += (frameCount, objectInfo) => |
|||
{ |
|||
NativeArray<uint> objectCounts = ComputeObjectCounts(objectInfo); |
|||
ObjectCountsComputed?.Invoke(frameCount, objectCounts, labelConfig.labelEntries); |
|||
ProduceObjectCountMetric(objectCounts, m_LabelConfig.labelEntries, frameCount); |
|||
}; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void OnBeginRendering() |
|||
{ |
|||
if (m_ObjectCountMetricDefinition.Equals(default)) |
|||
{ |
|||
m_ObjectCountMetricDefinition = DatasetCapture.RegisterMetricDefinition("object count", |
|||
m_LabelConfig.GetAnnotationSpecification(), |
|||
"Counts of objects for each label in the sensor's view", id: new Guid(objectCountMetricId)); |
|||
} |
|||
|
|||
m_ObjectCountAsyncMetrics[Time.frameCount] = perceptionCamera.SensorHandle.ReportMetricAsync(m_ObjectCountMetricDefinition); |
|||
} |
|||
|
|||
NativeArray<uint> ComputeObjectCounts(NativeArray<RenderedObjectInfo> objectInfo) |
|||
{ |
|||
var objectCounts = new NativeArray<uint>(m_LabelConfig.labelEntries.Count, Allocator.Temp); |
|||
foreach (var info in objectInfo) |
|||
{ |
|||
if (!m_LabelConfig.TryGetLabelEntryFromInstanceId(info.instanceId, out _, out var labelIndex)) |
|||
continue; |
|||
|
|||
objectCounts[labelIndex]++; |
|||
} |
|||
|
|||
return objectCounts; |
|||
} |
|||
|
|||
void ProduceObjectCountMetric(NativeSlice<uint> counts, IReadOnlyList<IdLabelEntry> entries, int frameCount) |
|||
{ |
|||
using (s_ClassCountCallback.Auto()) |
|||
{ |
|||
if (!m_ObjectCountAsyncMetrics.TryGetValue(frameCount, out var classCountAsyncMetric)) |
|||
return; |
|||
|
|||
m_ObjectCountAsyncMetrics.Remove(frameCount); |
|||
|
|||
if (m_ClassCountValues == null || m_ClassCountValues.Length != entries.Count) |
|||
m_ClassCountValues = new ClassCountValue[entries.Count]; |
|||
|
|||
for (var i = 0; i < entries.Count; i++) |
|||
{ |
|||
m_ClassCountValues[i] = new ClassCountValue() |
|||
{ |
|||
label_id = entries[i].id, |
|||
label_name = entries[i].label, |
|||
count = counts[i] |
|||
}; |
|||
} |
|||
|
|||
classCountAsyncMetric.ReportValues(m_ClassCountValues); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 715672f8c1f94106b6e84431e53c6096 |
|||
timeCreated: 1593183448 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using JetBrains.Annotations; |
|||
using Unity.Collections; |
|||
using Unity.Profiling; |
|||
using UnityEngine.Serialization; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth |
|||
{ |
|||
/// <summary>
|
|||
/// Labeler which produces label id, instance id, and visible pixel count in a single metric each frame for
|
|||
/// each object which takes up one or more pixels in the camera's frame.
|
|||
/// </summary>
|
|||
[Serializable] |
|||
public sealed class RenderedObjectInfoLabeler : CameraLabeler |
|||
{ |
|||
// ReSharper disable InconsistentNaming
|
|||
struct RenderedObjectInfoValue |
|||
{ |
|||
[UsedImplicitly] |
|||
public int label_id; |
|||
[UsedImplicitly] |
|||
public uint instance_id; |
|||
[UsedImplicitly] |
|||
public int visible_pixels; |
|||
} |
|||
// ReSharper restore InconsistentNaming
|
|||
|
|||
static ProfilerMarker s_ProduceRenderedObjectInfoMetric = new ProfilerMarker("ProduceRenderedObjectInfoMetric"); |
|||
|
|||
/// <summary>
|
|||
/// The ID to use for visible pixels metrics in the resulting dataset
|
|||
/// </summary>
|
|||
public string objectInfoMetricId = "5BA92024-B3B7-41A7-9D3F-C03A6A8DDD01"; |
|||
|
|||
/// <summary>
|
|||
/// The <see cref="IdLabelConfig"/> which associates objects with labels.
|
|||
/// </summary>
|
|||
[FormerlySerializedAs("labelingConfiguration")] |
|||
public IdLabelConfig idLabelConfig; |
|||
|
|||
RenderedObjectInfoValue[] m_VisiblePixelsValues; |
|||
Dictionary<int, AsyncMetric> m_ObjectInfoAsyncMetrics; |
|||
MetricDefinition m_RenderedObjectInfoMetricDefinition; |
|||
|
|||
/// <summary>
|
|||
/// Creates a new RenderedObjectInfoLabeler. Be sure to assign <see cref="idLabelConfig"/> before adding to a <see cref="PerceptionCamera"/>.
|
|||
/// </summary>
|
|||
public RenderedObjectInfoLabeler() |
|||
{ |
|||
} |
|||
/// <summary>
|
|||
/// Creates a new RenderedObjectInfoLabeler with an <see cref="IdLabelConfig"/>.
|
|||
/// </summary>
|
|||
/// <param name="idLabelConfig">The <see cref="IdLabelConfig"/> which associates objects with labels. </param>
|
|||
public RenderedObjectInfoLabeler(IdLabelConfig idLabelConfig) |
|||
{ |
|||
this.idLabelConfig = idLabelConfig; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void Setup() |
|||
{ |
|||
if (idLabelConfig == null) |
|||
throw new InvalidOperationException("RenderedObjectInfoLabeler's idLabelConfig field must be assigned"); |
|||
|
|||
m_ObjectInfoAsyncMetrics = new Dictionary<int, AsyncMetric>(); |
|||
|
|||
perceptionCamera.RenderedObjectInfosCalculated += (frameCount, objectInfo) => |
|||
{ |
|||
ProduceRenderedObjectInfoMetric(objectInfo, frameCount); |
|||
}; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void OnBeginRendering() |
|||
{ |
|||
if (m_RenderedObjectInfoMetricDefinition.Equals(default)) |
|||
{ |
|||
m_RenderedObjectInfoMetricDefinition = DatasetCapture.RegisterMetricDefinition( |
|||
"rendered object info", |
|||
idLabelConfig.GetAnnotationSpecification(), |
|||
"Information about each labeled object visible to the sensor", |
|||
id: new Guid(objectInfoMetricId)); |
|||
} |
|||
|
|||
m_ObjectInfoAsyncMetrics[Time.frameCount] = perceptionCamera.SensorHandle.ReportMetricAsync(m_RenderedObjectInfoMetricDefinition); |
|||
} |
|||
|
|||
void ProduceRenderedObjectInfoMetric(NativeArray<RenderedObjectInfo> renderedObjectInfos, int frameCount) |
|||
{ |
|||
using (s_ProduceRenderedObjectInfoMetric.Auto()) |
|||
{ |
|||
if (!m_ObjectInfoAsyncMetrics.TryGetValue(frameCount, out var metric)) |
|||
return; |
|||
|
|||
m_ObjectInfoAsyncMetrics.Remove(frameCount); |
|||
|
|||
if (m_VisiblePixelsValues == null || m_VisiblePixelsValues.Length != renderedObjectInfos.Length) |
|||
m_VisiblePixelsValues = new RenderedObjectInfoValue[renderedObjectInfos.Length]; |
|||
|
|||
for (var i = 0; i < renderedObjectInfos.Length; i++) |
|||
{ |
|||
var objectInfo = renderedObjectInfos[i]; |
|||
if (!TryGetLabelEntryFromInstanceId(objectInfo.instanceId, out var labelEntry)) |
|||
continue; |
|||
|
|||
m_VisiblePixelsValues[i] = new RenderedObjectInfoValue |
|||
{ |
|||
label_id = labelEntry.id, |
|||
instance_id = objectInfo.instanceId, |
|||
visible_pixels = objectInfo.pixelCount |
|||
}; |
|||
} |
|||
|
|||
metric.ReportValues(m_VisiblePixelsValues); |
|||
} |
|||
} |
|||
|
|||
bool TryGetLabelEntryFromInstanceId(uint instanceId, out IdLabelEntry labelEntry) |
|||
{ |
|||
return idLabelConfig.TryGetLabelEntryFromInstanceId(instanceId, out labelEntry); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c2fcc6ce8ec34a44ae0f1679f25b6fb4 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using JetBrains.Annotations; |
|||
using Unity.Collections; |
|||
using Unity.Simulation; |
|||
using UnityEngine.Experimental.Rendering; |
|||
using UnityEngine.Profiling; |
|||
|
|||
#if HDRP_PRESENT
|
|||
using UnityEngine.Rendering.HighDefinition; |
|||
#endif
|
|||
|
|||
namespace UnityEngine.Perception.GroundTruth |
|||
{ |
|||
/// <summary>
|
|||
/// Labeler which generates a semantic segmentation image each frame. Each object is rendered to the semantic segmentation
|
|||
/// image using the color associated with it based on the given <see cref="SemanticSegmentationLabelConfig"/>.
|
|||
/// Semantic segmentation images are saved to the dataset in PNG format.
|
|||
///
|
|||
/// Only one SemanticSegmentationLabeler can render at once across all cameras.
|
|||
/// </summary>
|
|||
[Serializable] |
|||
public sealed class SemanticSegmentationLabeler : CameraLabeler |
|||
{ |
|||
const string k_SemanticSegmentationDirectory = "SemanticSegmentation"; |
|||
const string k_SegmentationFilePrefix = "segmentation_"; |
|||
|
|||
/// <summary>
|
|||
/// The id to associate with semantic segmentation annotations in the dataset.
|
|||
/// </summary>
|
|||
[Tooltip("The id to associate with semantic segmentation annotations in the dataset.")] |
|||
public string annotationId = "12F94D8D-5425-4DEB-9B21-5E53AD957D66"; |
|||
/// <summary>
|
|||
/// The SemanticSegmentationLabelConfig which maps labels to pixel values.
|
|||
/// </summary>
|
|||
public SemanticSegmentationLabelConfig labelConfig; |
|||
|
|||
/// <summary>
|
|||
/// Event information for <see cref="SemanticSegmentationLabeler.imageReadback"/>
|
|||
/// </summary>
|
|||
public struct ImageReadbackEventArgs |
|||
{ |
|||
/// <summary>
|
|||
/// The <see cref="Time.frameCount"/> on which the image was rendered. This may be multiple frames in the past.
|
|||
/// </summary>
|
|||
public int frameCount; |
|||
/// <summary>
|
|||
/// Color pixel data.
|
|||
/// </summary>
|
|||
public NativeArray<Color32> data; |
|||
/// <summary>
|
|||
/// The source image texture.
|
|||
/// </summary>
|
|||
public RenderTexture sourceTexture; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Event which is called each frame a semantic segmentation image is read back from the GPU.
|
|||
/// </summary>
|
|||
public event Action<ImageReadbackEventArgs> imageReadback; |
|||
|
|||
[NonSerialized] |
|||
internal RenderTexture semanticSegmentationTexture; |
|||
|
|||
AnnotationDefinition m_SemanticSegmentationAnnotationDefinition; |
|||
RenderTextureReader<Color32> m_SemanticSegmentationTextureReader; |
|||
|
|||
#if HDRP_PRESENT
|
|||
SemanticSegmentationPass m_SemanticSegmentationPass; |
|||
#endif
|
|||
|
|||
Dictionary<int, AsyncAnnotation> m_AsyncAnnotations; |
|||
|
|||
/// <summary>
|
|||
/// Creates a new SemanticSegmentationLabeler. Be sure to assign <see cref="labelConfig"/> before adding to a <see cref="PerceptionCamera"/>.
|
|||
/// </summary>
|
|||
public SemanticSegmentationLabeler() { } |
|||
|
|||
/// <summary>
|
|||
/// Creates a new SemanticSegmentationLabeler with the given <see cref="SemanticSegmentationLabelConfig"/>.
|
|||
/// </summary>
|
|||
/// <param name="labelConfig">The label config associating labels with colors.</param>
|
|||
public SemanticSegmentationLabeler(SemanticSegmentationLabelConfig labelConfig) |
|||
{ |
|||
this.labelConfig = labelConfig; |
|||
} |
|||
|
|||
[SuppressMessage("ReSharper", "InconsistentNaming")] |
|||
struct SemanticSegmentationSpec |
|||
{ |
|||
[UsedImplicitly] |
|||
public string label_name; |
|||
[UsedImplicitly] |
|||
public Color pixel_value; |
|||
} |
|||
|
|||
struct AsyncSemanticSegmentationWrite |
|||
{ |
|||
public NativeArray<Color32> data; |
|||
public int width; |
|||
public int height; |
|||
public string path; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void Setup() |
|||
{ |
|||
var myCamera = perceptionCamera.GetComponent<Camera>(); |
|||
var width = myCamera.pixelWidth; |
|||
var height = myCamera.pixelHeight; |
|||
|
|||
if (labelConfig == null) |
|||
{ |
|||
throw new InvalidOperationException( |
|||
"SemanticSegmentationLabeler's LabelConfig must be assigned"); |
|||
} |
|||
|
|||
m_AsyncAnnotations = new Dictionary<int, AsyncAnnotation>(); |
|||
|
|||
semanticSegmentationTexture = new RenderTexture( |
|||
new RenderTextureDescriptor(width, height, GraphicsFormat.R8G8B8A8_UNorm, 8)); |
|||
semanticSegmentationTexture.name = "Labeling"; |
|||
|
|||
#if HDRP_PRESENT
|
|||
var gameObject = perceptionCamera.gameObject; |
|||
var customPassVolume = gameObject.GetComponent<CustomPassVolume>() ?? gameObject.AddComponent<CustomPassVolume>(); |
|||
customPassVolume.injectionPoint = CustomPassInjectionPoint.BeforeRendering; |
|||
customPassVolume.isGlobal = true; |
|||
m_SemanticSegmentationPass = new SemanticSegmentationPass(myCamera, semanticSegmentationTexture, labelConfig) |
|||
{ |
|||
name = "Labeling Pass" |
|||
}; |
|||
customPassVolume.customPasses.Add(m_SemanticSegmentationPass); |
|||
#endif
|
|||
#if URP_PRESENT
|
|||
perceptionCamera.AddScriptableRenderPass(new SemanticSegmentationUrpPass(myCamera, semanticSegmentationTexture, labelConfig)); |
|||
#endif
|
|||
|
|||
var specs = labelConfig.labelEntries.Select((l) => new SemanticSegmentationSpec() |
|||
{ |
|||
label_name = l.label, |
|||
pixel_value = l.color |
|||
}).ToArray(); |
|||
|
|||
m_SemanticSegmentationAnnotationDefinition = DatasetCapture.RegisterAnnotationDefinition( |
|||
"semantic segmentation", |
|||
specs, |
|||
"pixel-wise semantic segmentation label", |
|||
"PNG", |
|||
id: Guid.Parse(annotationId)); |
|||
|
|||
m_SemanticSegmentationTextureReader = new RenderTextureReader<Color32>(semanticSegmentationTexture, myCamera, |
|||
(frameCount, data, tex) => OnSemanticSegmentationImageRead(frameCount, data)); |
|||
} |
|||
|
|||
void OnSemanticSegmentationImageRead(int frameCount, NativeArray<Color32> data) |
|||
{ |
|||
if (!m_AsyncAnnotations.TryGetValue(frameCount, out var annotation)) |
|||
return; |
|||
|
|||
var datasetRelativePath = Path.Combine(k_SemanticSegmentationDirectory, k_SegmentationFilePrefix) + frameCount + ".png"; |
|||
var localPath = Path.Combine(Manager.Instance.GetDirectoryFor(k_SemanticSegmentationDirectory), k_SegmentationFilePrefix) + frameCount + ".png"; |
|||
|
|||
annotation.ReportFile(datasetRelativePath); |
|||
|
|||
var asyncRequest = Manager.Instance.CreateRequest<AsyncRequest<AsyncSemanticSegmentationWrite>>(); |
|||
imageReadback?.Invoke(new ImageReadbackEventArgs |
|||
{ |
|||
data = data, |
|||
frameCount = frameCount, |
|||
sourceTexture = semanticSegmentationTexture |
|||
}); |
|||
asyncRequest.data = new AsyncSemanticSegmentationWrite |
|||
{ |
|||
data = new NativeArray<Color32>(data, Allocator.TempJob), |
|||
width = semanticSegmentationTexture.width, |
|||
height = semanticSegmentationTexture.height, |
|||
path = localPath |
|||
}; |
|||
asyncRequest.Start((r) => |
|||
{ |
|||
Profiler.BeginSample("Encode"); |
|||
var pngBytes = ImageConversion.EncodeArrayToPNG(r.data.data.ToArray(), GraphicsFormat.R8G8B8A8_UNorm, (uint)r.data.width, (uint)r.data.height); |
|||
Profiler.EndSample(); |
|||
Profiler.BeginSample("WritePng"); |
|||
File.WriteAllBytes(r.data.path, pngBytes); |
|||
Manager.Instance.ConsumerFileProduced(r.data.path); |
|||
Profiler.EndSample(); |
|||
r.data.data.Dispose(); |
|||
return AsyncRequest.Result.Completed; |
|||
}); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void OnBeginRendering() |
|||
{ |
|||
m_AsyncAnnotations[Time.frameCount] = perceptionCamera.SensorHandle.ReportAnnotationAsync(m_SemanticSegmentationAnnotationDefinition); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void Cleanup() |
|||
{ |
|||
m_SemanticSegmentationTextureReader?.WaitForAllImages(); |
|||
m_SemanticSegmentationTextureReader?.Dispose(); |
|||
m_SemanticSegmentationTextureReader = null; |
|||
|
|||
if (semanticSegmentationTexture != null) |
|||
semanticSegmentationTexture.Release(); |
|||
|
|||
semanticSegmentationTexture = null; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6c08fb5eff78425db5567cf66f9cb3fc |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: be3971a848968144e8d07d9136a5bf49 |
|||
NativeFormatImporter: |
|||
externalObjects: {} |
|||
mainObjectFileID: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
%YAML 1.1 |
|||
%TAG !u! tag:unity3d.com,2011: |
|||
--- !u!114 &11400000 |
|||
MonoBehaviour: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 0} |
|||
m_Enabled: 1 |
|||
m_EditorHideFlags: 0 |
|||
m_Script: {fileID: 11500000, guid: bad10bec3eccd8e49a9d725b2c30f74c, type: 3} |
|||
m_Name: LabelingConfiguration |
|||
m_EditorClassIdentifier: |
|||
AutoAssignIds: 1 |
|||
StartingLabelId: 1 |
|||
LabelEntries: |
|||
- id: 1 |
|||
label: Box |
|||
value: 10000 |
|||
- id: 2 |
|||
label: Crate |
|||
value: 20000 |
|||
- id: 3 |
|||
label: Cube |
|||
value: 30000 |
|
|||
%YAML 1.1 |
|||
%TAG !u! tag:unity3d.com,2011: |
|||
--- !u!114 &11400000 |
|||
MonoBehaviour: |
|||
m_ObjectHideFlags: 0 |
|||
m_CorrespondingSourceObject: {fileID: 0} |
|||
m_PrefabInstance: {fileID: 0} |
|||
m_PrefabAsset: {fileID: 0} |
|||
m_GameObject: {fileID: 0} |
|||
m_Enabled: 1 |
|||
m_EditorHideFlags: 0 |
|||
m_Script: {fileID: 11500000, guid: bad10bec3eccd8e49a9d725b2c30f74c, type: 3} |
|||
m_Name: ExampleLabelingConfiguration |
|||
m_EditorClassIdentifier: |
|||
AutoAssignIds: 1 |
|||
StartingLabelId: 1 |
|||
LabelEntries: |
|||
- id: 1 |
|||
label: Box |
|||
value: 10000 |
|||
- id: 2 |
|||
label: Cube |
|||
value: 20000 |
|||
- id: 3 |
|||
label: Crate |
|||
value: 30000 |
|
|||
fileFormatVersion: 2 |
|||
guid: e74234fe725079e4aa7ecd74797ceb79 |
|||
NativeFormatImporter: |
|||
externalObjects: {} |
|||
mainObjectFileID: 0 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#if HDRP_PRESENT
|
|||
|
|||
using System; |
|||
using UnityEditor.Rendering.HighDefinition; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
|
|||
namespace UnityEditor.Perception.GroundTruth |
|||
{ |
|||
[CustomPassDrawer(typeof(ObjectCountPass))] |
|||
public class ObjectCountPassEditor : BaseCustomPassDrawer |
|||
{ |
|||
protected override void Initialize(SerializedProperty customPass) |
|||
{ |
|||
AddProperty(customPass.FindPropertyRelative(nameof(GroundTruthPass.targetCamera))); |
|||
AddProperty(customPass.FindPropertyRelative(nameof(ObjectCountPass.SegmentationTexture))); |
|||
AddProperty(customPass.FindPropertyRelative(nameof(ObjectCountPass.LabelingConfiguration))); |
|||
base.Initialize(customPass); |
|||
} |
|||
} |
|||
} |
|||
#endif
|
|
|||
using System; |
|||
using Unity.Mathematics; |
|||
using UnityEditorInternal; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
|
|||
namespace UnityEditor.Perception.GroundTruth |
|||
{ |
|||
[CustomEditor(typeof(LabelingConfiguration))] |
|||
class LabelingConfigurationEditor : Editor |
|||
{ |
|||
ReorderableList m_LabelsList; |
|||
const float k_Margin = 5f; |
|||
|
|||
public void OnEnable() |
|||
{ |
|||
m_LabelsList = new ReorderableList(this.serializedObject, this.serializedObject.FindProperty(nameof(LabelingConfiguration.LabelEntries)), true, false, true, true); |
|||
m_LabelsList.elementHeight = EditorGUIUtility.singleLineHeight * 3 + k_Margin; |
|||
m_LabelsList.drawElementCallback = DrawElement; |
|||
m_LabelsList.onAddCallback += OnAdd; |
|||
m_LabelsList.onRemoveCallback += OnRemove; |
|||
m_LabelsList.onReorderCallbackWithDetails += OnReorder; |
|||
} |
|||
|
|||
void OnReorder(ReorderableList list, int oldIndex, int newIndex) |
|||
{ |
|||
if (!autoAssign) |
|||
return; |
|||
|
|||
AutoAssignIds(); |
|||
} |
|||
|
|||
void OnRemove(ReorderableList list) |
|||
{ |
|||
if (list.index != -1) |
|||
list.serializedProperty.DeleteArrayElementAtIndex(list.index); |
|||
|
|||
if (autoAssign) |
|||
AutoAssignIds(); |
|||
|
|||
this.serializedObject.ApplyModifiedProperties(); |
|||
EditorUtility.SetDirty(target); |
|||
} |
|||
|
|||
void OnAdd(ReorderableList list) |
|||
{ |
|||
int maxLabel = Int32.MinValue; |
|||
if (list.serializedProperty.arraySize == 0) |
|||
maxLabel = -1; |
|||
|
|||
for (int i = 0; i < list.serializedProperty.arraySize; i++) |
|||
{ |
|||
var item = list.serializedProperty.GetArrayElementAtIndex(i); |
|||
maxLabel = math.max(maxLabel, item.FindPropertyRelative(nameof(LabelEntry.id)).intValue); |
|||
} |
|||
var index = list.serializedProperty.arraySize; |
|||
list.serializedProperty.InsertArrayElementAtIndex(index); |
|||
var element = list.serializedProperty.GetArrayElementAtIndex(index); |
|||
var idProperty = element.FindPropertyRelative(nameof(LabelEntry.id)); |
|||
idProperty.intValue = maxLabel + 1; |
|||
var labelProperty = element.FindPropertyRelative(nameof(LabelEntry.label)); |
|||
labelProperty.stringValue = ""; |
|||
var valueProperty = element.FindPropertyRelative(nameof(LabelEntry.value)); |
|||
valueProperty.intValue = 0; |
|||
|
|||
if (autoAssign) |
|||
AutoAssignIds(); |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
EditorUtility.SetDirty(target); |
|||
} |
|||
|
|||
void DrawElement(Rect rect, int index, bool isactive, bool isfocused) |
|||
{ |
|||
var element = m_LabelsList.serializedProperty.GetArrayElementAtIndex(index); |
|||
var idProperty = element.FindPropertyRelative(nameof(LabelEntry.id)); |
|||
var labelProperty = element.FindPropertyRelative(nameof(LabelEntry.label)); |
|||
var valueProperty = element.FindPropertyRelative(nameof(LabelEntry.value)); |
|||
using (var change = new EditorGUI.ChangeCheckScope()) |
|||
{ |
|||
var contentRect = new Rect(rect.position, new Vector2(rect.width, EditorGUIUtility.singleLineHeight)); |
|||
using (new EditorGUI.DisabledScope(autoAssign)) |
|||
{ |
|||
var newLabel = EditorGUI.IntField(contentRect, nameof(LabelEntry.id), idProperty.intValue); |
|||
if (change.changed) |
|||
{ |
|||
idProperty.intValue = newLabel; |
|||
if (autoAssign) |
|||
AutoAssignIds(); |
|||
} |
|||
} |
|||
} |
|||
using (var change = new EditorGUI.ChangeCheckScope()) |
|||
{ |
|||
var contentRect = new Rect(rect.position + new Vector2(0, EditorGUIUtility.singleLineHeight), new Vector2(rect.width, EditorGUIUtility.singleLineHeight)); |
|||
var newLabel = EditorGUI.TextField(contentRect, nameof(LabelEntry.label), labelProperty.stringValue); |
|||
if (change.changed) |
|||
{ |
|||
labelProperty.stringValue = newLabel; |
|||
} |
|||
} |
|||
|
|||
using (var change = new EditorGUI.ChangeCheckScope()) |
|||
{ |
|||
var contentRect = new Rect(rect.position + new Vector2(0, EditorGUIUtility.singleLineHeight * 2), new Vector2(rect.width, EditorGUIUtility.singleLineHeight)); |
|||
var newValue = EditorGUI.IntField(contentRect, nameof(LabelEntry.value), valueProperty.intValue); |
|||
if (change.changed) |
|||
valueProperty.intValue = newValue; |
|||
} |
|||
} |
|||
|
|||
bool autoAssign => serializedObject.FindProperty(nameof(LabelingConfiguration.AutoAssignIds)).boolValue; |
|||
|
|||
public override void OnInspectorGUI() |
|||
{ |
|||
serializedObject.Update(); |
|||
var autoAssignIdsProperty = serializedObject.FindProperty(nameof(LabelingConfiguration.AutoAssignIds)); |
|||
using (var change = new EditorGUI.ChangeCheckScope()) |
|||
{ |
|||
EditorGUILayout.PropertyField(autoAssignIdsProperty, new GUIContent("Auto Assign IDs")); |
|||
if (change.changed && autoAssignIdsProperty.boolValue) |
|||
AutoAssignIds(); |
|||
} |
|||
|
|||
if (autoAssignIdsProperty.boolValue) |
|||
{ |
|||
using (var change = new EditorGUI.ChangeCheckScope()) |
|||
{ |
|||
var startingLabelIdProperty = serializedObject.FindProperty(nameof(LabelingConfiguration.StartingLabelId)); |
|||
EditorGUILayout.PropertyField(startingLabelIdProperty, new GUIContent("Starting Label ID")); |
|||
if (change.changed) |
|||
AutoAssignIds(); |
|||
} |
|||
} |
|||
|
|||
m_LabelsList.DoLayoutList(); |
|||
this.serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
|
|||
void AutoAssignIds() |
|||
{ |
|||
var serializedProperty = serializedObject.FindProperty(nameof(LabelingConfiguration.LabelEntries)); |
|||
var size = serializedProperty.arraySize; |
|||
if (size == 0) |
|||
return; |
|||
|
|||
var startingLabelId = (StartingLabelId)serializedObject.FindProperty(nameof(LabelingConfiguration.StartingLabelId)).enumValueIndex; |
|||
|
|||
var nextId = startingLabelId == StartingLabelId.One ? 1 : 0; |
|||
for (int i = 0; i < size; i++) |
|||
{ |
|||
serializedProperty.GetArrayElementAtIndex(i).FindPropertyRelative(nameof(LabelEntry.id)).intValue = nextId; |
|||
nextId++; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using UnityEngine.Serialization; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth |
|||
{ |
|||
/// <summary>
|
|||
/// A definition for how a <see cref="Labeling"/> should be resolved to a single label and id for ground truth generation.
|
|||
/// </summary>
|
|||
[CreateAssetMenu(fileName = "LabelingConfiguration", menuName = "Perception/Labeling Configuration", order = 1)] |
|||
public class LabelingConfiguration : ScriptableObject |
|||
{ |
|||
/// <summary>
|
|||
/// Whether the inspector will auto-assign ids based on the id of the first element.
|
|||
/// </summary>
|
|||
public bool AutoAssignIds = true; |
|||
|
|||
/// <summary>
|
|||
/// Whether the inspector will start label ids at zero or one when <see cref="AutoAssignIds"/> is enabled.
|
|||
/// </summary>
|
|||
public StartingLabelId StartingLabelId = StartingLabelId.One; |
|||
|
|||
/// <summary>
|
|||
/// A sequence of <see cref="LabelEntry"/> which defines the labels relevant for this configuration and their values.
|
|||
/// </summary>
|
|||
[FormerlySerializedAs("LabelingConfigurations")] |
|||
[SerializeField] |
|||
public List<LabelEntry> LabelEntries = new List<LabelEntry>(); |
|||
|
|||
/// <summary>
|
|||
/// Attempts to find the matching index in <see cref="LabelEntries"/> for the given <see cref="Labeling"/>.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// The matching index is the first class name in the given Labeling which matches an entry in <see cref="LabelEntries"/>.
|
|||
/// </remarks>
|
|||
/// <param name="labeling">The <see cref="Labeling"/> to match </param>
|
|||
/// <param name="labelEntry">When this method returns, contains the matching <see cref="LabelEntry"/>, or <code>default</code> if no match was found.</param>
|
|||
/// <returns>Returns true if a match was found. False if not.</returns>
|
|||
public bool TryGetMatchingConfigurationEntry(Labeling labeling, out LabelEntry labelEntry) |
|||
{ |
|||
return TryGetMatchingConfigurationEntry(labeling, out labelEntry, out int _); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Attempts to find the matching index in <see cref="LabelEntries"/> for the given <see cref="Labeling"/>.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// The matching index is the first class name in the given Labeling which matches an entry in <see cref="LabelEntries"/>.
|
|||
/// </remarks>
|
|||
/// <param name="labeling">The <see cref="Labeling"/> to match </param>
|
|||
/// <param name="labelEntry">When this method returns, contains the matching <see cref="LabelEntry"/>, or <code>default</code> if no match was found.</param>
|
|||
/// <param name="labelEntryIndex">When this method returns, contains the index of the matching <see cref="LabelEntry"/>, or <code>-1</code> if no match was found.</param>
|
|||
/// <returns>Returns true if a match was found. False if not.</returns>
|
|||
public bool TryGetMatchingConfigurationEntry(Labeling labeling, out LabelEntry labelEntry, out int labelEntryIndex) |
|||
{ |
|||
foreach (var labelingClass in labeling.labels) |
|||
{ |
|||
for (var i = 0; i < LabelEntries.Count; i++) |
|||
{ |
|||
var entry = LabelEntries[i]; |
|||
if (string.Equals(entry.label, labelingClass)) |
|||
{ |
|||
labelEntry = entry; |
|||
labelEntryIndex = i; |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
labelEntryIndex = -1; |
|||
labelEntry = default; |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Structure defining a label configuration for <see cref="LabelingConfiguration"/>.
|
|||
/// </summary>
|
|||
[Serializable] |
|||
public struct LabelEntry |
|||
{ |
|||
/// <summary>
|
|||
/// The id associated with the label. Used to associate objects with labels in various forms of ground truth.
|
|||
/// </summary>
|
|||
public int id; |
|||
/// <summary>
|
|||
/// The label string
|
|||
/// </summary>
|
|||
public string label; |
|||
/// <summary>
|
|||
/// The value to use when generating semantic segmentation images.
|
|||
/// </summary>
|
|||
public int value; |
|||
|
|||
/// <summary>
|
|||
/// Creates a new LabelingConfigurationEntry with the given values.
|
|||
/// </summary>
|
|||
/// <param name="id">The id associated with the label. Used to associate objects with labels in various forms of ground truth.</param>
|
|||
/// <param name="label">The label string.</param>
|
|||
/// <param name="value">The value to use when generating semantic segmentation images.</param>
|
|||
public LabelEntry(int id, string label, int value) |
|||
{ |
|||
this.id = id; |
|||
this.label = label; |
|||
this.value = value; |
|||
} |
|||
} |
|||
} |
|
|||
#if HDRP_PRESENT
|
|||
|
|||
using Unity.Collections.LowLevel.Unsafe; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Unity.Collections; |
|||
using UnityEngine.Rendering.HighDefinition; |
|||
using UnityEngine.Rendering; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth |
|||
{ |
|||
/// <summary>
|
|||
/// CustomPass which computes object count for each label in the given LabelingConfiguration in the frame.
|
|||
/// Requires the texture produced by an InstanceSegmentationPass.
|
|||
/// </summary>
|
|||
public class ObjectCountPass : GroundTruthPass |
|||
{ |
|||
const int k_StartingObjectCount = 1 << 8; |
|||
public RenderTexture SegmentationTexture; |
|||
public LabelingConfiguration LabelingConfiguration; |
|||
|
|||
ComputeShader m_ComputeShader; |
|||
ComputeBuffer m_InstanceIdPresenceMask; |
|||
ComputeBuffer m_InstanceIdToClassId; |
|||
ComputeBuffer m_ClassCounts; |
|||
NativeList<int> m_InstanceIdToLabelIndexLookup; |
|||
HashSet<Camera> m_CamerasRendered = new HashSet<Camera>(); |
|||
bool m_IdBuffersNeedUpdating; |
|||
bool m_DidComputeLastFrame; |
|||
|
|||
public ObjectCountPass(Camera camera) : base(camera) |
|||
{ |
|||
} |
|||
|
|||
// ReSharper disable once UnusedMember.Global
|
|||
public ObjectCountPass() : base(null) |
|||
{ |
|||
} |
|||
|
|||
public override void SetupMaterialProperties(MaterialPropertyBlock mpb, Renderer meshRenderer, Labeling labeling, uint instanceId) |
|||
{ |
|||
if (!m_InstanceIdToLabelIndexLookup.IsCreated) |
|||
{ |
|||
m_InstanceIdToLabelIndexLookup = new NativeList<int>(k_StartingObjectCount, Allocator.Persistent); |
|||
} |
|||
if (LabelingConfiguration.TryGetMatchingConfigurationEntry(labeling, out LabelEntry labelEntry, out var index)) |
|||
{ |
|||
if (m_InstanceIdToLabelIndexLookup.Length <= instanceId) |
|||
{ |
|||
m_InstanceIdToLabelIndexLookup.Resize((int)instanceId + 1, NativeArrayOptions.ClearMemory); |
|||
} |
|||
m_IdBuffersNeedUpdating = true; |
|||
m_InstanceIdToLabelIndexLookup[(int)instanceId] = index + 1; |
|||
} |
|||
} |
|||
|
|||
protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd) |
|||
{ |
|||
base.Setup(renderContext, cmd); |
|||
m_ComputeShader = Resources.Load<ComputeShader>("LabeledObjectHistogram"); |
|||
|
|||
var objectCount = k_StartingObjectCount; |
|||
UpdateIdBufferSizes(objectCount); |
|||
m_ClassCounts = new ComputeBuffer(LabelingConfiguration.LabelEntries.Count + 1, UnsafeUtility.SizeOf<uint>(), ComputeBufferType.Structured); |
|||
|
|||
RenderPipelineManager.endCameraRendering += OnEndCameraRendering; |
|||
} |
|||
|
|||
void OnEndCameraRendering(ScriptableRenderContext renderContext, Camera camera) |
|||
{ |
|||
} |
|||
|
|||
void UpdateIdBufferSizes(int objectCount) |
|||
{ |
|||
var presenceMaskSizeNeeded = objectCount; |
|||
if (m_InstanceIdPresenceMask == null || presenceMaskSizeNeeded > m_InstanceIdPresenceMask.count) |
|||
{ |
|||
m_InstanceIdPresenceMask?.Release(); |
|||
m_InstanceIdPresenceMask = new ComputeBuffer(presenceMaskSizeNeeded, UnsafeUtility.SizeOf<uint>(), ComputeBufferType.Structured); |
|||
} |
|||
|
|||
if (m_InstanceIdToClassId == null || m_InstanceIdToClassId.count < objectCount) |
|||
{ |
|||
m_InstanceIdToClassId?.Release(); |
|||
m_InstanceIdToClassId = new ComputeBuffer(objectCount, UnsafeUtility.SizeOf<uint>(), ComputeBufferType.Structured); |
|||
} |
|||
} |
|||
|
|||
protected override void ExecutePass(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, CullingResults cullingResult) |
|||
{ |
|||
//If there are no objects to label, skip the pass
|
|||
if (!m_InstanceIdToLabelIndexLookup.IsCreated || m_InstanceIdToLabelIndexLookup.Length == 0) |
|||
{ |
|||
var counts = new NativeArray<uint>(LabelingConfiguration.LabelEntries.Count + 1, Allocator.Temp); |
|||
OnClassCountReadback(Time.frameCount, counts); |
|||
counts.Dispose(); |
|||
return; |
|||
} |
|||
|
|||
m_CamerasRendered.Add(hdCamera.camera); |
|||
|
|||
if (m_IdBuffersNeedUpdating) |
|||
{ |
|||
UpdateIdBufferSizes(m_InstanceIdToLabelIndexLookup.Capacity); |
|||
m_InstanceIdToClassId.SetData(m_InstanceIdToLabelIndexLookup.AsArray()); |
|||
} |
|||
|
|||
//The following section kicks off the four kernels in LabeledObjectHistogram.compute
|
|||
|
|||
//clear ClassCounts
|
|||
cmd.SetComputeBufferParam(m_ComputeShader, 1, "ClassCounts", m_ClassCounts); |
|||
cmd.DispatchCompute(m_ComputeShader, 1, m_ClassCounts.count, 1, 1); |
|||
|
|||
//clear InstanceIdPresenceMask
|
|||
cmd.SetComputeBufferParam(m_ComputeShader, 2, "InstanceIdPresenceMask", m_InstanceIdPresenceMask); |
|||
cmd.DispatchCompute(m_ComputeShader, 2, m_InstanceIdPresenceMask.count, 1, 1); |
|||
|
|||
//clear InstanceIdPresenceMask
|
|||
cmd.SetComputeTextureParam(m_ComputeShader, 0, "SegmentationTexture", SegmentationTexture); |
|||
cmd.SetComputeBufferParam(m_ComputeShader, 0, "InstanceIdPresenceMask", m_InstanceIdPresenceMask); |
|||
cmd.SetComputeIntParam(m_ComputeShader, "Width", SegmentationTexture.width); |
|||
cmd.SetComputeIntParam(m_ComputeShader, "Height", SegmentationTexture.height); |
|||
cmd.DispatchCompute(m_ComputeShader, 0, SegmentationTexture.width, SegmentationTexture.height, 1); |
|||
|
|||
//clear InstanceIdPresenceMask
|
|||
cmd.SetComputeBufferParam(m_ComputeShader, 3, "InstanceIdPresenceMask", m_InstanceIdPresenceMask); |
|||
cmd.SetComputeBufferParam(m_ComputeShader, 3, "InstanceIdToClassId", m_InstanceIdToClassId); |
|||
cmd.SetComputeBufferParam(m_ComputeShader, 3, "ClassCounts", m_ClassCounts); |
|||
cmd.DispatchCompute(m_ComputeShader, 3, m_InstanceIdToLabelIndexLookup.Length, 1, 1); |
|||
|
|||
var requestFrameCount = Time.frameCount; |
|||
cmd.RequestAsyncReadback(m_ClassCounts, request => OnClassCountReadback(requestFrameCount, request.GetData<uint>())); |
|||
} |
|||
|
|||
protected override void Cleanup() |
|||
{ |
|||
base.Cleanup(); |
|||
m_InstanceIdPresenceMask?.Dispose(); |
|||
m_InstanceIdPresenceMask = null; |
|||
m_InstanceIdToClassId?.Dispose(); |
|||
m_InstanceIdToClassId = null; |
|||
m_ClassCounts?.Dispose(); |
|||
m_ClassCounts = null; |
|||
WaitForAllRequests(); |
|||
|
|||
if (m_InstanceIdToLabelIndexLookup.IsCreated) |
|||
{ |
|||
m_InstanceIdToLabelIndexLookup.Dispose(); |
|||
m_InstanceIdToLabelIndexLookup = default; |
|||
} |
|||
} |
|||
|
|||
internal event Action<NativeSlice<uint>, IReadOnlyList<LabelEntry>, int> ClassCountsReceived; |
|||
|
|||
void OnClassCountReadback(int requestFrameCount, NativeArray<uint> counts) |
|||
{ |
|||
#if PERCEPTION_DEBUG
|
|||
StringBuilder sb = new StringBuilder(); |
|||
sb.AppendFormat("Histogram data. Frame {0}", requestFrameCount.ToString()); |
|||
for (int i = 0; i < LabelingConfiguration.LabelingConfigurations.Count; i++) |
|||
{ |
|||
sb.AppendFormat("{0}: {1}", LabelingConfiguration.LabelingConfigurations[i].label, |
|||
counts[i + 1].ToString()); |
|||
sb.AppendLine(); |
|||
} |
|||
Debug.Log(sb); |
|||
#endif
|
|||
|
|||
ClassCountsReceived?.Invoke(new NativeSlice<uint>(counts, 1), LabelingConfiguration.LabelEntries, requestFrameCount); |
|||
} |
|||
|
|||
public void WaitForAllRequests() |
|||
{ |
|||
var commandBuffer = CommandBufferPool.Get("LabelHistorgramCleanup"); |
|||
commandBuffer.WaitAllAsyncReadbackRequests(); |
|||
Graphics.ExecuteCommandBuffer(commandBuffer); |
|||
CommandBufferPool.Release(commandBuffer); |
|||
} |
|||
} |
|||
} |
|||
#endif
|
|
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using NUnit.Framework; |
|||
using Unity.Collections; |
|||
using Unity.Entities; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
using UnityEngine.TestTools; |
|||
|
|||
namespace GroundTruthTests |
|||
{ |
|||
[TestFixture] |
|||
public class BoundingBox2DTests : GroundTruthTestBase |
|||
{ |
|||
public class ProducesCorrectBoundingBoxesData |
|||
{ |
|||
public uint[] classCountsExpected; |
|||
public RenderedObjectInfo[] boundingBoxesExpected; |
|||
public uint[] data; |
|||
public BoundingBoxOrigin boundingBoxOrigin; |
|||
public int stride; |
|||
public string name; |
|||
public ProducesCorrectBoundingBoxesData(uint[] data, RenderedObjectInfo[] boundingBoxesExpected, uint[] classCountsExpected, int stride, BoundingBoxOrigin boundingBoxOrigin, string name) |
|||
{ |
|||
this.data = data; |
|||
this.boundingBoxesExpected = boundingBoxesExpected; |
|||
this.classCountsExpected = classCountsExpected; |
|||
this.stride = stride; |
|||
this.name = name; |
|||
this.boundingBoxOrigin = boundingBoxOrigin; |
|||
} |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return name; |
|||
} |
|||
} |
|||
public static IEnumerable ProducesCorrectBoundingBoxesTestCases() |
|||
{ |
|||
yield return new ProducesCorrectBoundingBoxesData( |
|||
new uint[] |
|||
{ |
|||
1, 1, |
|||
1, 1 |
|||
}, new[] |
|||
{ |
|||
new RenderedObjectInfo() |
|||
{ |
|||
boundingBox = new Rect(0, 0, 2, 2), |
|||
instanceId = 1, |
|||
labelId = 1, |
|||
pixelCount = 4 |
|||
} |
|||
}, new uint[] |
|||
{ |
|||
1, |
|||
0 |
|||
}, |
|||
2, |
|||
BoundingBoxOrigin.BottomLeft, |
|||
"SimpleBox"); |
|||
yield return new ProducesCorrectBoundingBoxesData( |
|||
new uint[] |
|||
{ |
|||
1, 0, 2, |
|||
1, 0, 0 |
|||
}, new[] |
|||
{ |
|||
new RenderedObjectInfo() |
|||
{ |
|||
boundingBox = new Rect(0, 0, 1, 2), |
|||
instanceId = 1, |
|||
labelId = 1, |
|||
pixelCount = 2 |
|||
}, |
|||
new RenderedObjectInfo() |
|||
{ |
|||
boundingBox = new Rect(2, 0, 1, 1), |
|||
instanceId = 2, |
|||
labelId = 2, |
|||
pixelCount = 1 |
|||
} |
|||
}, new uint[] |
|||
{ |
|||
1, |
|||
1 |
|||
}, |
|||
3, |
|||
BoundingBoxOrigin.BottomLeft, |
|||
"WithGaps"); |
|||
yield return new ProducesCorrectBoundingBoxesData( |
|||
new uint[] |
|||
{ |
|||
1, 2, 1, |
|||
1, 2, 1 |
|||
}, new[] |
|||
{ |
|||
new RenderedObjectInfo() |
|||
{ |
|||
boundingBox = new Rect(0, 0, 3, 2), |
|||
instanceId = 1, |
|||
labelId = 1, |
|||
pixelCount = 4 |
|||
}, |
|||
new RenderedObjectInfo() |
|||
{ |
|||
boundingBox = new Rect(1, 0, 1, 2), |
|||
instanceId = 2, |
|||
labelId = 2, |
|||
pixelCount = 2 |
|||
} |
|||
}, new uint[] |
|||
{ |
|||
1, |
|||
1 |
|||
}, |
|||
3, |
|||
BoundingBoxOrigin.BottomLeft, |
|||
"Interleaved"); |
|||
yield return new ProducesCorrectBoundingBoxesData( |
|||
new uint[] |
|||
{ |
|||
0, 0, |
|||
0, 0, |
|||
0, 1 |
|||
}, new[] |
|||
{ |
|||
new RenderedObjectInfo() |
|||
{ |
|||
boundingBox = new Rect(1, 0, 1, 1), |
|||
instanceId = 1, |
|||
labelId = 1, |
|||
pixelCount = 1 |
|||
}, |
|||
}, new uint[] |
|||
{ |
|||
1, |
|||
0 |
|||
}, |
|||
2, |
|||
BoundingBoxOrigin.TopLeft, |
|||
"TopLeft"); |
|||
} |
|||
|
|||
[UnityTest] |
|||
public IEnumerator ProducesCorrectBoundingBoxes([ValueSource(nameof(ProducesCorrectBoundingBoxesTestCases))] ProducesCorrectBoundingBoxesData producesCorrectBoundingBoxesData) |
|||
{ |
|||
var label = "label"; |
|||
var label2 = "label2"; |
|||
var labelingConfiguration = ScriptableObject.CreateInstance<LabelingConfiguration>(); |
|||
|
|||
labelingConfiguration.LabelEntries = new List<LabelEntry> |
|||
{ |
|||
new LabelEntry |
|||
{ |
|||
id = 1, |
|||
label = label, |
|||
value = 500 |
|||
}, |
|||
new LabelEntry |
|||
{ |
|||
id = 2, |
|||
label = label2, |
|||
value = 500 |
|||
} |
|||
}; |
|||
|
|||
var renderedObjectInfoGenerator = new RenderedObjectInfoGenerator(labelingConfiguration); |
|||
var groundTruthLabelSetupSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem<GroundTruthLabelSetupSystem>(); |
|||
groundTruthLabelSetupSystem.Activate(renderedObjectInfoGenerator); |
|||
|
|||
//Put a plane in front of the camera
|
|||
AddTestObjectForCleanup(TestHelper.CreateLabeledPlane(.1f, label)); |
|||
AddTestObjectForCleanup(TestHelper.CreateLabeledPlane(.1f, label2)); |
|||
yield return null; |
|||
|
|||
var dataNativeArray = new NativeArray<uint>(producesCorrectBoundingBoxesData.data, Allocator.Persistent); |
|||
|
|||
renderedObjectInfoGenerator.Compute(dataNativeArray, producesCorrectBoundingBoxesData.stride, producesCorrectBoundingBoxesData.boundingBoxOrigin, out var boundingBoxes, out var classCounts, Allocator.Temp); |
|||
|
|||
CollectionAssert.AreEqual(producesCorrectBoundingBoxesData.boundingBoxesExpected, boundingBoxes.ToArray()); |
|||
CollectionAssert.AreEqual(producesCorrectBoundingBoxesData.classCountsExpected, classCounts.ToArray()); |
|||
|
|||
dataNativeArray.Dispose(); |
|||
boundingBoxes.Dispose(); |
|||
classCounts.Dispose(); |
|||
groundTruthLabelSetupSystem.Deactivate(renderedObjectInfoGenerator); |
|||
renderedObjectInfoGenerator.Dispose(); |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using NUnit.Framework; |
|||
using Unity.Collections; |
|||
#if UNITY_EDITOR
|
|||
#endif
|
|||
using UnityEngine; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
using UnityEngine.TestTools; |
|||
using Object = UnityEngine.Object; |
|||
#if HDRP_PRESENT
|
|||
using UnityEngine.Experimental.Rendering; |
|||
using UnityEngine.Rendering.HighDefinition; |
|||
#endif
|
|||
|
|||
namespace GroundTruthTests |
|||
{ |
|||
//Graphics issues with OpenGL Linux Editor. https://jira.unity3d.com/browse/AISV-422
|
|||
[UnityPlatform(exclude = new[] {RuntimePlatform.LinuxEditor, RuntimePlatform.LinuxPlayer})] |
|||
[TestFixture] |
|||
class ObjectCountTests : GroundTruthTestBase |
|||
{ |
|||
[UnityTest] |
|||
public IEnumerator ProducesCorrectValuesWithChangingObjects() |
|||
{ |
|||
var label = "label"; |
|||
var labelingConfiguration = ScriptableObject.CreateInstance<LabelingConfiguration>(); |
|||
|
|||
labelingConfiguration.LabelEntries = new List<LabelEntry> |
|||
{ |
|||
new LabelEntry |
|||
{ |
|||
id = 1, |
|||
label = label, |
|||
value = 500 |
|||
} |
|||
}; |
|||
|
|||
var receivedResults = new List<(uint[] counts, LabelEntry[] labels, int frameCount)>(); |
|||
|
|||
var cameraObject = SetupCamera(labelingConfiguration, (counts, labels, frameCount) => |
|||
{ |
|||
receivedResults.Add((counts.ToArray(), labels.ToArray(), frameCount)); |
|||
}); |
|||
AddTestObjectForCleanup(cameraObject); |
|||
|
|||
//TestHelper.LoadAndStartRenderDocCapture(out EditorWindow gameView);
|
|||
var startFrameCount = Time.frameCount; |
|||
var expectedFramesAndCounts = new Dictionary<int, int>() |
|||
{ |
|||
{Time.frameCount , 0}, |
|||
{startFrameCount + 1, 1}, |
|||
{startFrameCount + 2, 1}, |
|||
{startFrameCount + 3, 2}, |
|||
{startFrameCount + 4, 1}, |
|||
{startFrameCount + 5, 1}, |
|||
}; |
|||
|
|||
yield return null; |
|||
//Put a plane in front of the camera
|
|||
var planeObject = TestHelper.CreateLabeledPlane(.1f, label); |
|||
yield return null; |
|||
Object.DestroyImmediate(planeObject); |
|||
planeObject = TestHelper.CreateLabeledPlane(.1f, label); |
|||
yield return null; |
|||
var planeObject2 = TestHelper.CreateLabeledPlane(.1f, label); |
|||
planeObject2.transform.Translate(.5f, 0, 0); |
|||
|
|||
yield return null; |
|||
Object.DestroyImmediate(planeObject); |
|||
yield return null; |
|||
yield return null; |
|||
|
|||
Object.DestroyImmediate(planeObject2); |
|||
#if HDRP_PRESENT
|
|||
//TODO: Remove this when DestroyImmediate properly calls Cleanup on the pass
|
|||
var labelHistogramPass = (ObjectCountPass)cameraObject.GetComponent<CustomPassVolume>().customPasses.First(p => p is ObjectCountPass); |
|||
labelHistogramPass.WaitForAllRequests(); |
|||
#endif
|
|||
//destroy the object to force all pending segmented image readbacks to finish and events to be fired.
|
|||
DestroyTestObject(cameraObject); |
|||
|
|||
//RenderDoc.EndCaptureRenderDoc(gameView);
|
|||
|
|||
foreach (var result in receivedResults) |
|||
{ |
|||
Assert.AreEqual(1, result.counts.Length); |
|||
Assert.AreEqual(1, result.labels.Length); |
|||
Assert.Contains(result.frameCount, expectedFramesAndCounts.Keys, "Received event with unexpected frameCount."); |
|||
|
|||
var expectedCount = expectedFramesAndCounts[result.frameCount]; |
|||
|
|||
var errorString = $"Wrong count in frame {result.frameCount - startFrameCount}. {string.Join(", ", receivedResults.Select(r => $"count: {r.counts[0]}"))}"; |
|||
Assert.AreEqual(expectedCount, result.counts[0], errorString); |
|||
|
|||
expectedFramesAndCounts.Remove(result.frameCount); |
|||
} |
|||
|
|||
CollectionAssert.IsEmpty(expectedFramesAndCounts); |
|||
} |
|||
|
|||
static GameObject SetupCamera(LabelingConfiguration labelingConfiguration, |
|||
Action<NativeSlice<uint>, IReadOnlyList<LabelEntry>, int> onClassCountsReceived) |
|||
{ |
|||
var cameraObject = new GameObject(); |
|||
cameraObject.SetActive(false); |
|||
var camera = cameraObject.AddComponent<Camera>(); |
|||
camera.orthographic = true; |
|||
camera.orthographicSize = 1; |
|||
|
|||
#if HDRP_PRESENT
|
|||
cameraObject.AddComponent<HDAdditionalCameraData>(); |
|||
var customPassVolume = cameraObject.AddComponent<CustomPassVolume>(); |
|||
customPassVolume.isGlobal = true; |
|||
var rt = new RenderTexture(128, 128, 1, GraphicsFormat.R8G8B8A8_UNorm); |
|||
rt.Create(); |
|||
var instanceSegmentationPass = new InstanceSegmentationPass() |
|||
{ |
|||
targetCamera = camera, |
|||
targetTexture = rt |
|||
}; |
|||
instanceSegmentationPass.name = nameof(instanceSegmentationPass); |
|||
instanceSegmentationPass.EnsureInit(); |
|||
customPassVolume.customPasses.Add(instanceSegmentationPass); |
|||
var objectCountPass = new ObjectCountPass(camera); |
|||
objectCountPass.SegmentationTexture = rt; |
|||
objectCountPass.LabelingConfiguration = labelingConfiguration; |
|||
objectCountPass.name = nameof(objectCountPass); |
|||
customPassVolume.customPasses.Add(objectCountPass); |
|||
|
|||
objectCountPass.ClassCountsReceived += onClassCountsReceived; |
|||
#endif
|
|||
#if URP_PRESENT
|
|||
var perceptionCamera = cameraObject.AddComponent<PerceptionCamera>(); |
|||
perceptionCamera.LabelingConfiguration = labelingConfiguration; |
|||
perceptionCamera.captureRgbImages = false; |
|||
perceptionCamera.produceBoundingBoxAnnotations = false; |
|||
perceptionCamera.produceObjectCountAnnotations = true; |
|||
perceptionCamera.classCountsReceived += onClassCountsReceived; |
|||
#endif
|
|||
cameraObject.SetActive(true); |
|||
return cameraObject; |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue