浏览代码

Extensible labelers (#28)

* Refactor PerceptionCamera into CameraLabeler and its subclasses
/main
GitHub 4 年前
当前提交
4caee75b
共有 91 个文件被更改,包括 3643 次插入1700 次删除
  1. 139
      TestProjects/PerceptionHDRP/Assets/Scenes/SampleScene.unity
  2. 5
      TestProjects/PerceptionHDRP/Packages/manifest.json
  3. 2
      TestProjects/PerceptionHDRP/ProjectSettings/EditorSettings.asset
  4. 4
      TestProjects/PerceptionHDRP/ProjectSettings/ProjectVersion.txt
  5. 124
      TestProjects/PerceptionURP/Assets/Scenes/SampleScene.unity
  6. 5
      TestProjects/PerceptionURP/Packages/manifest.json
  7. 2
      TestProjects/PerceptionURP/ProjectSettings/EditorSettings.asset
  8. 4
      TestProjects/PerceptionURP/ProjectSettings/ProjectVersion.txt
  9. 2
      TestProjects/PerceptionURP/ProjectSettings/QualitySettings.asset
  10. 12
      com.unity.perception/Editor/GroundTruth/LabelingEditor.cs
  11. 2
      com.unity.perception/Editor/GroundTruth/SemanticSegmentationPassEditor.cs
  12. 6
      com.unity.perception/Editor/Unity.Perception.Editor.asmdef
  13. 4
      com.unity.perception/Runtime/GroundTruth/Ego.cs
  14. 9
      com.unity.perception/Runtime/GroundTruth/GroundTruthRendererFeature.cs
  15. 2
      com.unity.perception/Runtime/GroundTruth/Labeling/StartingLabelId.cs
  16. 559
      com.unity.perception/Runtime/GroundTruth/PerceptionCamera.cs
  17. 13
      com.unity.perception/Runtime/GroundTruth/RenderedObjectInfo.cs
  18. 77
      com.unity.perception/Runtime/GroundTruth/RenderedObjectInfoGenerator.cs
  19. 8
      com.unity.perception/Runtime/GroundTruth/Resources/SemanticSegmentation.shader
  20. 20
      com.unity.perception/Runtime/GroundTruth/SemanticSegmentationCrossPipelinePass.cs
  21. 8
      com.unity.perception/Runtime/GroundTruth/SemanticSegmentationPass.cs
  22. 3
      com.unity.perception/Runtime/GroundTruth/SimulationState.cs
  23. 143
      com.unity.perception/Tests/Editor/PerceptionCameraEditorTests.cs
  24. 8
      com.unity.perception/Tests/Editor/Unity.Perception.Editor.Tests.asmdef
  25. 50
      com.unity.perception/Tests/Runtime/GroundTruthTests/PerceptionCameraIntegrationTests.cs
  26. 128
      com.unity.perception/Tests/Runtime/GroundTruthTests/SegmentationGroundTruthTests.cs
  27. 2
      com.unity.perception/Tests/Runtime/Unity.Perception.Runtime.Tests.asmdef
  28. 2
      com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureSensorSchedulingTests.cs.meta
  29. 2
      com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs.meta
  30. 2
      com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureTests.cs.meta
  31. 23
      TestProjects/PerceptionHDRP/Assets/IdLabelConfig.asset
  32. 8
      TestProjects/PerceptionHDRP/Assets/IdLabelConfig.asset.meta
  33. 21
      TestProjects/PerceptionHDRP/Assets/SemanticSegmentationLabelingConfiguration.asset
  34. 8
      TestProjects/PerceptionHDRP/Assets/SemanticSegmentationLabelingConfiguration.asset.meta
  35. 541
      TestProjects/PerceptionHDRP/Packages/packages-lock.json
  36. 2
      TestProjects/PerceptionHDRP/PerceptionHDRP.sln.DotSettings
  37. 23
      TestProjects/PerceptionURP/Assets/IdLabelConfig.asset
  38. 8
      TestProjects/PerceptionURP/Assets/IdLabelConfig.asset.meta
  39. 8
      TestProjects/PerceptionURP/Assets/Resources.meta
  40. 21
      TestProjects/PerceptionURP/Assets/SemanticSegmentationLabelingConfiguration.asset
  41. 8
      TestProjects/PerceptionURP/Assets/SemanticSegmentationLabelingConfiguration.asset.meta
  42. 519
      TestProjects/PerceptionURP/Packages/packages-lock.json
  43. 2
      TestProjects/PerceptionURP/PerceptionURP.sln.DotSettings
  44. 156
      com.unity.perception/Editor/GroundTruth/CameraLabelerDrawer.cs
  45. 3
      com.unity.perception/Editor/GroundTruth/CameraLabelerDrawer.cs.meta
  46. 23
      com.unity.perception/Editor/GroundTruth/CameraLabelerDrawerAttribute.cs
  47. 3
      com.unity.perception/Editor/GroundTruth/CameraLabelerDrawerAttribute.cs.meta
  48. 146
      com.unity.perception/Editor/GroundTruth/IdLabelConfigEditor.cs
  49. 131
      com.unity.perception/Editor/GroundTruth/PerceptionCameraEditor.cs
  50. 3
      com.unity.perception/Editor/GroundTruth/PerceptionCameraEditor.cs.meta
  51. 91
      com.unity.perception/Editor/GroundTruth/SemanticSegmentationLabelConfigEditor.cs
  52. 3
      com.unity.perception/Editor/GroundTruth/SemanticSegmentationLabelConfigEditor.cs.meta
  53. 3
      com.unity.perception/Runtime/GroundTruth/Labelers.meta
  54. 106
      com.unity.perception/Runtime/GroundTruth/Labeling/IdLabelConfig.cs
  55. 3
      com.unity.perception/Runtime/GroundTruth/Labeling/IdLabelConfig.cs.meta
  56. 104
      com.unity.perception/Runtime/GroundTruth/Labeling/LabelConfig.cs
  57. 3
      com.unity.perception/Runtime/GroundTruth/Labeling/LabelConfig.cs.meta
  58. 55
      com.unity.perception/Runtime/GroundTruth/Labeling/LabelEntryMatchCache.cs
  59. 3
      com.unity.perception/Runtime/GroundTruth/Labeling/LabelEntryMatchCache.cs.meta
  60. 28
      com.unity.perception/Runtime/GroundTruth/Labeling/SemanticSegmentationLabelConfig.cs
  61. 3
      com.unity.perception/Runtime/GroundTruth/Labeling/SemanticSegmentationLabelConfig.cs.meta
  62. 83
      com.unity.perception/Runtime/GroundTruth/PerceptionCamera_InstanceSegmentation.cs
  63. 3
      com.unity.perception/Runtime/GroundTruth/PerceptionCamera_InstanceSegmentation.cs.meta
  64. 125
      com.unity.perception/Tests/Runtime/GroundTruthTests/ObjectCountLabelerTests.cs
  65. 159
      com.unity.perception/Tests/Runtime/GroundTruthTests/RenderedObjectInfoTests.cs
  66. 115
      com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs
  67. 71
      com.unity.perception/Runtime/GroundTruth/Labelers/CameraLabeler.cs
  68. 3
      com.unity.perception/Runtime/GroundTruth/Labelers/CameraLabeler.cs.meta
  69. 138
      com.unity.perception/Runtime/GroundTruth/Labelers/ObjectCountLabeler.cs
  70. 3
      com.unity.perception/Runtime/GroundTruth/Labelers/ObjectCountLabeler.cs.meta
  71. 125
      com.unity.perception/Runtime/GroundTruth/Labelers/RenderedObjectInfoLabeler.cs
  72. 11
      com.unity.perception/Runtime/GroundTruth/Labelers/RenderedObjectInfoLabeler.cs.meta
  73. 216
      com.unity.perception/Runtime/GroundTruth/Labelers/SemanticSegmentationLabeler.cs
  74. 11
      com.unity.perception/Runtime/GroundTruth/Labelers/SemanticSegmentationLabeler.cs.meta
  75. 8
      TestProjects/PerceptionHDRP/Assets/LabelingConfiguration.asset.meta
  76. 26
      TestProjects/PerceptionHDRP/Assets/LabelingConfiguration.asset
  77. 26
      TestProjects/PerceptionURP/Assets/ExampleLabelingConfiguration.asset
  78. 8
      TestProjects/PerceptionURP/Assets/ExampleLabelingConfiguration.asset.meta
  79. 21
      com.unity.perception/Editor/GroundTruth/ObjectCountPassEditor.cs
  80. 157
      com.unity.perception/Editor/GroundTruth/LabelingConfigurationEditor.cs
  81. 108
      com.unity.perception/Runtime/GroundTruth/Labeling/LabelingConfiguration.cs
  82. 181
      com.unity.perception/Runtime/GroundTruth/ObjectCountPass.cs
  83. 192
      com.unity.perception/Tests/Runtime/GroundTruthTests/BoundingBox2DTests.cs
  84. 147
      com.unity.perception/Tests/Runtime/GroundTruthTests/ObjectCountTests.cs
  85. 0
      /com.unity.perception/Editor/GroundTruth/IdLabelConfigEditor.cs.meta
  86. 0
      /com.unity.perception/Tests/Runtime/GroundTruthTests/RenderedObjectInfoTests.cs.meta
  87. 0
      /com.unity.perception/Tests/Runtime/GroundTruthTests/ObjectCountLabelerTests.cs.meta
  88. 0
      /com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureSensorSchedulingTests.cs.meta
  89. 0
      /com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs.meta
  90. 0
      /com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureTests.cs.meta

139
TestProjects/PerceptionHDRP/Assets/Scenes/SampleScene.unity


debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &4662619
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4662620}
m_Layer: 0
m_Name: GameObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4662620
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4662619}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -2.7286716, y: -2.380882, z: 5.498973}
m_LocalScale: {x: 36.249973, y: 36.249973, z: 36.249973}
m_Children:
- {fileID: 963194228}
- {fileID: 705507995}
- {fileID: 1640252283}
- {fileID: 464025709}
- {fileID: 411238281}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &411238276
GameObject:
m_ObjectHideFlags: 0

- component: {fileID: 411238277}
- component: {fileID: 411238282}
m_Layer: 0
m_Name: Cube (2)
m_Name: Crate
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0

m_Script: {fileID: 11500000, guid: 8b33f0bc2b78db642a758f07826d0dd0, type: 3}
m_Name:
m_EditorClassIdentifier:
classes:
labels:
- Crate
--- !u!65 &411238278
BoxCollider:

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 411238276}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 4.3786716, y: 2.380882, z: -4.288973}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalPosition: {x: 155.99806, y: 83.926025, z: -149.97618}
m_LocalScale: {x: 36.249973, y: 36.249973, z: 36.249973}
m_Father: {fileID: 4662620}
m_RootOrder: 4
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &411238282
MonoBehaviour:

- component: {fileID: 464025705}
- component: {fileID: 464025710}
m_Layer: 0
m_Name: Cube (1)
m_Name: Cube
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0

