浏览代码

Splitting out semantic segmentation

/labeler_mock_mb
Jon Hogins 4 年前
当前提交
84c55f28
共有 7 个文件被更改,包括 161 次插入193 次删除
  1. 10
      com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs
  2. 153
      com.unity.perception/Runtime/GroundTruth/Labelers/SemanticSegmentationLabeler.cs
  3. 173
      com.unity.perception/Runtime/GroundTruth/PerceptionCamera.cs
  4. 4
      com.unity.perception/Tests/Editor/PerceptionCameraEditorTests.cs
  5. 1
      com.unity.perception/Tests/Runtime/GroundTruthTests/ObjectCountTests.cs
  6. 8
      com.unity.perception/Tests/Runtime/GroundTruthTests/PerceptionCameraIntegrationTests.cs
  7. 5
      com.unity.perception/Tests/Runtime/GroundTruthTests/SegmentationGroundTruthTests.cs

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


public class BoundingBoxLabeler : MonoBehaviour
{
public string annotationId = "F9F22E05-443F-4602-A422-EBE4EA9B55CB";
public LabelingConfiguration labelingConfiguration;
static ProfilerMarker s_BoundingBoxCallback = new ProfilerMarker("OnBoundingBoxesReceived");

void Start()
{
if (labelingConfiguration == null)
{
Debug.LogError("labelingConfiguration must be assigned.");
this.enabled = false;
return;
}
m_BoundingBoxAnnotationDefinition = SimulationManager.RegisterAnnotationDefinition("bounding box", labelingConfiguration.GetAnnotationSpecification(),
m_BoundingBoxAnnotationDefinition = SimulationManager.RegisterAnnotationDefinition("bounding box", m_RenderedObjectInfoLabeler.labelingConfiguration.GetAnnotationSpecification(),
"Bounding box for each labeled object visible to the sensor", id: new Guid(annotationId));
m_RenderedObjectInfoLabeler.renderedObjectInfosCalculated += OnRenderedObjectInfosCalculated;

153
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 {
[AddComponentMenu("Perception/Labelers/SemanticSegmentationLabeler")]

const string k_SemanticSegmentationDirectory = "SemanticSegmentation";
const string k_SegmentationFilePrefix = "segmentation_";
/// <summary>
/// The LabelingConfiguration to use for determining segmentation pixel values.
/// </summary>
[NonSerialized]
internal RenderTexture semanticSegmentationTexture;
AnnotationDefinition m_SemanticSegmentationAnnotationDefinition;
RenderTextureReader<short> m_SemanticSegmentationTextureReader;
#if HDRP_PRESENT
SemanticSegmentationPass m_SemanticSegmentationPass;
#endif
Dictionary<int, AsyncAnnotation> m_AsyncAnnotations = new Dictionary<int, AsyncAnnotation>();
PerceptionCamera m_PerceptionCamera;
[SuppressMessage("ReSharper", "InconsistentNaming")]
struct SemanticSegmentationSpec
{
[UsedImplicitly]
public int label_id;
[UsedImplicitly]
public string label_name;
[UsedImplicitly]
public int pixel_value;
}
struct AsyncSemanticSegmentationWrite
{
public short[] dataArray;
public int width;
public int height;
public string path;
}
void Start()
{
var myCamera = GetComponent<Camera>();
var width = myCamera.pixelWidth;
var height = myCamera.pixelHeight;
if (labelingConfiguration == null)
{
Debug.LogError("LabelingConfiguration must be set if producing ground truth data");
this.enabled = false;
}
semanticSegmentationTexture = new RenderTexture(new RenderTextureDescriptor(width, height, GraphicsFormat.R8G8B8A8_UNorm, 8));
semanticSegmentationTexture.name = "Labeling";
m_PerceptionCamera = GetComponent<PerceptionCamera>();
#if HDRP_PRESENT
var customPassVolume = this.GetComponent<CustomPassVolume>() ?? gameObject.AddComponent<CustomPassVolume>();
customPassVolume.injectionPoint = CustomPassInjectionPoint.BeforeRendering;
customPassVolume.isGlobal = true;
m_SemanticSegmentationPass = new SemanticSegmentationPass(myCamera, semanticSegmentationTexture, labelingConfiguration)
{
name = "Labeling Pass"
};
customPassVolume.customPasses.Add(m_SemanticSegmentationPass);
#endif
#if URP_PRESENT
m_PerceptionCamera.AddScriptableRenderPass(new SemanticSegmentationUrpPass(myCamera, semanticSegmentationTexture, labelingConfiguration));
#endif
var specs = labelingConfiguration.LabelEntries.Select((l) => new SemanticSegmentationSpec()
{
label_id = l.id,
label_name = l.label,
pixel_value = l.value
}).ToArray();
m_SemanticSegmentationAnnotationDefinition = SimulationManager.RegisterAnnotationDefinition("semantic segmentation", specs, "pixel-wise semantic segmentation label", "PNG");
m_SemanticSegmentationTextureReader = new RenderTextureReader<short>(semanticSegmentationTexture, myCamera,
(frameCount, data, tex) => OnSemanticSegmentationImageRead(frameCount, data));
SimulationManager.SimulationEnding += OnSimulationEnding;
m_PerceptionCamera.BeginRendering += ReportAsyncAnnotations;
}
void OnSemanticSegmentationImageRead(int frameCount, NativeArray<short> data)
{
var dxLocalPath = Path.Combine(k_SemanticSegmentationDirectory, k_SegmentationFilePrefix) + frameCount + ".png";
var path = Path.Combine(Manager.Instance.GetDirectoryFor(k_SemanticSegmentationDirectory), k_SegmentationFilePrefix) + frameCount + ".png";
if (!m_AsyncAnnotations.TryGetValue(frameCount, out var annotation))
return;
annotation.ReportFile(dxLocalPath);
var asyncRequest = Manager.Instance.CreateRequest<AsyncRequest<AsyncSemanticSegmentationWrite>>();
asyncRequest.data = new AsyncSemanticSegmentationWrite()
{
dataArray = data.ToArray(),
width = semanticSegmentationTexture.width,
height = semanticSegmentationTexture.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;
});
}
void ReportAsyncAnnotations()
{
m_AsyncAnnotations[Time.frameCount] = m_PerceptionCamera.SensorHandle.ReportAnnotationAsync(m_SemanticSegmentationAnnotationDefinition);
}
void OnSimulationEnding()
{
m_SemanticSegmentationTextureReader?.WaitForAllImages();
m_SemanticSegmentationTextureReader?.Dispose();
m_SemanticSegmentationTextureReader = null;
}
void OnDisable()
{
SimulationManager.SimulationEnding -= OnSimulationEnding;
m_SemanticSegmentationTextureReader?.Dispose();
m_SemanticSegmentationTextureReader = null;
if (semanticSegmentationTexture != null)
semanticSegmentationTexture.Release();
semanticSegmentationTexture = null;
}
}
}

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


[RequireComponent(typeof(Camera))]
public 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>
/// The LabelingConfiguration to use for segmentation and object count.
/// </summary>
public LabelingConfiguration LabelingConfiguration;
/// <summary>
[NonSerialized]
internal RenderTexture semanticSegmentationTexture;
RenderTextureReader<short> m_SemanticSegmentationTextureReader;
Dictionary<string, object> m_PersistentSensorData = new Dictionary<string, object>();
#if URP_PRESENT

/// The <see cref="SensorHandle"/> associated with this camera. Use this to report additional annotations and metrics at runtime.
/// </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;

List<AsyncCaptureInfo> m_AsyncCaptureInfos = new List<AsyncCaptureInfo>();
#if HDRP_PRESENT
SemanticSegmentationPass m_SemanticSegmentationPass;
#endif
MetricDefinition m_ObjectCountMetricDefinition;
AnnotationDefinition m_BoundingBoxAnnotationDefinition;
AnnotationDefinition m_SemanticSegmentationAnnotationDefinition;
MetricDefinition m_RenderedObjectInfoMetricDefinition;
[SuppressMessage("ReSharper", "InconsistentNaming")]
struct SemanticSegmentationSpec
{
[UsedImplicitly]
public int label_id;
[UsedImplicitly]
public string label_name;
[UsedImplicitly]
public int pixel_value;
}
/// <summary>
/// Add a data object which will be added to the dataset with each capture. Overrides existing sensor data associated with the given key.
/// </summary>

var width = myCamera.pixelWidth;
var height = myCamera.pixelHeight;
if (produceSegmentationImages && LabelingConfiguration == null)
{
Debug.LogError("LabelingConfiguration must be set if producing ground truth data");
produceSegmentationImages = false;
}
semanticSegmentationTexture = new RenderTexture(new RenderTextureDescriptor(width, height, GraphicsFormat.R8G8B8A8_UNorm, 8));
semanticSegmentationTexture.name = "Labeling";
#if HDRP_PRESENT
var customPassVolume = this.GetComponent<CustomPassVolume>() ?? gameObject.AddComponent<CustomPassVolume>();
customPassVolume.injectionPoint = CustomPassInjectionPoint.BeforeRendering;
customPassVolume.isGlobal = true;
m_SemanticSegmentationPass = new SemanticSegmentationPass(myCamera, semanticSegmentationTexture, LabelingConfiguration)
{
name = "Labeling Pass"
};
SetupPasses(customPassVolume);
#endif
#if URP_PRESENT
AddScriptableRenderPass(new SemanticSegmentationUrpPass(myCamera, semanticSegmentationTexture, 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_SemanticSegmentationAnnotationDefinition = SimulationManager.RegisterAnnotationDefinition("semantic segmentation", specs, "pixel-wise semantic segmentation label", "PNG");
m_SemanticSegmentationTextureReader = new RenderTextureReader<short>(semanticSegmentationTexture, myCamera,
(frameCount, data, tex) => OnSemanticSegmentationImageRead(frameCount, data));
}
#if HDRP_PRESENT
void SetupPasses(CustomPassVolume customPassVolume)
{
customPassVolume.customPasses.Remove(m_SemanticSegmentationPass);
if (produceSegmentationImages)
customPassVolume.customPasses.Add(m_SemanticSegmentationPass);
}
#endif
(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)
{
var captureInfo = new AsyncCaptureInfo()
{
FrameCount = Time.frameCount
};
if (produceSegmentationImages)
captureInfo.SegmentationAsyncAnnotation = SensorHandle.ReportAnnotationAsync(m_SemanticSegmentationAnnotationDefinition);
m_AsyncCaptureInfos.Add(captureInfo);
}
}
void CaptureRgbData(Camera cam)

void OnSimulationEnding()
{
m_SemanticSegmentationTextureReader?.WaitForAllImages();
m_SemanticSegmentationTextureReader?.Dispose();
m_SemanticSegmentationTextureReader = null;
RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
}

return;
#endif
BeginRendering?.Invoke();
ReportAsyncAnnotations();
CaptureRgbData(cam);
}