m_Script: {fileID: 11500000, guid: 8b33f0bc2b78db642a758f07826d0dd0, type: 3}
m_Name:
m_EditorClassIdentifier:
classes:
labels:
- Cube
--- !u!65 &464025706
BoxCollider:

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 464025704}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 2.6386716, y: 2.380882, z: -3.9089727}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalPosition: {x: 92.92311, y: 83.926025, z: -136.20119}
m_LocalScale: {x: 36.249973, y: 36.249973, z: 36.249973}
m_Father: {fileID: 4662620}
m_RootOrder: 3
m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &464025710
MonoBehaviour:

m_BounceIntensity: 1
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_BoundingSphereOverride: {x: 6.25e-43, y: 1.0156355e+12, z: 6.25e-43, w: 2.8676e-41}
m_BoundingSphereOverride: {x: 6.3e-43, y: 108.39679, z: 6.3e-43, w: 0}
m_UseBoundingSphereOverride: 0
m_ShadowRadius: 0
m_ShadowAngle: 0

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 705507993}
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
m_LocalPosition: {x: 2.7286716, y: 5.3808823, z: -5.498973}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalPosition: {x: 96.1856, y: 192.67596, z: -193.83864}
m_LocalScale: {x: 36.249973, y: 36.249977, z: 36.249973}
m_Father: {fileID: 4662620}
m_RootOrder: 1
m_Father: {fileID: 0}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!114 &705507996
MonoBehaviour:

m_Script: {fileID: 11500000, guid: 7a68c43fe1f2a47cfa234b5eeaa98012, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Version: 9
m_Version: 10
m_ObsoleteShadowResolutionTier: 1
m_ObsoleteUseShadowQualitySettings: 0
m_ObsoleteCustomShadowResolution: 512

m_FilterSizeTraced: 16
m_SunLightConeAngle: 0.5
m_LightShadowRadius: 0.5
m_SemiTransparentShadow: 0
m_ColorShadow: 1
m_EvsmExponent: 15
m_EvsmLightLeakBias: 0
m_EvsmVarianceBias: 0.00001

useVolumetric: 1
featuresFoldout: 1
showAdditionalSettings: 0
m_AreaLightEmissiveMeshShadowCastingMode: 0
m_AreaLightEmissiveMeshMotionVectorGenerationMode: 0
--- !u!1 &963194225
GameObject:
m_ObjectHideFlags: 0

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 963194225}
m_LocalRotation: {x: -0.17179534, y: 0.30667058, z: -0.056378223, w: -0.93448436}
m_LocalPosition: {x: 5.5378666, y: 3.5565922, z: -7.528791}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalPosition: {x: 198.01884, y: 126.545494, z: -267.4195}
m_LocalScale: {x: 36.249973, y: 36.249973, z: 36.249973}
m_Father: {fileID: 4662620}
m_RootOrder: 0
m_Father: {fileID: 0}
m_RootOrder: 4
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &963194229
MonoBehaviour:

description: The main camera
period: 0.0166
startTime: 0
produceSegmentationImages: 1
produceObjectCountAnnotations: 1
LabelingConfiguration: {fileID: 11400000, guid: be3971a848968144e8d07d9136a5bf49,
type: 2}
captureRgbImages: 1
m_Labelers:
- id: 0
- id: 1
- id: 2
- id: 3
references:
version: 1
00000000:
type: {class: BoundingBox2DLabeler, ns: UnityEngine.Perception.GroundTruth,
asm: Unity.Perception.Runtime}
data:
enabled: 1
foldout: 0
annotationId: F9F22E05-443F-4602-A422-EBE4EA9B55CB
labelingConfiguration: {fileID: 11400000, guid: be3971a848968144e8d07d9136a5bf49,
type: 2}
00000001:
type: {class: SemanticSegmentationLabeler, ns: UnityEngine.Perception.GroundTruth,
asm: Unity.Perception.Runtime}
data:
enabled: 1
foldout: 0
annotationId: 12F94D8D-5425-4DEB-9B21-5E53AD957D66
labelConfig: {fileID: 11400000, guid: c140c5aa05dd09e4fadaa26de31b1f39, type: 2}
00000002:
type: {class: ObjectCountLabeler, ns: UnityEngine.Perception.GroundTruth, asm: Unity.Perception.Runtime}
data:
enabled: 1
foldout: 0
objectCountMetricId: 51DA3C27-369D-4929-AEA6-D01614635CE2
m_LabelingConfiguration: {fileID: 11400000, guid: be3971a848968144e8d07d9136a5bf49,
type: 2}
00000003:
type: {class: RenderedObjectInfoLabeler, ns: UnityEngine.Perception.GroundTruth,
asm: Unity.Perception.Runtime}
data:
enabled: 1
foldout: 0
objectInfoMetricId: 5BA92024-B3B7-41A7-9D3F-C03A6A8DDD01
labelingConfiguration: {fileID: 11400000, guid: be3971a848968144e8d07d9136a5bf49,
type: 2}
--- !u!1 &1640252278
GameObject:
m_ObjectHideFlags: 0

- component: {fileID: 1640252279}
- component: {fileID: 1640252284}
m_Layer: 0
m_Name: Cube
m_Name: Box
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0

m_Script: {fileID: 11500000, guid: 8b33f0bc2b78db642a758f07826d0dd0, type: 3}
m_Name:
m_EditorClassIdentifier:
classes:
labels:
- Box
--- !u!65 &1640252280
BoxCollider:

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1640252278}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 2.7286716, y: 2.380882, z: -5.498973}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalPosition: {x: 96.1856, y: 83.926025, z: -193.83864}
m_LocalScale: {x: 36.249973, y: 36.249973, z: 36.249973}
m_Father: {fileID: 4662620}
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1640252284

5
TestProjects/PerceptionHDRP/Packages/manifest.json


"com.unity.collab-proxy": "1.2.16",
"com.unity.ext.nunit": "1.0.0",
"com.unity.ide.rider": "1.1.4",
"com.unity.ide.vscode": "1.2.0",
"com.unity.ide.vscode": "1.2.1",
"com.unity.package-validation-suite": "0.9.1-preview",
"com.unity.perception": "file:../../../com.unity.perception",
"com.unity.render-pipelines.core": "7.3.1",

"com.unity.test-framework": "1.1.13",
"com.unity.test-framework": "1.1.14",
"nuget.moq": "1.0.0",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.androidjni": "1.0.0",
"com.unity.modules.animation": "1.0.0",

2
TestProjects/PerceptionHDRP/ProjectSettings/EditorSettings.asset


inProgressEnabled: 1
m_EnableTextureStreamingInEditMode: 1
m_EnableTextureStreamingInPlayMode: 1
m_AsyncShaderCompilation: 1
m_AsyncShaderCompilation: 0
m_EnterPlayModeOptionsEnabled: 0
m_EnterPlayModeOptions: 3
m_ShowLightmapResolutionOverlay: 1

4
TestProjects/PerceptionHDRP/ProjectSettings/ProjectVersion.txt


m_EditorVersion: 2019.3.13f1
m_EditorVersionWithRevision: 2019.3.13f1 (d4ddf0d95db9)
m_EditorVersion: 2019.4.1f1
m_EditorVersionWithRevision: 2019.4.1f1 (e6c045e14e4e)

124
TestProjects/PerceptionURP/Assets/Scenes/SampleScene.unity


debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &4662619
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4662620}
m_Layer: 0
m_Name: GameObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4662620
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4662619}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -2.7286716, y: -2.380882, z: 5.498973}
m_LocalScale: {x: 36.249973, y: 36.249973, z: 36.249973}
m_Children:
- {fileID: 963194228}
- {fileID: 705507995}
- {fileID: 1640252283}
- {fileID: 464025709}
- {fileID: 411238281}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &411238276
GameObject:
m_ObjectHideFlags: 0

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 411238276}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 4.3786716, y: 2.380882, z: -4.288973}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalPosition: {x: 155.99806, y: 83.926025, z: -149.97618}
m_LocalScale: {x: 36.249973, y: 36.249973, z: 36.249973}
m_Father: {fileID: 4662620}
m_RootOrder: 4
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &411238282
MonoBehaviour:

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 464025704}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 2.6386716, y: 2.380882, z: -3.9089727}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalPosition: {x: 92.92311, y: 83.926025, z: -136.20119}
m_LocalScale: {x: 36.249973, y: 36.249973, z: 36.249973}
m_Father: {fileID: 4662620}
m_RootOrder: 3
m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &464025710
MonoBehaviour:

m_BounceIntensity: 1
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_BoundingSphereOverride: {x: 6.25e-43, y: 1.0156355e+12, z: 6.25e-43, w: 2.8676e-41}
m_BoundingSphereOverride: {x: 1e-45, y: 9e-44, z: 9e-44, w: 0}
m_UseBoundingSphereOverride: 0
m_ShadowRadius: 0
m_ShadowAngle: 0

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 705507993}
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
m_LocalPosition: {x: 2.7286716, y: 5.3808823, z: -5.498973}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalPosition: {x: 96.1856, y: 192.67596, z: -193.83864}
m_LocalScale: {x: 36.249973, y: 36.249977, z: 36.249973}
m_Father: {fileID: 4662620}
m_RootOrder: 1
m_Father: {fileID: 0}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!114 &705507996
MonoBehaviour:

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 963194225}
m_LocalRotation: {x: -0.17179534, y: 0.30667058, z: -0.056378223, w: -0.93448436}
m_LocalPosition: {x: 5.5378666, y: 3.5565922, z: -7.528791}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalPosition: {x: 198.01884, y: 126.545494, z: -267.4195}
m_LocalScale: {x: 36.249973, y: 36.249973, z: 36.249973}
m_Father: {fileID: 4662620}
m_RootOrder: 0
m_Father: {fileID: 0}
m_RootOrder: 4
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!20 &963194229
Camera:

period: 0.0166
startTime: 0
captureRgbImages: 1
produceSegmentationImages: 1
produceObjectCountAnnotations: 1
objectCountId: 51DA3C27-369D-4929-AEA6-D01614635CE2
produceBoundingBoxAnnotations: 1
boundingBoxId: F9F22E05-443F-4602-A422-EBE4EA9B55CB
produceRenderedObjectInfoMetric: 1
renderedObjectInfoId: 5BA92024-B3B7-41A7-9D3F-C03A6A8DDD01
boundingBoxOrigin: 0
LabelingConfiguration: {fileID: 11400000, guid: e74234fe725079e4aa7ecd74797ceb79,
type: 2}
m_Labelers:
- id: 0
- id: 1
- id: 2
- id: 3
references:
version: 1
00000000:
type: {class: ObjectCountLabeler, ns: UnityEngine.Perception.GroundTruth, asm: Unity.Perception.Runtime}
data:
enabled: 1
objectCountMetricId: 51DA3C27-369D-4929-AEA6-D01614635CE2
m_IdLabelConfig: {fileID: 11400000, guid: cedcacfb1d9beb34fbbb231166c472fe,
type: 2}
00000001:
type: {class: BoundingBox2DLabeler, ns: UnityEngine.Perception.GroundTruth,
asm: Unity.Perception.Runtime}
data:
enabled: 1
annotationId: F9F22E05-443F-4602-A422-EBE4EA9B55CB
idLabelConfig: {fileID: 11400000, guid: cedcacfb1d9beb34fbbb231166c472fe,
type: 2}
00000002:
type: {class: RenderedObjectInfoLabeler, ns: UnityEngine.Perception.GroundTruth,
asm: Unity.Perception.Runtime}
data:
enabled: 1
objectInfoMetricId: 5BA92024-B3B7-41A7-9D3F-C03A6A8DDD01
idLabelConfig: {fileID: 11400000, guid: cedcacfb1d9beb34fbbb231166c472fe,
type: 2}
00000003:
type: {class: SemanticSegmentationLabeler, ns: UnityEngine.Perception.GroundTruth,
asm: Unity.Perception.Runtime}
data:
enabled: 1
annotationId: 12F94D8D-5425-4DEB-9B21-5E53AD957D66
labelConfig: {fileID: 11400000, guid: c140c5aa05dd09e4fadaa26de31b1f39, type: 2}
--- !u!114 &963194231
MonoBehaviour:
m_ObjectHideFlags: 0