OnSimulationEnding();
m_SemanticSegmentationTextureReader?.Dispose();
m_SemanticSegmentationTextureReader = null;
if (semanticSegmentationTexture != null)
semanticSegmentationTexture.Release();
semanticSegmentationTexture = null;
void OnSemanticSegmentationImageRead(int frameCount, NativeArray<short> data)
{
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;
annotation.ReportFile(dxLocalPath);
var asyncRequest = Manager.Instance.CreateRequest<AsyncRequest<AsyncSemanticSegmentationWrite>>();
asyncRequest.data = new AsyncSemanticSegmentationWrite()
{
dataArray = data.ToArray(),
width = semanticSegmentationTexture.width,
height = semanticSegmentationTexture.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;
});
}
}
}

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


#endif
var perceptionCamera = cameraObject.AddComponent<PerceptionCamera>();
perceptionCamera.LabelingConfiguration = labelingConfiguration;
cameraObject.AddComponent<RenderedObjectInfoLabeler>();
var renderedObjectInfoLabeler = cameraObject.AddComponent<RenderedObjectInfoLabeler>();
renderedObjectInfoLabeler.labelingConfiguration = labelingConfiguration;
cameraObject.SetActive(true);
}

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


camera.orthographicSize = 1;
var perceptionCamera = cameraObject.AddComponent<PerceptionCamera>();
perceptionCamera.LabelingConfiguration = labelingConfiguration;
perceptionCamera.captureRgbImages = false;
cameraObject.AddComponent<InstanceSegmentationLabeler>();
var renderedObjectInfoLabeler = cameraObject.AddComponent<RenderedObjectInfoLabeler>();

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


public IEnumerator EnableSemanticSegmentation_GeneratesCorrectDataset()
{
var labelingConfiguration = CreateLabelingConfiguration();
SetupCamera(labelingConfiguration, pc => pc.produceSegmentationImages = true);
SetupCamera(labelingConfiguration, pc =>
{
var semanticSegmentationLabeler = pc.gameObject.AddComponent<SemanticSegmentationLabeler>();
semanticSegmentationLabeler.labelingConfiguration = labelingConfiguration;
});
string expectedImageFilename = $"segmentation_{Time.frameCount}.png";

camera.orthographicSize = 1;
var perceptionCamera = cameraObject.AddComponent<PerceptionCamera>();
perceptionCamera.produceSegmentationImages = false;
perceptionCamera.LabelingConfiguration = labelingConfiguration;
initPerceptionCamera(perceptionCamera);
cameraObject.SetActive(true);

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


var camera = cameraObject.AddComponent<Camera>();
camera.orthographic = true;
camera.orthographicSize = 1;
var labelingConfiguration = ScriptableObject.CreateInstance<LabelingConfiguration>();
perceptionCamera.LabelingConfiguration = labelingConfiguration;
var renderedObjectInfoLabeler = cameraObject.AddComponent<RenderedObjectInfoLabeler>();
renderedObjectInfoLabeler.labelingConfiguration = labelingConfiguration;
renderedObjectInfoLabeler.produceObjectInfoMetrics = false;
AddTestObjectForCleanup(cameraObject);
cameraObject.SetActive(true);

正在加载...
取消
保存