- component: {fileID: 1640252284}
- component: {fileID: 1640252280}
m_Layer: 0
m_Name: Box
m_Name: Box1234
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0

m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1640252278}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 2.7286716, y: 2.380882, z: -5.498973}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalPosition: {x: 96.1856, y: 83.926025, z: -193.83864}
m_LocalScale: {x: 36.249973, y: 36.249973, z: 36.249973}
m_Father: {fileID: 4662620}
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1640252284

5
TestProjects/PerceptionURP/Packages/manifest.json


"dependencies": {
"com.unity.collab-proxy": "1.2.16",
"com.unity.ide.rider": "1.1.4",
"com.unity.ide.vscode": "1.2.0",
"com.unity.ide.vscode": "1.2.1",
"com.unity.test-framework": "1.1.13",
"com.unity.test-framework": "1.1.14",
"nuget.moq": "1.0.0",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.androidjni": "1.0.0",
"com.unity.modules.animation": "1.0.0",

2
TestProjects/PerceptionURP/ProjectSettings/EditorSettings.asset


inProgressEnabled: 1
m_EnableTextureStreamingInEditMode: 1
m_EnableTextureStreamingInPlayMode: 1
m_AsyncShaderCompilation: 1
m_AsyncShaderCompilation: 0
m_EnterPlayModeOptionsEnabled: 0
m_EnterPlayModeOptions: 3
m_ShowLightmapResolutionOverlay: 1

4
TestProjects/PerceptionURP/ProjectSettings/ProjectVersion.txt


m_EditorVersion: 2019.3.13f1
m_EditorVersionWithRevision: 2019.3.13f1 (d4ddf0d95db9)
m_EditorVersion: 2019.4.1f1
m_EditorVersionWithRevision: 2019.4.1f1 (e6c045e14e4e)

2
TestProjects/PerceptionURP/ProjectSettings/QualitySettings.asset


skinWeights: 2
textureQuality: 0
anisotropicTextures: 1
antiAliasing: 0
antiAliasing: 2
softParticles: 0
softVegetation: 1
realtimeReflectionProbes: 1

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


public void OnEnable()
{
m_LabelsList = new ReorderableList(serializedObject, serializedObject.FindProperty(nameof(global::UnityEngine.Perception.GroundTruth.Labeling.labels)), true, false, true, true);
m_LabelsList = new ReorderableList(serializedObject, serializedObject.FindProperty(nameof(Labeling.labels)), true, false, true, true);
m_LabelsList.drawElementCallback = DrawElement;
m_LabelsList.onAddCallback += OnAdd;
m_LabelsList.onRemoveCallback += OnRemove;

{
if (list.index != -1)
Labeling.labels.RemoveAt(list.index);
labeling.labels.RemoveAt(list.index);
Labeling Labeling => (Labeling)target;
Labeling labeling => (Labeling)target;
Labeling.labels.Add("");
labeling.labels.Add("");
}
void DrawElement(Rect rect, int index, bool isactive, bool isfocused)

return;
var contentRect = new Rect(rect.x + indent, rect.y, rect.width - indent, rect.height);
var value = EditorGUI.TextField(contentRect, Labeling.labels[index]);
var value = EditorGUI.TextField(contentRect, labeling.labels[index]);
Labeling.labels[index] = value;
labeling.labels[index] = value;
}
}
}

2
com.unity.perception/Editor/GroundTruth/SemanticSegmentationPassEditor.cs


{
AddProperty(customPass.FindPropertyRelative(nameof(SemanticSegmentationPass.targetCamera)));
AddProperty(customPass.FindPropertyRelative(nameof(SemanticSegmentationPass.targetTexture)));
AddProperty(customPass.FindPropertyRelative(nameof(SemanticSegmentationPass.labelingConfiguration)));
AddProperty(customPass.FindPropertyRelative(nameof(SemanticSegmentationPass.semanticSegmentationLabelConfig)));
base.Initialize(customPass);
}
}

6
com.unity.perception/Editor/Unity.Perception.Editor.asmdef


],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"overrideReferences": true,
"precompiledReferences": [
"Newtonsoft.Json.dll"
],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [

4
com.unity.perception/Runtime/GroundTruth/Ego.cs


/// </summary>
public string Description;
EgoHandle m_EgoHandle;
/// The EgoHandle registered with the SimulationManager at runtime.
/// The EgoHandle registered with DatasetCapture at runtime.
/// </summary>
public EgoHandle EgoHandle
{

9
com.unity.perception/Runtime/GroundTruth/GroundTruthRendererFeature.cs


{
SemanticSegmentationCrossPipelinePass m_SemanticSegmentationCrossPipelinePass;
public SemanticSegmentationUrpPass(Camera camera, RenderTexture targetTexture, LabelingConfiguration labelingConfiguration)
public SemanticSegmentationUrpPass(Camera camera, RenderTexture targetTexture, SemanticSegmentationLabelConfig labelConfig)
m_SemanticSegmentationCrossPipelinePass = new SemanticSegmentationCrossPipelinePass(camera, labelingConfiguration);
m_SemanticSegmentationCrossPipelinePass = new SemanticSegmentationCrossPipelinePass(camera, labelConfig);
ConfigureTarget(targetTexture, targetTexture.depthBuffer);
m_SemanticSegmentationCrossPipelinePass.Setup();
}

if (!EditorApplication.isPlaying)
return;
#endif
renderer.EnqueuePass(perceptionCamera.instanceSegmentationUrpPass);
renderer.EnqueuePass(perceptionCamera.semanticSegmentationUrpPass);
foreach (var pass in perceptionCamera.passes)
renderer.EnqueuePass(pass);
}
}
}

2
com.unity.perception/Runtime/GroundTruth/Labeling/StartingLabelId.cs


namespace UnityEngine.Perception.GroundTruth
{
/// <summary>
/// Selector for whether label ids should start at zero or one. <seealso cref="LabelingConfiguration.StartingLabelId"/>.
/// Selector for whether label ids should start at zero or one. <seealso cref="IdLabelConfig.startingLabelId"/>.
/// </summary>
public enum StartingLabelId
{

559
com.unity.perception/Runtime/GroundTruth/PerceptionCamera.cs


using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations;
using Unity.Entities;
using Unity.Profiling;
using Unity.Simulation;
using UnityEngine;

using UnityEngine.Serialization;
#if URP_PRESENT
using UnityEngine.Rendering.Universal;
#endif
namespace UnityEngine.Perception.GroundTruth
{

[RequireComponent(typeof(Camera))]
public class PerceptionCamera : MonoBehaviour
public partial class PerceptionCamera : MonoBehaviour
const string k_SemanticSegmentationDirectory = "SemanticSegmentation";
const string k_SegmentationFilePrefix = "segmentation_";
/// <summary>
/// A human-readable description of the camera.

/// </summary>
public bool captureRgbImages = true;
/// <summary>
/// Whether semantic segmentation images should be generated
/// </summary>
public bool produceSegmentationImages = true;
/// <summary>
/// Whether object counts should be computed
/// </summary>
public bool produceObjectCountAnnotations = true;
/// <summary>
/// The ID to use for object count annotations in the resulting dataset
/// </summary>
[FormerlySerializedAs("m_ObjectCountID")]
public string objectCountId = "51DA3C27-369D-4929-AEA6-D01614635CE2";
/// <summary>
/// Whether object bounding boxes should be computed
/// </summary>
public bool produceBoundingBoxAnnotations = true;
/// <summary>
/// The ID to use for bounding box annotations in the resulting dataset
/// </summary>
[FormerlySerializedAs("m_BoundingBoxID")]
public string boundingBoxId = "F9F22E05-443F-4602-A422-EBE4EA9B55CB";
/// <summary>
/// Whether rendered object info metrics should be generated. This metric currently contains label id, instance id, and visible pixels.
/// </summary>
[FormerlySerializedAs("produceVisiblePixelsMetric")]
public bool produceRenderedObjectInfoMetric = true;
/// <summary>
/// The ID to use for visible pixels metrics in the resulting dataset
/// </summary>
[FormerlySerializedAs("visiblePixelsId")]
[FormerlySerializedAs("m_VisiblePixelsID")]
public string renderedObjectInfoId = "5BA92024-B3B7-41A7-9D3F-C03A6A8DDD01";
/// <summary>
/// The corner of the image to use as the origin for bounding boxs.
/// Event invoked after the camera finishes rendering during a frame.
public BoundingBoxOrigin boundingBoxOrigin = BoundingBoxOrigin.TopLeft;
/// <summary>
/// The LabelingConfiguration to use for segmentation and object count.
/// </summary>
public LabelingConfiguration LabelingConfiguration;
/// <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 frame in which the objects were rendered.
/// </summary>
public event Action<int, NativeArray<RenderedObjectInfo>> renderedObjectInfosCalculated;
internal event Action<int, NativeArray<uint>> segmentationImageReceived;
internal event Action<NativeSlice<uint>, IReadOnlyList<LabelEntry>, int> classCountsReceived;
[NonSerialized]
internal RenderTexture labelingTexture;
[NonSerialized]
internal RenderTexture segmentationTexture;
RenderTextureReader<short> m_ClassLabelingTextureReader;
RenderTextureReader<uint> m_SegmentationReader;
RenderedObjectInfoGenerator m_RenderedObjectInfoGenerator;
[SerializeReference]
List<CameraLabeler> m_Labelers = new List<CameraLabeler>();
[NonSerialized]
internal InstanceSegmentationUrpPass instanceSegmentationUrpPass;
[NonSerialized]
internal SemanticSegmentationUrpPass semanticSegmentationUrpPass;
internal List<ScriptableRenderPass> passes = new List<ScriptableRenderPass>();
public void AddScriptableRenderPass(ScriptableRenderPass pass)
{
passes.Add(pass);
}
#endif
bool m_CapturedLastFrame;

/// </summary>
public SensorHandle SensorHandle { get; private set; }
struct AsyncSemanticSegmentationWrite
{
public short[] dataArray;
public int width;
public int height;
public string path;
}
struct AsyncCaptureInfo
{
public int FrameCount;
public AsyncAnnotation SegmentationAsyncAnnotation;
public AsyncMetric ClassCountAsyncMetric;
public AsyncMetric RenderedObjectInfoAsyncMetric;
public AsyncAnnotation BoundingBoxAsyncMetric;
}
List<AsyncCaptureInfo> m_AsyncCaptureInfos = new List<AsyncCaptureInfo>();
[SuppressMessage("ReSharper", "InconsistentNaming")]
[SuppressMessage("ReSharper", "NotAccessedField.Local")]
struct ClassCountValue
{
public int label_id;
public string label_name;
public uint count;
}
[SuppressMessage("ReSharper", "InconsistentNaming")]
[SuppressMessage("ReSharper", "NotAccessedField.Local")]
struct BoundingBoxValue
{
public int label_id;
public string label_name;
public int instance_id;
public float x;
public float y;
public float width;
public float height;
}
ClassCountValue[] m_ClassCountValues;
BoundingBoxValue[] m_BoundingBoxValues;
RenderedObjectInfoValue[] m_VisiblePixelsValues;
#if HDRP_PRESENT
InstanceSegmentationPass m_SegmentationPass;
SemanticSegmentationPass m_SemanticSegmentationPass;
#endif
MetricDefinition m_ObjectCountMetricDefinition;
AnnotationDefinition m_BoundingBoxAnnotationDefinition;
AnnotationDefinition m_SegmentationAnnotationDefinition;
MetricDefinition m_RenderedObjectInfoMetricDefinition;
static ProfilerMarker s_ClassCountCallback = new ProfilerMarker("OnClassLabelsReceived");
static ProfilerMarker s_RenderedObjectInfosCalculatedEvent = new ProfilerMarker("renderedObjectInfosCalculated event");
static ProfilerMarker s_BoundingBoxCallback = new ProfilerMarker("OnBoundingBoxesReceived");
static ProfilerMarker s_ProduceRenderedObjectInfoMetric = new ProfilerMarker("ProduceRenderedObjectInfoMetric");
[SuppressMessage("ReSharper", "InconsistentNaming")]
struct SemanticSegmentationSpec
{
[UsedImplicitly]
public int label_id;
[UsedImplicitly]
public string label_name;
[UsedImplicitly]
public int pixel_value;
}
[SuppressMessage("ReSharper", "InconsistentNaming")]
struct ObjectCountSpec
{
[UsedImplicitly]
public int label_id;
[UsedImplicitly]
public string label_name;
}
/// <summary>
/// Add a data object which will be added to the dataset with each capture. Overrides existing sensor data associated with the given key.

// Start is called before the first frame update
void Awake()
{
//CaptureOptions.useAsyncReadbackIfSupported = false;
var myCamera = GetComponent<Camera>();
var width = myCamera.pixelWidth;
var height = myCamera.pixelHeight;
if ((produceSegmentationImages || produceObjectCountAnnotations || produceBoundingBoxAnnotations) && LabelingConfiguration == null)
{
Debug.LogError("LabelingConfiguration must be set if producing ground truth data");
produceSegmentationImages = false;
produceObjectCountAnnotations = false;
produceBoundingBoxAnnotations = false;
}
segmentationTexture = new RenderTexture(new RenderTextureDescriptor(width, height, GraphicsFormat.R8G8B8A8_UNorm, 8));
segmentationTexture.name = "Segmentation";
labelingTexture = new RenderTexture(new RenderTextureDescriptor(width, height, GraphicsFormat.R8G8B8A8_UNorm, 8));
labelingTexture.name = "Labeling";
#if HDRP_PRESENT
var customPassVolume = this.GetComponent<CustomPassVolume>() ?? gameObject.AddComponent<CustomPassVolume>();
customPassVolume.injectionPoint = CustomPassInjectionPoint.BeforeRendering;
customPassVolume.isGlobal = true;
m_SegmentationPass = new InstanceSegmentationPass()
{
name = "Segmentation Pass",
targetCamera = myCamera,
targetTexture = segmentationTexture
};
m_SegmentationPass.EnsureInit();
m_SemanticSegmentationPass = new SemanticSegmentationPass(myCamera, labelingTexture, LabelingConfiguration)
{
name = "Labeling Pass"
};
SetupPasses(customPassVolume);
#endif
#if URP_PRESENT
instanceSegmentationUrpPass = new InstanceSegmentationUrpPass(myCamera, segmentationTexture);
semanticSegmentationUrpPass = new SemanticSegmentationUrpPass(myCamera, labelingTexture, LabelingConfiguration);
#endif
if (produceSegmentationImages)
{
var specs = LabelingConfiguration.LabelEntries.Select((l) => new SemanticSegmentationSpec()
{
label_id = l.id,
label_name = l.label,
pixel_value = l.value
}).ToArray();
m_SegmentationAnnotationDefinition = DatasetCapture.RegisterAnnotationDefinition("semantic segmentation", specs, "pixel-wise semantic segmentation label", "PNG");
m_ClassLabelingTextureReader = new RenderTextureReader<short>(labelingTexture, myCamera,
(frameCount, data, tex) => OnSemanticSegmentationImageRead(frameCount, data));
}
if (produceObjectCountAnnotations || produceBoundingBoxAnnotations || produceRenderedObjectInfoMetric)
{
var labelingMetricSpec = LabelingConfiguration.LabelEntries.Select((l) => new ObjectCountSpec()
{
label_id = l.id,
label_name = l.label,
}).ToArray();
if (produceObjectCountAnnotations)
{
m_ObjectCountMetricDefinition = DatasetCapture.RegisterMetricDefinition("object count", labelingMetricSpec, "Counts of objects for each label in the sensor's view", id: new Guid(objectCountId));
}
if (produceBoundingBoxAnnotations)
{
m_BoundingBoxAnnotationDefinition = DatasetCapture.RegisterAnnotationDefinition("bounding box", labelingMetricSpec, "Bounding box for each labeled object visible to the sensor", id: new Guid(boundingBoxId));
}
if (produceRenderedObjectInfoMetric)
m_RenderedObjectInfoMetricDefinition = DatasetCapture.RegisterMetricDefinition("rendered object info", labelingMetricSpec, "Information about each labeled object visible to the sensor", id: new Guid(renderedObjectInfoId));
m_RenderedObjectInfoGenerator = new RenderedObjectInfoGenerator(LabelingConfiguration);
World.DefaultGameObjectInjectionWorld.GetExistingSystem<GroundTruthLabelSetupSystem>().Activate(m_RenderedObjectInfoGenerator);
m_SegmentationReader = new RenderTextureReader<uint>(segmentationTexture, myCamera, (frameCount, data, tex) =>
{
if (segmentationImageReceived != null)
segmentationImageReceived(frameCount, data);
m_RenderedObjectInfoGenerator.Compute(data, tex.width, boundingBoxOrigin, out var renderedObjectInfos, out var classCounts, Allocator.Temp);
using (s_RenderedObjectInfosCalculatedEvent.Auto())
renderedObjectInfosCalculated?.Invoke(frameCount, renderedObjectInfos);
if (produceObjectCountAnnotations)
OnObjectCountsReceived(classCounts, LabelingConfiguration.LabelEntries, frameCount);
if (produceBoundingBoxAnnotations)
ProduceBoundingBoxesAnnotation(renderedObjectInfos, LabelingConfiguration.LabelEntries, frameCount);
if (produceRenderedObjectInfoMetric)
ProduceRenderedObjectInfoMetric(renderedObjectInfos, frameCount);
});
}
SetupInstanceSegmentation();
// ReSharper disable InconsistentNaming
struct RenderedObjectInfoValue
{
[UsedImplicitly]
public int label_id;
[UsedImplicitly]
public int instance_id;
[UsedImplicitly]
public int visible_pixels;
}
// ReSharper restore InconsistentNaming
void ProduceRenderedObjectInfoMetric(NativeArray<RenderedObjectInfo> renderedObjectInfos, int frameCount)
{
using (s_ProduceRenderedObjectInfoMetric.Auto())
{
var findResult = FindAsyncCaptureInfo(frameCount);
if (findResult.index == -1)
return;
var asyncCaptureInfo = findResult.asyncCaptureInfo;
var metric = asyncCaptureInfo.RenderedObjectInfoAsyncMetric;
if (!metric.IsValid)
return;
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);
}
}
#if HDRP_PRESENT
void SetupPasses(CustomPassVolume customPassVolume)
{
customPassVolume.customPasses.Remove(m_SegmentationPass);
customPassVolume.customPasses.Remove(m_SemanticSegmentationPass);
if (produceSegmentationImages || produceObjectCountAnnotations)
customPassVolume.customPasses.Add(m_SegmentationPass);
if (produceSegmentationImages)
customPassVolume.customPasses.Add(m_SemanticSegmentationPass);
}
#endif
void ProduceBoundingBoxesAnnotation(NativeArray<RenderedObjectInfo> renderedObjectInfos, List<LabelEntry> labelingConfigurations, int frameCount)
{
using (s_BoundingBoxCallback.Auto())
{
var findResult = FindAsyncCaptureInfo(frameCount);
if (findResult.index == -1)
return;
var asyncCaptureInfo = findResult.asyncCaptureInfo;
var boundingBoxAsyncAnnotation = asyncCaptureInfo.BoundingBoxAsyncMetric;
if (!boundingBoxAsyncAnnotation.IsValid)
return;
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 (!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,
};
}
boundingBoxAsyncAnnotation.ReportValues(m_BoundingBoxValues);
}
}
/// <summary>
/// Returns the class ID for the given instance ID resolved by <see cref="LabelingConfiguration"/>. Only valid when bounding boxes are being computed.
/// </summary>
/// <param name="instanceId">The instanceId of the object</param>
/// <param name="labelEntry">When this method returns, contains the LabelEntry associated with the given instanceId if one exists. default otherwise.</param>
/// <returns>True if a valid LabelEntry was found for the given instanceId.</returns>
/// <exception cref="InvalidOperationException">Thrown when <see cref="produceBoundingBoxAnnotations"/> was not true on Start.</exception>
public bool TryGetLabelEntryFromInstanceId(int instanceId, out LabelEntry labelEntry)
{
if (m_RenderedObjectInfoGenerator == null)
throw new InvalidOperationException($"{nameof(TryGetLabelEntryFromInstanceId)} can only be used when bounding box capture is enabled");
return m_RenderedObjectInfoGenerator.TryGetLabelEntryFromInstanceId(instanceId, out labelEntry);
}
void OnObjectCountsReceived(NativeSlice<uint> counts, IReadOnlyList<LabelEntry> entries, int frameCount)
{
using (s_ClassCountCallback.Auto())
{
classCountsReceived?.Invoke(counts, entries, frameCount);
var findResult = FindAsyncCaptureInfo(frameCount);
if (findResult.index == -1)
return;
var asyncCaptureInfo = findResult.asyncCaptureInfo;
var classCountAsyncMetric = asyncCaptureInfo.ClassCountAsyncMetric;
if (!classCountAsyncMetric.IsValid)
return;
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);
}
}
(int index, AsyncCaptureInfo asyncCaptureInfo) FindAsyncCaptureInfo(int frameCount)
{
for (var i = 0; i < m_AsyncCaptureInfos.Count; i++)
{
var captureInfo = m_AsyncCaptureInfos[i];
if (captureInfo.FrameCount == frameCount)
{
return (i, captureInfo);
}
}
return (-1, default);
}
// Update is called once per frame
void Update()
{

var cam = GetComponent<Camera>();
cam.enabled = SensorHandle.ShouldCaptureThisFrame;
m_AsyncCaptureInfos.RemoveSwapBack(i =>
!i.SegmentationAsyncAnnotation.IsPending &&
!i.BoundingBoxAsyncMetric.IsPending &&
!i.RenderedObjectInfoAsyncMetric.IsPending &&
!i.ClassCountAsyncMetric.IsPending);
}
void ReportAsyncAnnotations()
{
if (produceSegmentationImages || produceObjectCountAnnotations || produceBoundingBoxAnnotations || produceRenderedObjectInfoMetric)
foreach (var labeler in m_Labelers)
var captureInfo = new AsyncCaptureInfo()
{
FrameCount = Time.frameCount
};
if (produceSegmentationImages)
captureInfo.SegmentationAsyncAnnotation = SensorHandle.ReportAnnotationAsync(m_SegmentationAnnotationDefinition);
if (produceObjectCountAnnotations)
captureInfo.ClassCountAsyncMetric = SensorHandle.ReportMetricAsync(m_ObjectCountMetricDefinition);
if (produceBoundingBoxAnnotations)
captureInfo.BoundingBoxAsyncMetric = SensorHandle.ReportAnnotationAsync(m_BoundingBoxAnnotationDefinition);
if (!labeler.enabled)
continue;
if (produceRenderedObjectInfoMetric)
captureInfo.RenderedObjectInfoAsyncMetric = SensorHandle.ReportMetricAsync(m_RenderedObjectInfoMetricDefinition);
if (!labeler.isInitialized)
labeler.Init(this);
m_AsyncCaptureInfos.Add(captureInfo);
labeler.InternalOnUpdate();
void OnValidate()
{
if (m_Labelers == null)
m_Labelers = new List<CameraLabeler>();
}
void CaptureRgbData(Camera cam)
{
Profiler.BeginSample("CaptureDataFromLastFrame");

var dxRootPath = Path.Combine(RgbDirectory, $"{s_RgbFilePrefix}{Time.frameCount}.png");
SensorHandle.ReportCapture(dxRootPath, SensorSpatialData.FromGameObjects(m_EgoMarker == null ? null : m_EgoMarker.gameObject, gameObject), m_PersistentSensorData.Select(kvp => (kvp.Key, kvp.Value)).ToArray());
Func<AsyncRequest<CaptureCamera.CaptureState>, AsyncRequest.Result> colorFunctor = null;
Func<AsyncRequest<CaptureCamera.CaptureState>, AsyncRequest.Result> colorFunctor;
var width = cam.pixelWidth;
var height = cam.pixelHeight;
var flipY = ShouldFlipY(cam);

void OnSimulationEnding()
{
m_ClassLabelingTextureReader?.WaitForAllImages();
m_ClassLabelingTextureReader?.Dispose();
m_ClassLabelingTextureReader = null;
m_SegmentationReader?.WaitForAllImages();
m_SegmentationReader?.Dispose();
m_SegmentationReader = null;
RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
CleanUpInstanceSegmentation();
foreach (var labeler in m_Labelers)
{
if (labeler.isInitialized)
labeler.InternalCleanup();
}
}
void OnBeginCameraRendering(ScriptableRenderContext _, Camera cam)

if (!SensorHandle.ShouldCaptureThisFrame)
return;
ReportAsyncAnnotations();
foreach (var labeler in m_Labelers)
{
if (!labeler.enabled)
continue;
if (!labeler.isInitialized)
labeler.Init(this);
labeler.InternalOnBeginRendering();
}
RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
m_ClassLabelingTextureReader?.Dispose();
m_ClassLabelingTextureReader = null;
if (segmentationTexture != null)
segmentationTexture.Release();
segmentationTexture = null;
if (labelingTexture != null)
labelingTexture.Release();
if (m_RenderedObjectInfoGenerator != null)
{
World.DefaultGameObjectInjectionWorld?.GetExistingSystem<GroundTruthLabelSetupSystem>()?.Deactivate(m_RenderedObjectInfoGenerator);
m_RenderedObjectInfoGenerator?.Dispose();
m_RenderedObjectInfoGenerator = null;
}
}
labelingTexture = null;
}
/// <summary>
/// The <see cref="CameraLabeler"/> instances which will be run for this PerceptionCamera.
/// </summary>
public IReadOnlyList<CameraLabeler> labelers => m_Labelers;
/// <summary>
/// Add the given <see cref="CameraLabeler"/> to the PerceptionCamera. It will be set up and executed by this
/// PerceptionCamera each frame it captures data.
/// </summary>
/// <param name="cameraLabeler">The labeler to add to this PerceptionCamera</param>
public void AddLabeler(CameraLabeler cameraLabeler) => m_Labelers.Add(cameraLabeler);
void OnSemanticSegmentationImageRead(int frameCount, NativeArray<short> data)
/// <summary>
/// Removes the given <see cref="CameraLabeler"/> from the list of labelers under this PerceptionCamera, if it
/// is in the list. The labeler is cleaned up in the process. Labelers removed from a PerceptionCamera should
/// not be used again.
/// </summary>
/// <param name="cameraLabeler"></param>
/// <returns></returns>
public bool RemoveLabeler(CameraLabeler cameraLabeler)
var findResult = FindAsyncCaptureInfo(frameCount);
var asyncCaptureInfo = findResult.asyncCaptureInfo;
var dxLocalPath = Path.Combine(k_SemanticSegmentationDirectory, k_SegmentationFilePrefix) + frameCount + ".png";
var path = Path.Combine(Manager.Instance.GetDirectoryFor(k_SemanticSegmentationDirectory), k_SegmentationFilePrefix) + frameCount + ".png";
var annotation = asyncCaptureInfo.SegmentationAsyncAnnotation;
if (!annotation.IsValid)
return;
if (m_Labelers.Remove(cameraLabeler))
{
if (cameraLabeler.isInitialized)
cameraLabeler.InternalCleanup();
annotation.ReportFile(dxLocalPath);
var asyncRequest = Manager.Instance.CreateRequest<AsyncRequest<AsyncSemanticSegmentationWrite>>();
asyncRequest.data = new AsyncSemanticSegmentationWrite()
{
dataArray = data.ToArray(),
width = labelingTexture.width,
height = labelingTexture.height,
path = path
};
asyncRequest.Start((r) =>
{
Profiler.EndSample();
Profiler.BeginSample("Encode");
var pngBytes = ImageConversion.EncodeArrayToPNG(r.data.dataArray, 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();
return AsyncRequest.Result.Completed;
});
return true;
}
return false;
}
}
}

13
com.unity.perception/Runtime/GroundTruth/RenderedObjectInfo.cs


/// <summary>
/// The instanceId of the rendered object.
/// </summary>
public int instanceId;
/// <summary>
/// The labelId of the object resolved by a <see cref="LabelingConfiguration"/>
/// </summary>
public int labelId;
public uint instanceId;
/// <summary>
/// The bounding box of the object in pixel coordinates.
/// </summary>

/// <inheritdoc />
public override string ToString()
{
return $"{nameof(instanceId)}: {instanceId}, {nameof(labelId)}: {labelId}, {nameof(boundingBox)}: {boundingBox}, {nameof(pixelCount)}: {pixelCount}";
return $"{nameof(instanceId)}: {instanceId}, {nameof(boundingBox)}: {boundingBox}, {nameof(pixelCount)}: {pixelCount}";
return instanceId == other.instanceId && labelId == other.labelId && boundingBox.Equals(other.boundingBox) && pixelCount == other.pixelCount;
return instanceId == other.instanceId && boundingBox.Equals(other.boundingBox) && pixelCount == other.pixelCount;
}
/// <inheritdoc />

{
unchecked
{
var hashCode = instanceId;
hashCode = (hashCode * 397) ^ labelId;
var hashCode = (int)instanceId;
hashCode = (hashCode * 397) ^ boundingBox.GetHashCode();
hashCode = (hashCode * 397) ^ pixelCount;
return hashCode;

77
com.unity.perception/Runtime/GroundTruth/RenderedObjectInfoGenerator.cs


using Unity.Jobs;
using Unity.Mathematics;
using Unity.Profiling;
using UnityEngine.UIElements;
namespace UnityEngine.Perception.GroundTruth
{

public class RenderedObjectInfoGenerator : IGroundTruthGenerator, IDisposable
public class RenderedObjectInfoGenerator
const int k_StartingObjectCount = 1 << 8;
public int instanceId;
public uint instanceId;
public int row;
public int left;
public int right;

for (var row = 0; row < rows; row++)
{
var rowSlice = new NativeSlice<uint>(segmentationImageData, width * row, width);
instanceId = -1,
instanceId = 0,
row = row + rowStart
};
for (var i = 0; i < rowSlice.Length; i++)

currentBB = new Object1DSpan
{
instanceId = (int)value,
instanceId = value,
left = i,
row = row + rowStart
};

}
}
NativeList<int> m_InstanceIdToLabelEntryIndexLookup;
LabelingConfiguration m_LabelingConfiguration;
// ReSharper disable once InvalidXmlDocComment
/// <summary>
/// Create a new CpuRenderedObjectInfoPass with the given LabelingConfiguration.
/// </summary>
/// <param name="labelingConfiguration">The LabelingConfiguration to use to determine labelId. Should match the
/// one used by the <seealso cref="InstanceSegmentationUrpPass"/> generating the input image. See <see cref="Compute"/></param>
public RenderedObjectInfoGenerator(LabelingConfiguration labelingConfiguration)
{
m_LabelingConfiguration = labelingConfiguration;
m_InstanceIdToLabelEntryIndexLookup = new NativeList<int>(k_StartingObjectCount, Allocator.Persistent);
}
/// <inheritdoc/>
public void SetupMaterialProperties(MaterialPropertyBlock mpb, Renderer renderer, Labeling labeling, uint instanceId)
{
if (m_LabelingConfiguration.TryGetMatchingConfigurationEntry(labeling, out _, out var index))
{
if (m_InstanceIdToLabelEntryIndexLookup.Length <= instanceId)
{
m_InstanceIdToLabelEntryIndexLookup.Resize((int)instanceId + 1, NativeArrayOptions.ClearMemory);
}
m_InstanceIdToLabelEntryIndexLookup[(int)instanceId] = index;
}
}
// ReSharper disable once InvalidXmlDocComment
/// <summary>

/// <param name="stride">Stride of the image data. Should be equal to the width of the image.</param>
/// <param name="boundingBoxOrigin">Whether bounding boxes should be top-left or bottom-right-based.</param>
/// <param name="renderedObjectInfos">When this method returns, filled with RenderedObjectInfo entries for each object visible in the frame.</param>
/// <param name="perLabelEntryObjectCount">When the method returns, filled with a NativeArray with the count of objects for each entry in <see cref="LabelingConfiguration.LabelEntries"/> in the LabelingConfiguration passed into the constructor.</param>
public void Compute(NativeArray<uint> instanceSegmentationRawData, int stride, BoundingBoxOrigin boundingBoxOrigin, out NativeArray<RenderedObjectInfo> renderedObjectInfos, out NativeArray<uint> perLabelEntryObjectCount, Allocator allocator)
public void Compute(NativeArray<uint> instanceSegmentationRawData, int stride, BoundingBoxOrigin boundingBoxOrigin, out NativeArray<RenderedObjectInfo> renderedObjectInfos, Allocator allocator)
{
const int jobCount = 24;
var height = instanceSegmentationRawData.Length / stride;

JobHandle.CompleteAll(handles);
}
perLabelEntryObjectCount = new NativeArray<uint>(m_LabelingConfiguration.LabelEntries.Count, allocator);
var boundingBoxMap = new NativeHashMap<int, RenderedObjectInfo>(100, Allocator.Temp);
var boundingBoxMap = new NativeHashMap<uint, RenderedObjectInfo>(100, Allocator.Temp);
using (s_LabelMerge.Auto())
{
foreach (var boundingBoxList in jobBoundingBoxLists)

for (var i = 0; i < keyValueArrays.Keys.Length; i++)
{
var instanceId = keyValueArrays.Keys[i];
if (m_InstanceIdToLabelEntryIndexLookup.Length <= instanceId)
continue;
var labelIndex = m_InstanceIdToLabelEntryIndexLookup[instanceId];
var labelId = m_LabelingConfiguration.LabelEntries[labelIndex].id;
perLabelEntryObjectCount[labelIndex]++;
var renderedObjectInfo = keyValueArrays.Values[i];
var boundingBox = renderedObjectInfo.boundingBox;
if (boundingBoxOrigin == BoundingBoxOrigin.TopLeft)

renderedObjectInfos[i] = new RenderedObjectInfo
{
instanceId = instanceId,
labelId = labelId,
boundingBox = boundingBox,
pixelCount = renderedObjectInfo.pixelCount
};

}
handles.Dispose();
}
/// <summary>
/// Attempts to find the label id for the given instance id using the LabelingConfiguration passed into the constructor.
/// </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(int instanceId, out LabelEntry labelEntry)
{
labelEntry = default;
if (m_InstanceIdToLabelEntryIndexLookup.Length <= instanceId)
return false;
var labelEntryIndex = m_InstanceIdToLabelEntryIndexLookup[instanceId];
labelEntry = m_LabelingConfiguration.LabelEntries[labelEntryIndex];
return true;
}
/// <inheritdoc />
public void Dispose()
{
m_InstanceIdToLabelEntryIndexLookup.Dispose();
}
}
}

8
com.unity.perception/Runtime/GroundTruth/Resources/SemanticSegmentation.shader


{
Properties
{
[PerObjectData] LabelingId("Labeling Id", int) = 0
[PerObjectData] LabelingId("Labeling Id", Color) = (1,1,1,1)
}
HLSLINCLUDE

#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl"
uint LabelingId;
float4 LabelingId;
struct appdata
{

float4 vertex : SV_POSITION;
};
uint _SegmentationId;
v2f vert (appdata v)
{
v2f o;

fixed4 frag (v2f i) : SV_Target
{
return float4(UnpackUIntToFloat((uint)LabelingId, 0, 8), UnpackUIntToFloat((uint)LabelingId, 8, 8), 0, 1.0);
return LabelingId;
}
ENDCG

20
com.unity.perception/Runtime/GroundTruth/SemanticSegmentationCrossPipelinePass.cs


const string k_ShaderName = "Perception/SemanticSegmentation";
static readonly int k_LabelingId = Shader.PropertyToID("LabelingId");
LabelingConfiguration m_LabelingConfiguration;
static int s_LastFrameExecuted = -1;
SemanticSegmentationLabelConfig m_LabelConfig;
//Serialize the shader so that the shader asset is included in player builds when the SemanticSegmentationPass is used.
//Currently commented out and shaders moved to Resources folder due to serialization crashes when it is enabled.

Material m_OverrideMaterial;
public SemanticSegmentationCrossPipelinePass(Camera targetCamera, LabelingConfiguration labelingConfiguration) : base(targetCamera)
public SemanticSegmentationCrossPipelinePass(Camera targetCamera, SemanticSegmentationLabelConfig labelConfig) : base(targetCamera)
this.m_LabelingConfiguration = labelingConfiguration;
this.m_LabelConfig = labelConfig;
}
public override void Setup()

protected override void ExecutePass(ScriptableRenderContext renderContext, CommandBuffer cmd, Camera camera, CullingResults cullingResult)
{
if (s_LastFrameExecuted == Time.frameCount)
{
Debug.LogError("Semantic segmentation was run twice in the same frame. Multiple semantic segmentations are not currently supported.");
}
s_LastFrameExecuted = Time.frameCount;
var renderList = CreateRendererListDesc(camera, cullingResult, "FirstPass", 0, m_OverrideMaterial, -1);
cmd.ClearRenderTarget(true, true, Color.clear);
DrawRendererList(renderContext, cmd, RendererList.Create(renderList));

{
var entry = new LabelEntry();
foreach (var l in m_LabelingConfiguration.LabelEntries)
var entry = new SemanticSegmentationLabelEntry();
foreach (var l in m_LabelConfig.labelEntries)
{
if (labeling.labels.Contains(l.label))
{

}
//Set the labeling ID so that it can be accessed in ClassSemanticSegmentationPass.shader
mpb.SetInt(k_LabelingId, entry.value);
mpb.SetColor(k_LabelingId, entry.color);
}
}
}

8
com.unity.perception/Runtime/GroundTruth/SemanticSegmentationPass.cs


public class SemanticSegmentationPass : CustomPass
{
public RenderTexture targetTexture;
public LabelingConfiguration labelingConfiguration;
public SemanticSegmentationLabelConfig semanticSegmentationLabelConfig;
public SemanticSegmentationPass(Camera targetCamera, RenderTexture targetTexture, LabelingConfiguration labelingConfiguration)
public SemanticSegmentationPass(Camera targetCamera, RenderTexture targetTexture, SemanticSegmentationLabelConfig semanticSegmentationLabelConfig)
this.labelingConfiguration = labelingConfiguration;
this.semanticSegmentationLabelConfig = semanticSegmentationLabelConfig;
this.targetCamera = targetCamera;
EnsureInit();
}

if (m_SemanticSegmentationCrossPipelinePass == null)
{
m_SemanticSegmentationCrossPipelinePass = new SemanticSegmentationCrossPipelinePass(targetCamera, labelingConfiguration);
m_SemanticSegmentationCrossPipelinePass = new SemanticSegmentationCrossPipelinePass(targetCamera, semanticSegmentationLabelConfig);
m_SemanticSegmentationCrossPipelinePass.EnsureActivated();
}
}

3
com.unity.perception/Runtime/GroundTruth/SimulationState.cs


public bool ShouldCaptureThisFrame(SensorHandle sensorHandle)
{
if (!m_Sensors.ContainsKey(sensorHandle))
return false;
var data = m_Sensors[sensorHandle];
if (data.lastCaptureFrameCount == Time.frameCount)
return true;

143
com.unity.perception/Tests/Editor/PerceptionCameraEditorTests.cs


using UnityEngine.Perception.GroundTruth;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
#if MOQ_PRESENT
using Moq;
using Moq.Protected;
#endif
namespace EditorTests
{

[UnityTest]
public IEnumerator EditorPause_DoesNotLogErrors()
{
int sceneCount = SceneManager.sceneCount;
for (int i = sceneCount - 1; i >= 0; i--)
ResetScene();
SetupCamera(p =>
EditorSceneManager.CloseScene(SceneManager.GetSceneAt(i), true);
}
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
SetupCamera(ScriptableObject.CreateInstance<LabelingConfiguration>());
var idLabelConfig = ScriptableObject.CreateInstance<IdLabelConfig>();
p.captureRgbImages = true;
p.AddLabeler(new BoundingBox2DLabeler(idLabelConfig));
p.AddLabeler(new RenderedObjectInfoLabeler(idLabelConfig));
});
yield return new EnterPlayMode();
var expectedFirstFrame = Time.frameCount;
yield return null;

yield return new ExitPlayMode();
}
static void SetupCamera(LabelingConfiguration labelingConfiguration)
static void ResetScene()
{
int sceneCount = SceneManager.sceneCount;
for (int i = sceneCount - 1; i >= 0; i--)
{
EditorSceneManager.CloseScene(SceneManager.GetSceneAt(i), true);
}
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
}
#if MOQ_PRESENT
[UnityTest]
public IEnumerator AddLabelerAfterStart_ShouldInitialize()
{
ResetScene();
yield return new EnterPlayMode();
var camera = SetupCamera(null);
var mockLabeler = new Mock<CameraLabeler>();
yield return null;
camera.GetComponent<PerceptionCamera>().AddLabeler(mockLabeler.Object);
yield return null;
mockLabeler.Protected().Verify("Setup", Times.Once());
yield return new ExitPlayMode();
}
[UnityTest]
public IEnumerator Labeler_ShouldSetupAndUpdateAndOnBeginRenderingInFirstFrame()
{
ResetScene();
yield return new EnterPlayMode();
var mockLabeler = new Mock<CameraLabeler>();
var camera = SetupCamera(null);
camera.GetComponent<PerceptionCamera>().AddLabeler(mockLabeler.Object);
yield return null;
mockLabeler.Protected().Verify("Setup", Times.Once());
mockLabeler.Protected().Verify("OnUpdate", Times.Once());
mockLabeler.Protected().Verify("OnBeginRendering", Times.Once());
yield return new ExitPlayMode();
}
[UnityTest]
public IEnumerator AddAndRemoveLabelerInSameFrame_ShouldDoNothing()
{
ResetScene();
yield return new EnterPlayMode();
var mockLabeler = new Mock<CameraLabeler>();
var cameraObject = SetupCamera(null);
var perceptionCamera = cameraObject.GetComponent<PerceptionCamera>();
perceptionCamera.AddLabeler(mockLabeler.Object);
perceptionCamera.RemoveLabeler(mockLabeler.Object);
yield return null;
mockLabeler.Protected().Verify("Setup", Times.Never());
mockLabeler.Protected().Verify("OnUpdate", Times.Never());
mockLabeler.Protected().Verify("OnBeginRendering", Times.Never());
mockLabeler.Protected().Verify("Cleanup", Times.Never());
yield return new ExitPlayMode();
}
[UnityTest]
public IEnumerator RemoveLabeler_ShouldCallCleanup()
{
ResetScene();
yield return new EnterPlayMode();
var mockLabeler = new Mock<CameraLabeler>();
var cameraObject = SetupCamera(null);
var perceptionCamera = cameraObject.GetComponent<PerceptionCamera>();
perceptionCamera.AddLabeler(mockLabeler.Object);
yield return null;
Assert.IsTrue(perceptionCamera.RemoveLabeler(mockLabeler.Object));
mockLabeler.Protected().Verify("Cleanup", Times.Once());
yield return new ExitPlayMode();
}
[UnityTest]
public IEnumerator RemoveLabeler_OnLabelerNotAdded_ShouldNotCallCleanup()
{
ResetScene();
yield return new EnterPlayMode();
var mockLabeler = new Mock<CameraLabeler>();
var cameraObject = SetupCamera(null);
var perceptionCamera = cameraObject.GetComponent<PerceptionCamera>();
yield return null;
Assert.IsFalse(perceptionCamera.RemoveLabeler(mockLabeler.Object));
mockLabeler.Protected().Verify("Cleanup", Times.Never());
yield return new ExitPlayMode();
}
[UnityTest]
public IEnumerator DestroyPerceptionCameraObject_ShouldCallCleanup()
{
ResetScene();
yield return new EnterPlayMode();
var mockLabeler = new Mock<CameraLabeler>();
var cameraObject = SetupCamera(null);
var perceptionCamera = cameraObject.GetComponent<PerceptionCamera>();
perceptionCamera.AddLabeler(mockLabeler.Object);
yield return null;
UnityEngine.Object.DestroyImmediate(cameraObject);
mockLabeler.Protected().Verify("Cleanup", Times.Once());
yield return new ExitPlayMode();
}
[UnityTest]
public IEnumerator SetupThrows_ShouldDisable()
{
ResetScene();
yield return new EnterPlayMode();
var mockLabeler = new Mock<CameraLabeler>();
mockLabeler.Protected().Setup("Setup").Throws<InvalidOperationException>();
var labeler = mockLabeler.Object;
var camera = SetupCamera(null);
camera.GetComponent<PerceptionCamera>().AddLabeler(labeler);
LogAssert.Expect(LogType.Exception, "InvalidOperationException: Operation is not valid due to the current state of the object.");
yield return null;
mockLabeler.Protected().Verify("Setup", Times.Once());
mockLabeler.Protected().Verify("OnUpdate", Times.Never());
mockLabeler.Protected().Verify("OnBeginRendering", Times.Never());
Assert.IsFalse(labeler.enabled);
yield return new ExitPlayMode();
}
#endif
static GameObject SetupCamera(Action<PerceptionCamera> initPerceptionCameraCallback)
{
var cameraObject = new GameObject();
cameraObject.SetActive(false);

#endif
var perceptionCamera = cameraObject.AddComponent<PerceptionCamera>();
perceptionCamera.LabelingConfiguration = labelingConfiguration;
perceptionCamera.captureRgbImages = true;
perceptionCamera.produceBoundingBoxAnnotations = true;
perceptionCamera.produceObjectCountAnnotations = true;
initPerceptionCameraCallback?.Invoke(perceptionCamera);
return cameraObject;
}
}
}

8
com.unity.perception/Tests/Editor/Unity.Perception.Editor.Tests.asmdef


"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
"nunit.framework.dll",
"Moq.dll"
],
"autoReferenced": false,
"defineConstraints": [

"name": "com.unity.render-pipelines.high-definition",
"expression": "",
"define": "HDRP_PRESENT"
},
{
"name": "nuget.moq",
"expression": "",
"define": "MOQ_PRESENT"
}
],
"noEngineReferences": false

50
com.unity.perception/Tests/Runtime/GroundTruthTests/PerceptionCameraIntegrationTests.cs


using UnityEngine.Perception.GroundTruth;
using UnityEngine.TestTools;
#if MOQ_PRESENT
using Moq;
#endif
namespace GroundTruthTests
{
#if HDRP_PRESENT

""height"": {Screen.height / 2:F1}
}}";
var labelingConfiguration = CreateLabelingConfiguration();
SetupCamera(labelingConfiguration, pc =>
SetupCamera(pc =>
pc.produceBoundingBoxAnnotations = true;
pc.AddLabeler(new BoundingBox2DLabeler(labelingConfiguration));
});
var plane = TestHelper.CreateLabeledPlane();

[UnityTest]
public IEnumerator EnableSemanticSegmentation_GeneratesCorrectDataset()
{
var labelingConfiguration = CreateLabelingConfiguration();
SetupCamera(labelingConfiguration, pc => pc.produceSegmentationImages = true);
SetupCamera(pc =>
{
pc.AddLabeler(new SemanticSegmentationLabeler(CreateSemanticSegmentationLabelConfig()));
});
string expectedImageFilename = $"segmentation_{Time.frameCount}.png";

StringAssert.Contains(imagePath, capturesJson);
}
static LabelingConfiguration CreateLabelingConfiguration()
static IdLabelConfig CreateLabelingConfiguration()
var labelingConfiguration = ScriptableObject.CreateInstance<LabelingConfiguration>();
var labelingConfiguration = ScriptableObject.CreateInstance<IdLabelConfig>();
labelingConfiguration.LabelEntries = new List<LabelEntry>
labelingConfiguration.Init(new List<IdLabelEntry>
new LabelEntry
new IdLabelEntry
label = label
}
});
return labelingConfiguration;
}
static SemanticSegmentationLabelConfig CreateSemanticSegmentationLabelConfig()
{
var label = "label";
var labelingConfiguration = ScriptableObject.CreateInstance<SemanticSegmentationLabelConfig>();
labelingConfiguration.Init(new List<SemanticSegmentationLabelEntry>
{
new SemanticSegmentationLabelEntry()
{
value = 500
color = Color.blue
};
});
GameObject SetupCamera(LabelingConfiguration labelingConfiguration, Action<PerceptionCamera> initPerceptionCamera)
void SetupCamera(Action<PerceptionCamera> initPerceptionCamera)
{
var cameraObject = new GameObject();
cameraObject.SetActive(false);

var perceptionCamera = cameraObject.AddComponent<PerceptionCamera>();
perceptionCamera.produceSegmentationImages = false;
perceptionCamera.produceRenderedObjectInfoMetric = false;
perceptionCamera.produceBoundingBoxAnnotations = false;
perceptionCamera.produceObjectCountAnnotations = false;
perceptionCamera.LabelingConfiguration = labelingConfiguration;
initPerceptionCamera(perceptionCamera);
initPerceptionCamera?.Invoke(perceptionCamera);
return cameraObject;
}
}
}

128
com.unity.perception/Tests/Runtime/GroundTruthTests/SegmentationGroundTruthTests.cs


[UnityPlatform(exclude = new[] {RuntimePlatform.LinuxEditor, RuntimePlatform.LinuxPlayer})]
public class SegmentationPassTests : GroundTruthTestBase
{
static readonly Color32 k_SemanticPixelValue = Color.blue;
public enum SegmentationKind
{
Instance,
Semantic
}
public IEnumerator SegmentationPassTestsWithEnumeratorPasses([Values(false, true)] bool useSkinnedMeshRenderer)
public IEnumerator SegmentationPassTestsWithEnumeratorPasses(
[Values(false, true)] bool useSkinnedMeshRenderer,
[Values(SegmentationKind.Instance, SegmentationKind.Semantic)] SegmentationKind segmentationKind)
Action<int, NativeArray<uint>> onSegmentationImageReceived = (frameCount, data) =>
GameObject cameraObject = null;
object expectedPixelValue;
void OnSegmentationImageReceived<T>(int frameCount, NativeArray<T> data, RenderTexture tex) where T : struct
if (frameStart == null || frameStart > frameCount)
return;
if (frameStart == null || frameStart > frameCount) return;
CollectionAssert.AreEqual(Enumerable.Repeat(1, data.Length), data);
};
CollectionAssert.AreEqual(Enumerable.Repeat(expectedPixelValue, data.Length), data);
}
var cameraObject = SetupCamera(onSegmentationImageReceived);
switch (segmentationKind)
{
case SegmentationKind.Instance:
expectedPixelValue = 1;
cameraObject = SetupCameraInstanceSegmentation(OnSegmentationImageReceived);
break;
case SegmentationKind.Semantic:
expectedPixelValue = k_SemanticPixelValue;
cameraObject = SetupCameraSemanticSegmentation(a => OnSegmentationImageReceived(a.frameCount, a.data, a.sourceTexture));
break;
}
//
// // Arbitrary wait for 5 frames for shaders to load. Workaround for issue with Shader.WarmupAllShaders()
// for (int i=0 ; i<5 ; ++i)

var skinnedMeshRenderer = planeObject.AddComponent<SkinnedMeshRenderer>();
skinnedMeshRenderer.sharedMesh = meshFilter.sharedMesh;
skinnedMeshRenderer.material = meshRenderer.material;
planeObject.AddComponent<Labeling>();
var labeling = planeObject.AddComponent<Labeling>();
labeling.labels.Add("label");
AddTestObjectForCleanup(planeObject);
yield return null;

}
[UnityTest]
public IEnumerator SegmentationPassProducesCorrectValuesEachFrame()
public IEnumerator SegmentationPassProducesCorrectValuesEachFrame(
[Values(SegmentationKind.Instance, SegmentationKind.Semantic)] SegmentationKind segmentationKind)
Dictionary<int, int> expectedLabelAtFrame = null;
Dictionary<int, object> expectedLabelAtFrame = null;
Action<int, NativeArray<uint>> onSegmentationImageReceived = (frameCount, data) =>
void OnSegmentationImageReceived<T>(int frameCount, NativeArray<T> data, RenderTexture tex) where T : struct
if (expectedLabelAtFrame == null || !expectedLabelAtFrame.ContainsKey(frameCount))
return;
if (expectedLabelAtFrame == null || !expectedLabelAtFrame.ContainsKey(frameCount)) return;
timesSegmentationImageReceived++;

{
CollectionAssert.AreEqual(Enumerable.Repeat(expectedLabelAtFrame[frameCount], data.Length), data);
}
// ReSharper disable once RedundantCatchClause
catch (Exception)
{

}
};
}
var cameraObject = SetupCamera(onSegmentationImageReceived);
var cameraObject = segmentationKind == SegmentationKind.Instance ?
SetupCameraInstanceSegmentation(OnSegmentationImageReceived<uint>) :
SetupCameraSemanticSegmentation((a) => OnSegmentationImageReceived<Color32>(a.frameCount, a.data, a.sourceTexture));
expectedLabelAtFrame = new Dictionary<int, int>
object expectedPixelValue = segmentationKind == SegmentationKind.Instance ? (object) 1 : k_SemanticPixelValue;
expectedLabelAtFrame = new Dictionary<int, object>
{Time.frameCount , 1},
{Time.frameCount + 1, 1},
{Time.frameCount + 2, 1}
{Time.frameCount , expectedPixelValue},
{Time.frameCount + 1, expectedPixelValue},
{Time.frameCount + 2, expectedPixelValue}
};
GameObject planeObject;

Assert.AreEqual(3, timesSegmentationImageReceived);
}
GameObject SetupCamera(Action<int, NativeArray<uint>> onSegmentationImageReceived)
GameObject SetupCameraInstanceSegmentation(Action<int, NativeArray<uint>, RenderTexture> onSegmentationImageReceived)
{
var cameraObject = SetupCamera(out var perceptionCamera);
perceptionCamera.InstanceSegmentationImageReadback += onSegmentationImageReceived;
cameraObject.SetActive(true);
return cameraObject;
}
GameObject SetupCameraSemanticSegmentation(Action<SemanticSegmentationLabeler.ImageReadbackEventArgs> onSegmentationImageReceived)
{
var cameraObject = SetupCamera(out var perceptionCamera);
var labelConfig = ScriptableObject.CreateInstance<SemanticSegmentationLabelConfig>();
labelConfig.Init(new List<SemanticSegmentationLabelEntry>()
{
new SemanticSegmentationLabelEntry()
{
label = "label",
color = k_SemanticPixelValue
}
});
var semanticSegmentationLabeler = new SemanticSegmentationLabeler(labelConfig);
semanticSegmentationLabeler.imageReadback += onSegmentationImageReceived;
perceptionCamera.AddLabeler(semanticSegmentationLabeler);
cameraObject.SetActive(true);
return cameraObject;
}
GameObject SetupCamera(out PerceptionCamera perceptionCamera)
{
var cameraObject = new GameObject();
cameraObject.SetActive(false);

#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();
instanceSegmentationPass.targetCamera = camera;
instanceSegmentationPass.targetTexture = rt;
customPassVolume.customPasses.Add(instanceSegmentationPass);
instanceSegmentationPass.name = nameof(instanceSegmentationPass);
instanceSegmentationPass.EnsureInit();
var reader = cameraObject.AddComponent<ImageReaderBehaviour>();
reader.source = rt;
reader.cameraSource = camera;
reader.SegmentationImageReceived += onSegmentationImageReceived;
#endif
#if URP_PRESENT
var labelingConfiguration = ScriptableObject.CreateInstance<LabelingConfiguration>();
var perceptionCamera = cameraObject.AddComponent<PerceptionCamera>();
perceptionCamera.LabelingConfiguration = labelingConfiguration;
perceptionCamera = cameraObject.AddComponent<PerceptionCamera>();
perceptionCamera.produceBoundingBoxAnnotations = false;
perceptionCamera.produceObjectCountAnnotations = true;
perceptionCamera.segmentationImageReceived += onSegmentationImageReceived;
#endif
cameraObject.SetActive(true);
return cameraObject;
}
}

2
com.unity.perception/Tests/Runtime/Unity.Perception.Runtime.Tests.asmdef


}
],
"noEngineReferences": false
}
}

2
com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureSensorSchedulingTests.cs.meta


fileFormatVersion: 2
guid: d28b6eb98e988b34b9da6e73fccc09bb
guid: 440ceee0f1833054db2f1a666296971d
MonoImporter:
externalObjects: {}
serializedVersion: 2

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


fileFormatVersion: 2
guid: bad10bec3eccd8e49a9d725b2c30f74c
guid: d0127208de324c00a881af84cdd63da3
MonoImporter:
externalObjects: {}
serializedVersion: 2

2
com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureTests.cs.meta


fileFormatVersion: 2
guid: 0e6829808d75dc849a5c29b6b547c0e1
guid: d18e395d4335b5d4ba0e568736f581c4
MonoImporter:
externalObjects: {}
serializedVersion: 2

23
TestProjects/PerceptionHDRP/Assets/IdLabelConfig.asset


%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

8
TestProjects/PerceptionHDRP/Assets/IdLabelConfig.asset.meta


fileFormatVersion: 2
guid: 034ffd4e09ffb7348b2fe6634259058a
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

21
TestProjects/PerceptionHDRP/Assets/SemanticSegmentationLabelingConfiguration.asset


%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}

8
TestProjects/PerceptionHDRP/Assets/SemanticSegmentationLabelingConfiguration.asset.meta


fileFormatVersion: 2
guid: c140c5aa05dd09e4fadaa26de31b1f39
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

541
TestProjects/PerceptionHDRP/Packages/packages-lock.json


{
"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"
}
}
}
}

2
TestProjects/PerceptionHDRP/PerceptionHDRP.sln.DotSettings


<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">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String></wpf:ResourceDictionary>

23
TestProjects/PerceptionURP/Assets/IdLabelConfig.asset


%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

8
TestProjects/PerceptionURP/Assets/IdLabelConfig.asset.meta


fileFormatVersion: 2
guid: cedcacfb1d9beb34fbbb231166c472fe
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

8
TestProjects/PerceptionURP/Assets/Resources.meta


fileFormatVersion: 2
guid: a9ac6d4ef2846ce4cbb891bbf2650223
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

21
TestProjects/PerceptionURP/Assets/SemanticSegmentationLabelingConfiguration.asset


%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}

8
TestProjects/PerceptionURP/Assets/SemanticSegmentationLabelingConfiguration.asset.meta


fileFormatVersion: 2
guid: c140c5aa05dd09e4fadaa26de31b1f39
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

519
TestProjects/PerceptionURP/Packages/packages-lock.json


{
"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"
}
}
}
}

2
TestProjects/PerceptionURP/PerceptionURP.sln.DotSettings


<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">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String></wpf:ResourceDictionary>

156
com.unity.perception/Editor/GroundTruth/CameraLabelerDrawer.cs


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");
}
}
}

3
com.unity.perception/Editor/GroundTruth/CameraLabelerDrawer.cs.meta


fileFormatVersion: 2
guid: a9aa79de1f2f402aa15ef42f82c3d334
timeCreated: 1593613195

23
com.unity.perception/Editor/GroundTruth/CameraLabelerDrawerAttribute.cs


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;
}
}
}

3
com.unity.perception/Editor/GroundTruth/CameraLabelerDrawerAttribute.cs.meta


fileFormatVersion: 2
guid: b7dfd54d7de84ca6a06e36f0e09de906
timeCreated: 1593613460

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


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++;
}
}
}
}

131
com.unity.perception/Editor/GroundTruth/PerceptionCameraEditor.cs


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;
}
}
}

3
com.unity.perception/Editor/GroundTruth/PerceptionCameraEditor.cs.meta


fileFormatVersion: 2
guid: d6936a1fe4b946a8b72f33ac7c4906e4
timeCreated: 1589372488

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


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();
}
}
}

3
com.unity.perception/Editor/GroundTruth/SemanticSegmentationLabelConfigEditor.cs.meta


fileFormatVersion: 2
guid: e8cb4fead5b34d41884c1c9a77308c72
timeCreated: 1593454492

3
com.unity.perception/Runtime/GroundTruth/Labelers.meta


fileFormatVersion: 2
guid: 021a5e99d6664a188c5c78599587a08c
timeCreated: 1589374593

106
com.unity.perception/Runtime/GroundTruth/Labeling/IdLabelConfig.cs


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();
}
}
}

3
com.unity.perception/Runtime/GroundTruth/Labeling/IdLabelConfig.cs.meta


fileFormatVersion: 2
guid: 2f09f279848e42cea259348b13bce4c5
timeCreated: 1593552475

104
com.unity.perception/Runtime/GroundTruth/Labeling/LabelConfig.cs


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;
}
}
}

3
com.unity.perception/Runtime/GroundTruth/Labeling/LabelConfig.cs.meta


fileFormatVersion: 2
guid: ef6f93cc88964359a505ccc75835fd5a
timeCreated: 1589581072

55
com.unity.perception/Runtime/GroundTruth/Labeling/LabelEntryMatchCache.cs


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();
}
}
}

3
com.unity.perception/Runtime/GroundTruth/Labeling/LabelEntryMatchCache.cs.meta


fileFormatVersion: 2
guid: e736a5078e0a44d69bdc643b3157f670
timeCreated: 1593182152

28
com.unity.perception/Runtime/GroundTruth/Labeling/SemanticSegmentationLabelConfig.cs


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;
}
}

3
com.unity.perception/Runtime/GroundTruth/Labeling/SemanticSegmentationLabelConfig.cs.meta


fileFormatVersion: 2
guid: a9d0176327854820ab53adc46cbec7c1
timeCreated: 1593444493

83
com.unity.perception/Runtime/GroundTruth/PerceptionCamera_InstanceSegmentation.cs


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;
}
}
}

3
com.unity.perception/Runtime/GroundTruth/PerceptionCamera_InstanceSegmentation.cs.meta


fileFormatVersion: 2
guid: ee9eab40cf054cd6ad5da120c84881d7
timeCreated: 1593126137

125
com.unity.perception/Tests/Runtime/GroundTruthTests/ObjectCountLabelerTests.cs


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;
}
}
}

159
com.unity.perception/Tests/Runtime/GroundTruthTests/RenderedObjectInfoTests.cs


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();
}
}
}

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


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);
}
}
}
}

71
com.unity.perception/Runtime/GroundTruth/Labelers/CameraLabeler.cs


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;
}
}
}
}

3
com.unity.perception/Runtime/GroundTruth/Labelers/CameraLabeler.cs.meta


fileFormatVersion: 2
guid: 1f21ae5ed3374b7288ad9bd4ad367c59
timeCreated: 1593188098

138
com.unity.perception/Runtime/GroundTruth/Labelers/ObjectCountLabeler.cs


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);
}
}
}
}

3
com.unity.perception/Runtime/GroundTruth/Labelers/ObjectCountLabeler.cs.meta


fileFormatVersion: 2
guid: 715672f8c1f94106b6e84431e53c6096
timeCreated: 1593183448

125
com.unity.perception/Runtime/GroundTruth/Labelers/RenderedObjectInfoLabeler.cs


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);
}
}
}

11
com.unity.perception/Runtime/GroundTruth/Labelers/RenderedObjectInfoLabeler.cs.meta


fileFormatVersion: 2
guid: c2fcc6ce8ec34a44ae0f1679f25b6fb4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

216
com.unity.perception/Runtime/GroundTruth/Labelers/SemanticSegmentationLabeler.cs


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;
}
}
}

11
com.unity.perception/Runtime/GroundTruth/Labelers/SemanticSegmentationLabeler.cs.meta


fileFormatVersion: 2
guid: 6c08fb5eff78425db5567cf66f9cb3fc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
TestProjects/PerceptionHDRP/Assets/LabelingConfiguration.asset.meta


fileFormatVersion: 2
guid: be3971a848968144e8d07d9136a5bf49
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

26
TestProjects/PerceptionHDRP/Assets/LabelingConfiguration.asset


%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

26
TestProjects/PerceptionURP/Assets/ExampleLabelingConfiguration.asset


%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

8
TestProjects/PerceptionURP/Assets/ExampleLabelingConfiguration.asset.meta


fileFormatVersion: 2
guid: e74234fe725079e4aa7ecd74797ceb79
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

21
com.unity.perception/Editor/GroundTruth/ObjectCountPassEditor.cs


#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

157
com.unity.perception/Editor/GroundTruth/LabelingConfigurationEditor.cs


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++;
}
}
}
}

108
com.unity.perception/Runtime/GroundTruth/Labeling/LabelingConfiguration.cs


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;
}
}
}

181
com.unity.perception/Runtime/GroundTruth/ObjectCountPass.cs


#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

192
com.unity.perception/Tests/Runtime/GroundTruthTests/BoundingBox2DTests.cs


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();
}
}
}

147
com.unity.perception/Tests/Runtime/GroundTruthTests/ObjectCountTests.cs


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;
}
}
}

/com.unity.perception/Editor/GroundTruth/LabelingConfigurationEditor.cs.meta → /com.unity.perception/Editor/GroundTruth/IdLabelConfigEditor.cs.meta

/com.unity.perception/Tests/Runtime/GroundTruthTests/BoundingBox2DTests.cs.meta → /com.unity.perception/Tests/Runtime/GroundTruthTests/RenderedObjectInfoTests.cs.meta

/com.unity.perception/Tests/Runtime/GroundTruthTests/ObjectCountTests.cs.meta → /com.unity.perception/Tests/Runtime/GroundTruthTests/ObjectCountLabelerTests.cs.meta

/com.unity.perception/Editor/GroundTruth/ObjectCountPassEditor.cs.meta → /com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureSensorSchedulingTests.cs.meta

/com.unity.perception/Runtime/GroundTruth/Labeling/LabelingConfiguration.cs.meta → /com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs.meta

/com.unity.perception/Runtime/GroundTruth/ObjectCountPass.cs.meta → /com.unity.perception/Tests/Runtime/GroundTruthTests/DatasetCaptureTests.cs.meta

正在加载...
取消
保存