Mohsen Kamalzadeh
3 年前
当前提交
123d60c1
共有 38 个文件被更改,包括 1712 次插入 和 42 次删除
-
34com.unity.perception/Editor/GroundTruth/PerceptionCameraEditor.cs
-
33com.unity.perception/Editor/Randomization/Editors/RunInUnitySimulationWindow.cs
-
5com.unity.perception/Editor/Randomization/Uxml/RunInUnitySimulationWindow.uxml
-
8com.unity.perception/Runtime/GroundTruth/DatasetCapture.cs
-
10com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBoxLabeler.cs
-
80com.unity.perception/Runtime/GroundTruth/Labelers/KeypointLabeler.cs
-
2com.unity.perception/Runtime/GroundTruth/Labeling/IdLabelConfig.cs
-
18com.unity.perception/Runtime/GroundTruth/PerceptionCamera.cs
-
143com.unity.perception/Runtime/GroundTruth/SimulationState.cs
-
6com.unity.perception/Runtime/GroundTruth/SimulationState_Json.cs
-
2com.unity.perception/Runtime/Randomization/Scenarios/UnitySimulationScenario.cs
-
2com.unity.perception/Runtime/Randomization/Scenarios/UnitySimulationScenarioConstants.cs
-
8com.unity.perception/Runtime/GroundTruth/Exporters.meta
-
8com.unity.perception/Runtime/GroundTruth/Exporters/Coco.meta
-
8com.unity.perception/Runtime/GroundTruth/Exporters/PerceptionFormat.meta
-
11com.unity.perception/Runtime/GroundTruth/Exporters/IDatasetExporter.cs.meta
-
11com.unity.perception/Runtime/GroundTruth/Exporters/PerceptionFormat/PerceptionExporter.cs.meta
-
150com.unity.perception/Runtime/GroundTruth/Exporters/PerceptionFormat/PerceptionExporter.cs
-
8com.unity.perception/Runtime/GroundTruth/Exporters/PerceptionNew.meta
-
94com.unity.perception/Runtime/GroundTruth/Exporters/PerceptionNew/AnnotationHandler.cs
-
11com.unity.perception/Runtime/GroundTruth/Exporters/PerceptionNew/AnnotationHandler.cs.meta
-
151com.unity.perception/Runtime/GroundTruth/Exporters/PerceptionNew/PerceptionNewExporter.cs
-
11com.unity.perception/Runtime/GroundTruth/Exporters/PerceptionNew/PerceptionNewExporter.cs.meta
-
20com.unity.perception/Runtime/GroundTruth/Exporters/IDatasetExporter.cs
-
8com.unity.perception/Runtime/GroundTruth/Exporters/CocoHybrid.meta
-
53com.unity.perception/Runtime/GroundTruth/Exporters/CocoHybrid/CocoHybridExporter.cs
-
11com.unity.perception/Runtime/GroundTruth/Exporters/CocoHybrid/CocoHybridExporter.cs.meta
-
11com.unity.perception/Runtime/GroundTruth/Exporters/Coco/AnnotationHandler.cs.meta
-
11com.unity.perception/Runtime/GroundTruth/Exporters/Coco/CocoExporter.cs.meta
-
11com.unity.perception/Runtime/GroundTruth/Exporters/Coco/CocoTypes.cs.meta
-
165com.unity.perception/Runtime/GroundTruth/Exporters/Coco/CocoTypes.cs
-
69com.unity.perception/Runtime/GroundTruth/Exporters/Coco/AnnotationHandler.cs
-
581com.unity.perception/Runtime/GroundTruth/Exporters/Coco/CocoExporter.cs
|
|||
fileFormatVersion: 2 |
|||
guid: 5353392e887128948bc94b5e0dd9ff73 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: b543148039c075741a0d54a25d56f573 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: a40dd8c5379f64748a0942b0475badc6 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 28e95774bd5a26d47973d1213bcc4c26 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: c38f43837b9cf984f92853858398e0b4 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using Unity.Simulation; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth.Exporters.PerceptionFormat |
|||
{ |
|||
public class PerceptionExporter : IDatasetExporter |
|||
{ |
|||
const Formatting k_Formatting = Formatting.Indented; |
|||
string outputDirectory = string.Empty; |
|||
int captureFileIndex = 0; |
|||
|
|||
public string GetRgbCaptureFilename(params(string, object)[] additionalSensorValues) |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
public void OnSimulationBegin(string directoryName) |
|||
{ |
|||
Debug.Log($"SS - Perception - OnSimBegin"); |
|||
outputDirectory = directoryName; |
|||
} |
|||
|
|||
public void OnSimulationEnd() |
|||
{ |
|||
Debug.Log($"SS - Perception - OnSimEnd"); |
|||
// do nothing :-)
|
|||
} |
|||
|
|||
public void OnAnnotationRegistered<TSpec>(Guid annotationId, TSpec[] values) |
|||
{ |
|||
// do nothing :-)
|
|||
} |
|||
|
|||
public static void WriteJObjectToFile(JObject jObject, string directory, string filename) |
|||
{ |
|||
var stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture); |
|||
using (var jsonTextWriter = new JsonTextWriter(stringWriter)) |
|||
{ |
|||
jsonTextWriter.Formatting = k_Formatting; |
|||
jObject.WriteTo(jsonTextWriter); |
|||
} |
|||
|
|||
var contents = stringWriter.ToString(); |
|||
|
|||
var path = Path.Combine(directory, filename); |
|||
File.WriteAllText(path, contents); |
|||
|
|||
// TODO what to do about this...
|
|||
Manager.Instance.ConsumerFileProduced(path); |
|||
} |
|||
|
|||
public Task ProcessPendingCaptures(List<SimulationState.PendingCapture> pendingCaptures, SimulationState simState) |
|||
{ |
|||
//lazily allocate for fast zero-write frames
|
|||
var capturesJArray = new JArray(); |
|||
|
|||
foreach (var pendingCapture in pendingCaptures) |
|||
capturesJArray.Add(JObjectFromPendingCapture(pendingCapture)); |
|||
|
|||
var capturesJObject = new JObject(); |
|||
capturesJObject.Add("version", DatasetCapture.SchemaVersion); |
|||
capturesJObject.Add("captures", capturesJArray); |
|||
|
|||
Debug.Log("SS - perception - writing"); |
|||
|
|||
WriteJObjectToFile(capturesJObject, outputDirectory, $"captures_{captureFileIndex:000}.json"); |
|||
|
|||
// TODO what to do about this...
|
|||
return null; |
|||
} |
|||
|
|||
public Task OnCaptureReported(int frame, int width, int height, string filename) |
|||
{ |
|||
// do nothing :-)
|
|||
return null; |
|||
} |
|||
|
|||
public static JToken JObjectFromPendingCapture(SimulationState.PendingCapture pendingCapture) |
|||
{ |
|||
var sensorJObject = new JObject();//new SensorCaptureJson
|
|||
sensorJObject["sensor_id"] = pendingCapture.SensorHandle.Id.ToString(); |
|||
sensorJObject["ego_id"] = pendingCapture.SensorData.egoHandle.Id.ToString(); |
|||
sensorJObject["modality"] = pendingCapture.SensorData.modality; |
|||
sensorJObject["translation"] = DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.SensorPose.position); |
|||
sensorJObject["rotation"] = DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.SensorPose.rotation); |
|||
|
|||
if (pendingCapture.AdditionalSensorValues != null) |
|||
{ |
|||
foreach (var(name, value) in pendingCapture.AdditionalSensorValues) |
|||
sensorJObject.Add(name, DatasetJsonUtility.ToJToken(value)); |
|||
} |
|||
|
|||
var egoCaptureJson = new JObject(); |
|||
egoCaptureJson["ego_id"] = pendingCapture.SensorData.egoHandle.Id.ToString(); |
|||
egoCaptureJson["translation"] = DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.EgoPose.position); |
|||
egoCaptureJson["rotation"] = DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.EgoPose.rotation); |
|||
egoCaptureJson["velocity"] = pendingCapture.SensorSpatialData.EgoVelocity.HasValue ? DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.EgoVelocity.Value) : null; |
|||
egoCaptureJson["acceleration"] = pendingCapture.SensorSpatialData.EgoAcceleration.HasValue ? DatasetJsonUtility.ToJToken(pendingCapture.SensorSpatialData.EgoAcceleration.Value) : null; |
|||
|
|||
var capture = new JObject(); |
|||
capture["id"] = pendingCapture.Id.ToString(); |
|||
capture["sequence_id"] = pendingCapture.SequenceId.ToString(); |
|||
capture["step"] = pendingCapture.Step; |
|||
capture["timestamp"] = pendingCapture.Timestamp; |
|||
capture["sensor"] = sensorJObject; |
|||
capture["ego"] = egoCaptureJson; |
|||
capture["filename"] = pendingCapture.Path; |
|||
capture["format"] = GetFormatFromFilename(pendingCapture.Path); |
|||
|
|||
if (pendingCapture.Annotations.Any()) |
|||
capture["annotations"] = new JArray(pendingCapture.Annotations.Select(JObjectFromAnnotation).ToArray()); |
|||
|
|||
return capture; |
|||
} |
|||
|
|||
public static JObject JObjectFromAnnotation((Annotation, SimulationState.AnnotationData) annotationInfo) |
|||
{ |
|||
var annotationJObject = new JObject(); |
|||
annotationJObject["id"] = annotationInfo.Item1.Id.ToString(); |
|||
annotationJObject["annotation_definition"] = annotationInfo.Item2.AnnotationDefinition.Id.ToString(); |
|||
if (annotationInfo.Item2.Path != null) |
|||
annotationJObject["filename"] = annotationInfo.Item2.Path; |
|||
|
|||
if (annotationInfo.Item2.ValuesJson != null) |
|||
annotationJObject["values"] = annotationInfo.Item2.ValuesJson; |
|||
|
|||
return annotationJObject; |
|||
} |
|||
|
|||
static string GetFormatFromFilename(string filename) |
|||
{ |
|||
var ext = Path.GetExtension(filename); |
|||
if (ext == null) |
|||
return null; |
|||
|
|||
if (ext.StartsWith(".")) |
|||
ext = ext.Substring(1); |
|||
|
|||
return ext.ToUpperInvariant(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 8b80f219b9e258043aeae665de9f8d90 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using Unity.Simulation; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth.Exporters.PerceptionNew |
|||
{ |
|||
public static class AnnotationHandler |
|||
{ |
|||
[Serializable] |
|||
struct BoundingBox2dRecord |
|||
{ |
|||
public uint instanceId; |
|||
public int frame; |
|||
public int labelId; |
|||
public string labelName; |
|||
public float x; |
|||
public float y; |
|||
public float width; |
|||
public float height; |
|||
public string annotationId; |
|||
public string annotationDefinition; |
|||
|
|||
public static BoundingBox2dRecord FromBoundingBoxValue(Guid annotationId, Guid annotationDefinition, BoundingBox2DLabeler.BoundingBoxValue bbox) |
|||
{ |
|||
return new BoundingBox2dRecord |
|||
{ |
|||
instanceId = bbox.instance_id, |
|||
frame = bbox.frame, |
|||
labelId = bbox.label_id, |
|||
labelName = bbox.label_name, |
|||
x = bbox.x, |
|||
y = bbox.y, |
|||
width = bbox.width, |
|||
height = bbox.height, |
|||
annotationId = annotationId.ToString(), |
|||
annotationDefinition = annotationDefinition.ToString() |
|||
}; |
|||
} |
|||
|
|||
public string ToJson() |
|||
{ |
|||
return JsonUtility.ToJson(this, true); |
|||
} |
|||
} |
|||
|
|||
public static async Task WriteOutJson(string path, string filename, string json) |
|||
{ |
|||
if (true) |
|||
{ |
|||
json = JToken.Parse(json).ToString(Formatting.Indented); |
|||
} |
|||
|
|||
var writePath = Path.Combine(path, filename); |
|||
var file = File.CreateText(writePath); |
|||
|
|||
await file.WriteAsync(json); |
|||
file.Close(); |
|||
|
|||
Manager.Instance.ConsumerFileProduced(writePath); |
|||
} |
|||
|
|||
static async Task HandleBoundingBoxAnnotation(string path, Annotation annotation, AnnotationDefinition def, BoundingBox2DLabeler.BoundingBoxValue bbox) |
|||
{ |
|||
|
|||
|
|||
var id = annotation.Id; |
|||
var defId = def.Id; |
|||
var converted = BoundingBox2dRecord.FromBoundingBoxValue(id, defId, bbox); |
|||
var filename = $"frame_{converted.frame}_id_{converted.instanceId}_bounding_box_2d.json"; |
|||
var writePath = Path.Combine(path, filename); |
|||
var file = File.CreateText(writePath); |
|||
await file.WriteAsync(converted.ToJson()); |
|||
file.Close(); |
|||
Manager.Instance.ConsumerFileProduced(writePath); |
|||
} |
|||
|
|||
|
|||
public static async Task HandleAnnotation(string path, Annotation annotation, AnnotationDefinition def, object annotatedData) |
|||
{ |
|||
switch (annotatedData) |
|||
{ |
|||
case BoundingBox2DLabeler.BoundingBoxValue bbox: |
|||
await HandleBoundingBoxAnnotation(path, annotation, def, bbox); |
|||
break; |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9c350f412031d374ebe3027d0e8283de |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Unity.Simulation; |
|||
using UnityEngine.Perception.GroundTruth.Exporters.PerceptionFormat; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth.Exporters.PerceptionNew |
|||
{ |
|||
public class PerceptionNewExporter : IDatasetExporter |
|||
{ |
|||
public bool prettyPrint = true; |
|||
|
|||
string m_DirectoryName = string.Empty; |
|||
|
|||
int m_UnknownFrameCount = 0; |
|||
|
|||
public string GetRgbCaptureFilename(params(string, object)[] additionalSensorValues) |
|||
{ |
|||
var frameArray = additionalSensorValues.Where(p => p.Item1 == "frame").Select(p => p.Item2); |
|||
var frame = frameArray.Any() ? (int)frameArray.First() : m_UnknownFrameCount++; |
|||
|
|||
return Path.Combine(m_DirectoryName, $"rgb_{frame}.png"); |
|||
} |
|||
|
|||
public void OnSimulationBegin(string directoryName) |
|||
{ |
|||
Debug.Log($"SS - New Perception - OnSimBegin"); |
|||
m_Metadata = new Metadata |
|||
{ |
|||
version = "0.0.1", |
|||
image_width = 0, |
|||
image_height = 0, |
|||
dataset_size = 0 |
|||
}; |
|||
|
|||
m_DirectoryName = directoryName + Path.DirectorySeparatorChar + Guid.NewGuid() + Path.DirectorySeparatorChar; |
|||
if (!Directory.Exists(m_DirectoryName)) |
|||
Directory.CreateDirectory(m_DirectoryName); |
|||
} |
|||
|
|||
[Serializable] |
|||
struct Metadata |
|||
{ |
|||
public string version; |
|||
public int image_width; |
|||
public int image_height; |
|||
public int dataset_size; |
|||
} |
|||
|
|||
Metadata m_Metadata; |
|||
|
|||
public void OnSimulationEnd() |
|||
{ |
|||
Debug.Log($"SS - New Perception - OnSimEnd"); |
|||
|
|||
var writePath = Path.Combine(m_DirectoryName, "metadata.json"); |
|||
var file = File.CreateText(writePath); |
|||
|
|||
Debug.Log("SS - New Perception - writing"); |
|||
|
|||
file.Write(JsonUtility.ToJson(m_Metadata, true)); |
|||
file.Close(); |
|||
|
|||
Manager.Instance.ConsumerFileProduced(writePath); |
|||
|
|||
Task.WhenAll(m_PendingTasks); |
|||
} |
|||
|
|||
public void OnAnnotationRegistered<TSpec>(Guid annotationId, TSpec[] values) |
|||
{ |
|||
// Right now, do nothing :-)
|
|||
} |
|||
|
|||
static bool GetFilenameForAnnotation(object rawData, out string filename) |
|||
{ |
|||
filename = string.Empty; |
|||
if (rawData is BoundingBox2DLabeler.BoundingBoxValue bbox) |
|||
{ |
|||
var frame = bbox.frame; |
|||
filename = $"frame_{frame}_bounding_bocx_2d.json"; |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
// TODO - handle the 1000's of file writes we will be doing in a more intelligent fashion. Perhaps create a bg thread
|
|||
// that reads json records off of a queue and writes them out
|
|||
|
|||
List<Task> m_PendingTasks = new List<Task>(); |
|||
|
|||
public Task ProcessPendingCaptures(List<SimulationState.PendingCapture> pendingCaptures, SimulationState simState) |
|||
{ |
|||
foreach (var cap in pendingCaptures) |
|||
{ |
|||
foreach (var (annotation, annotationData) in cap.Annotations) |
|||
{ |
|||
// Create a file for the annotation
|
|||
|
|||
#if false
|
|||
if (annotationData.RawValues.Any()) |
|||
{ |
|||
var first = annotationData.RawValues.First(); |
|||
|
|||
if (GetFilenameForAnnotation(first, frame, out var filename)) |
|||
{ |
|||
var json = new StringBuilder("{"); |
|||
json.Append(annotationData.ValuesJson); |
|||
json.Append("}"); |
|||
m_PendingTasks.Add(AnnotationHandler.WriteOutJson(m_DirectoryName, filename, json.ToString())); |
|||
#if false
|
|||
// Need to revisit this and handle this in a performant way
|
|||
var jObject = PerceptionExporter.JObjectFromAnnotation((annotation, annotationData)); |
|||
PerceptionExporter.WriteJObjectToFile(jObject, m_DirectoryName, filename); |
|||
#endif
|
|||
} |
|||
} |
|||
#endif
|
|||
foreach (var rawValue in annotationData.RawValues) |
|||
{ |
|||
|
|||
if (GetFilenameForAnnotation(rawValue, out var filename)) |
|||
{ |
|||
#if true
|
|||
var json = new StringBuilder(); |
|||
json.Append(annotationData.ValuesJson); |
|||
m_PendingTasks.Add(AnnotationHandler.WriteOutJson(m_DirectoryName, filename, json.ToString())); |
|||
#else
|
|||
// Need to revisit this and handle this in a performant way
|
|||
var jObject = PerceptionExporter.JObjectFromAnnotation((annotation, annotationData)); |
|||
PerceptionExporter.WriteJObjectToFile(jObject, m_DirectoryName, filename); |
|||
#endif
|
|||
} |
|||
} |
|||
} |
|||
} |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
public Task OnCaptureReported(int frame, int width, int height, string filename) |
|||
{ |
|||
m_Metadata.dataset_size++; |
|||
m_Metadata.image_height = height; |
|||
m_Metadata.image_width = width; |
|||
return null; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 50287c95e34d8354d935c14caf487750 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth.Exporters |
|||
{ |
|||
public interface IDatasetExporter |
|||
{ |
|||
string GetRgbCaptureFilename(params(string, object)[] additionalSensorValues); |
|||
|
|||
void OnSimulationBegin(string directoryName); |
|||
void OnSimulationEnd(); |
|||
|
|||
void OnAnnotationRegistered<TSpec>(Guid annotationId, TSpec[] values); |
|||
|
|||
Task ProcessPendingCaptures(List<SimulationState.PendingCapture> pendingCaptures, SimulationState simState); |
|||
|
|||
Task OnCaptureReported(int frame, int width, int height, string filename); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 71de1979b5988b34d8d7e41110c57c56 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using UnityEngine.Perception.GroundTruth.Exporters.Coco; |
|||
using UnityEngine.Perception.GroundTruth.Exporters.PerceptionFormat; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth.Exporters.CocoHybrid |
|||
{ |
|||
public class CocoHybridExporter : IDatasetExporter |
|||
{ |
|||
CocoExporter m_Coco = new CocoExporter(); |
|||
PerceptionExporter m_Perception = new PerceptionExporter(); |
|||
|
|||
public string GetRgbCaptureFilename(params (string, object)[] additionalSensorValues) |
|||
{ |
|||
return m_Coco.GetRgbCaptureFilename(additionalSensorValues) + m_Perception.GetRgbCaptureFilename(additionalSensorValues); |
|||
} |
|||
|
|||
public void OnSimulationBegin(string directoryName) |
|||
{ |
|||
m_Coco.OnSimulationBegin(directoryName + "_coco"); |
|||
m_Perception.OnSimulationBegin(directoryName); |
|||
} |
|||
|
|||
public void OnSimulationEnd() |
|||
{ |
|||
m_Coco.OnSimulationEnd(); |
|||
m_Perception.OnSimulationEnd(); |
|||
} |
|||
|
|||
public void OnAnnotationRegistered<TSpec>(Guid annotationId, TSpec[] values) |
|||
{ |
|||
m_Coco.OnAnnotationRegistered(annotationId, values); |
|||
m_Perception.OnAnnotationRegistered(annotationId, values); |
|||
} |
|||
|
|||
public async Task ProcessPendingCaptures(List<SimulationState.PendingCapture> pendingCaptures, SimulationState simState) |
|||
{ |
|||
var cocoTask = m_Coco.ProcessPendingCaptures(pendingCaptures, simState); |
|||
var perceptionTask = m_Perception.ProcessPendingCaptures(pendingCaptures, simState); |
|||
await cocoTask; |
|||
await perceptionTask; |
|||
} |
|||
|
|||
public async Task OnCaptureReported(int frame, int width, int height, string filename) |
|||
{ |
|||
var cocoTask = m_Coco.OnCaptureReported(frame, width, height, filename); |
|||
var perceptionTask = m_Perception.OnCaptureReported(frame, width, height, filename); |
|||
await cocoTask; |
|||
await perceptionTask; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 75965f62c369c564b89229b8cbb10d93 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 0f587bc3e200ea542bd7725e7f64978c |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: d25254cc4c0ad734cb76497c70a40088 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: a715e9572e6cc314098dcdf401bb9273 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Newtonsoft.Json; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth.Exporters.Coco |
|||
{ |
|||
public static class CocoTypes |
|||
{ |
|||
public class CocoData |
|||
{ |
|||
public Info info; |
|||
public Image[] images; |
|||
public ObjectDetectionAnnotation[] annotations; |
|||
public ObjectDetectionCategory[] categories; |
|||
public License[] licenses; |
|||
} |
|||
|
|||
public class Info |
|||
{ |
|||
public int year; |
|||
public string version; |
|||
public string description; |
|||
public string contributor; |
|||
public string url; |
|||
public string date_created; |
|||
} |
|||
|
|||
[Serializable] |
|||
public class License |
|||
{ |
|||
public int id; |
|||
public string name; |
|||
public string url; |
|||
} |
|||
|
|||
[Serializable] |
|||
public class Licenses |
|||
{ |
|||
public License[] licenses; |
|||
} |
|||
|
|||
public class Image |
|||
{ |
|||
public int id; |
|||
public int width; |
|||
public int height; |
|||
public string file_name; |
|||
public int license; |
|||
public string flickr_url; |
|||
public string coco_url; |
|||
public string date_captured; |
|||
} |
|||
|
|||
[Serializable] |
|||
public class ObjectDetectionAnnotation |
|||
{ |
|||
[JsonProperty(Order = -2)] |
|||
public int id; |
|||
[JsonProperty(Order = -2)] |
|||
public int image_id; |
|||
[JsonProperty(Order = -2)] |
|||
public int category_id; |
|||
[JsonProperty(Order = -2)] |
|||
public float[] segmentation; |
|||
[JsonProperty(Order = -2)] |
|||
public float area; |
|||
[JsonProperty(Order = -2)] |
|||
public float[] bbox; |
|||
[JsonProperty(Order = -2)] |
|||
public int iscrowd; |
|||
|
|||
public static ObjectDetectionAnnotation FromBoundingBoxValue(BoundingBox2DLabeler.BoundingBoxValue bbox) |
|||
{ |
|||
return new ObjectDetectionAnnotation |
|||
{ |
|||
id = (int)bbox.instance_id, |
|||
image_id = bbox.frame, |
|||
category_id = bbox.label_id, |
|||
segmentation = new float[]{}, |
|||
area = bbox.width * bbox.height, |
|||
bbox = new []{bbox.x, bbox.y, bbox.width, bbox.height}, |
|||
iscrowd = 0 |
|||
}; |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public class ObjectDetectionCategory |
|||
{ |
|||
[JsonProperty(Order = -2)] |
|||
public int id; |
|||
[JsonProperty(Order = -2)] |
|||
public string name = string.Empty; |
|||
[JsonProperty(Order = -2)] |
|||
public string supercategory = string.Empty; |
|||
} |
|||
|
|||
[Serializable] |
|||
public class ObjectDetectionCategories |
|||
{ |
|||
public List<ObjectDetectionCategory> categories; |
|||
} |
|||
|
|||
public class KeypointAnnotation : ObjectDetectionAnnotation |
|||
{ |
|||
public int num_keypoints; |
|||
public float[] keypoints; |
|||
|
|||
|
|||
public void CopyObjectDetectionData(ObjectDetectionAnnotation objDetection) |
|||
{ |
|||
if (objDetection.id == this.id) |
|||
{ |
|||
image_id = objDetection.image_id; |
|||
area = objDetection.area; |
|||
bbox = objDetection.bbox; |
|||
iscrowd = objDetection.iscrowd; |
|||
} |
|||
} |
|||
|
|||
public static KeypointAnnotation FromKeypointValue(KeypointLabeler.KeypointEntry keypoint) |
|||
{ |
|||
var outKeypoint = new KeypointAnnotation() |
|||
{ |
|||
id = (int)keypoint.instance_id, |
|||
image_id = keypoint.frame, |
|||
category_id = keypoint.label_id, |
|||
segmentation = new float[]{}, |
|||
area = 0, |
|||
bbox = new []{0f}, |
|||
iscrowd = 0, |
|||
num_keypoints = keypoint.keypoints.Length, |
|||
keypoints = new float[keypoint.keypoints.Length * 3] |
|||
}; |
|||
|
|||
var i = 0; |
|||
foreach (var k in keypoint.keypoints) |
|||
{ |
|||
outKeypoint.keypoints[i++] = k.x; |
|||
outKeypoint.keypoints[i++] = k.y; |
|||
outKeypoint.keypoints[i++] = k.state; |
|||
} |
|||
|
|||
return outKeypoint; |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public class KeypointCategory : ObjectDetectionCategory |
|||
{ |
|||
public string[] keypoints; |
|||
public int[][] skeleton; |
|||
} |
|||
|
|||
|
|||
|
|||
[Serializable] |
|||
public class KeypointCategories |
|||
{ |
|||
public KeypointCategory[] categories; |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
|
|||
using System; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth.Exporters.Coco |
|||
{ |
|||
public static class AnnotationHandler |
|||
{ |
|||
public static object HandleAnnotation(AsyncAnnotation asyncAnnotation, object annotation) |
|||
{ |
|||
switch (annotation) |
|||
{ |
|||
case BoundingBox2DLabeler.BoundingBoxValue bbox: |
|||
return CocoTypes.ObjectDetectionAnnotation.FromBoundingBoxValue(bbox); |
|||
case KeypointLabeler.KeypointEntry keypoint: |
|||
return CocoTypes.KeypointAnnotation.FromKeypointValue(keypoint); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
public static CocoTypes.KeypointCategory ToKeypointCategory(KeypointLabeler.KeypointJson keypointJson) |
|||
{ |
|||
var keypoints = new string[keypointJson.key_points.Length]; |
|||
var skeleton = new int[keypointJson.skeleton.Length][]; |
|||
|
|||
foreach (var kp in keypointJson.key_points) |
|||
{ |
|||
keypoints[kp.index] = kp.label; |
|||
} |
|||
|
|||
var i = 0; |
|||
foreach (var bone in keypointJson.skeleton) |
|||
{ |
|||
var joints = new int[] |
|||
{ |
|||
bone.joint1, |
|||
bone.joint2 |
|||
}; |
|||
skeleton[i++] = joints; |
|||
} |
|||
|
|||
return new CocoTypes.KeypointCategory |
|||
{ |
|||
id = keypointJson.label_id, |
|||
name = keypointJson.label_name, |
|||
supercategory = keypointJson.label_name, |
|||
keypoints = keypoints, |
|||
skeleton = skeleton |
|||
}; |
|||
} |
|||
|
|||
|
|||
public static object HandleCameraCapture(int id, int width, int height, string filename) |
|||
{ |
|||
var image = new CocoTypes.Image() |
|||
{ |
|||
id = id, |
|||
width = width, |
|||
height = height, |
|||
file_name = filename, |
|||
license = 0, |
|||
flickr_url = "", |
|||
coco_url = "", |
|||
date_captured = DateTime.Today.ToString("D") |
|||
}; |
|||
|
|||
return image; |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using Unity.Simulation; |
|||
|
|||
namespace UnityEngine.Perception.GroundTruth.Exporters.Coco |
|||
{ |
|||
public class CocoExporter : IDatasetExporter |
|||
{ |
|||
bool m_PrettyPrint = true; |
|||
|
|||
bool m_ReportingObjectDetection; |
|||
bool m_ReportingKeypoints; |
|||
|
|||
bool m_Initialized; |
|||
string m_DirectoryName = string.Empty; |
|||
|
|||
string m_RgbCaptureFilename; |
|||
StreamWriter m_RgbCaptureStream; |
|||
|
|||
string m_ObjectDetectionFilename; |
|||
StreamWriter m_ObjectDetectionStream; |
|||
Task m_ObjectDetectionWritingTask; |
|||
|
|||
string m_KeypointFilename; |
|||
StreamWriter m_KeypointDetectionStream; |
|||
Task m_KeypointDetectionWritingTask; |
|||
|
|||
CocoTypes.ObjectDetectionCategories m_ObjectDetectionCategories; |
|||
string m_ObjectDetectionCategoryFilename; |
|||
StreamWriter m_ObjectDetectionCategoryStream; |
|||
Task m_ObjectDetectionCategoryWritingTask; |
|||
|
|||
CocoTypes.KeypointCategories m_KeypointCategories; |
|||
string m_KeypointCategoryFilename; |
|||
StreamWriter m_KeypointCategoryStream; |
|||
Task m_KeypointCategoryWritingTask; |
|||
|
|||
Guid m_SessionGuid; |
|||
|
|||
public string GetRgbCaptureFilename(params(string, object)[] additionalSensorValues) |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
public void OnSimulationBegin(string directoryName) |
|||
{ |
|||
Debug.Log($"SS - COCO - OnSimBegin"); |
|||
m_DirectoryName = directoryName; |
|||
m_DataCaptured = false; |
|||
} |
|||
|
|||
async Task AwaitAllWrites() |
|||
{ |
|||
Debug.Log("SS - coco - writing"); |
|||
|
|||
WriteOutCategories(); |
|||
|
|||
if (m_ObjectDetectionWritingTask != null) |
|||
{ |
|||
await m_ObjectDetectionWritingTask; |
|||
await m_ObjectDetectionStream.WriteAsync("]"); |
|||
} |
|||
|
|||
if (m_KeypointDetectionWritingTask != null) |
|||
{ |
|||
await m_KeypointDetectionWritingTask; |
|||
await m_KeypointDetectionStream.WriteAsync("]"); |
|||
} |
|||
|
|||
if (m_RgbCaptureWritingTask != null) |
|||
{ |
|||
await m_RgbCaptureWritingTask; |
|||
await m_RgbCaptureStream.WriteAsync("]"); |
|||
} |
|||
|
|||
if (m_ObjectDetectionCategoryWritingTask != null) |
|||
{ |
|||
await m_ObjectDetectionCategoryWritingTask; |
|||
} |
|||
|
|||
if (m_KeypointCategoryWritingTask != null) |
|||
{ |
|||
await m_KeypointCategoryWritingTask; |
|||
} |
|||
|
|||
m_RgbCaptureStream?.Close(); |
|||
m_ObjectDetectionStream?.Close(); |
|||
m_ObjectDetectionCategoryStream?.Close(); |
|||
m_KeypointDetectionStream?.Close(); |
|||
m_KeypointCategoryStream?.Close(); |
|||
} |
|||
|
|||
|
|||
public async void OnSimulationEnd() |
|||
{ |
|||
Debug.Log($"SS - COCO - OnSimEnd"); |
|||
if (!m_DataCaptured) return; |
|||
|
|||
await AwaitAllWrites(); |
|||
|
|||
if (m_ReportingObjectDetection) |
|||
{ |
|||
await WriteObjectDetectionFile(); |
|||
} |
|||
|
|||
if (m_ReportingKeypoints) |
|||
{ |
|||
await WriteKeypointFile(); |
|||
} |
|||
|
|||
File.Delete(m_RgbCaptureFilename); |
|||
|
|||
m_Initialized = false; |
|||
|
|||
} |
|||
|
|||
void InitializeCaptureFiles() |
|||
{ |
|||
if (m_Initialized) return; |
|||
|
|||
if (!Directory.Exists(m_DirectoryName)) |
|||
Directory.CreateDirectory(m_DirectoryName); |
|||
|
|||
m_SessionGuid = Guid.NewGuid(); |
|||
|
|||
//var prefix = m_DirectoryName + Path.DirectorySeparatorChar + m_SessionGuid;
|
|||
|
|||
|
|||
m_RgbCaptureFilename = Path.Combine(m_DirectoryName, m_SessionGuid + "_coco_captures.json"); |
|||
m_RgbCaptureStream = File.CreateText(m_RgbCaptureFilename); |
|||
|
|||
m_ObjectDetectionFilename = Path.Combine(m_DirectoryName, m_SessionGuid + "_coco_box_annotations.json"); |
|||
if (m_ReportingObjectDetection) |
|||
{ |
|||
m_ObjectDetectionStream = File.CreateText(m_ObjectDetectionFilename); |
|||
m_ObjectDetectionCategoryFilename = Path.Combine(m_DirectoryName, m_SessionGuid + "_coco_obj_detection_categories.json"); |
|||
} |
|||
|
|||
m_KeypointFilename = Path.Combine(m_DirectoryName, m_SessionGuid + "_coco_keypoint_annotations.json"); |
|||
if (m_ReportingKeypoints) |
|||
{ |
|||
m_KeypointDetectionStream = File.CreateText(m_KeypointFilename); |
|||
m_KeypointCategoryFilename = Path.Combine(m_DirectoryName, m_SessionGuid + "_coco_keypoint_categories.json"); |
|||
} |
|||
|
|||
m_Initialized = true; |
|||
} |
|||
|
|||
static void AggregateFile(string filename, StringBuilder aggregated, bool skipFirstCharacter = false) |
|||
{ |
|||
var sr = new StreamReader(filename); |
|||
|
|||
var length = (int)sr.BaseStream.Length; |
|||
var start = 0; |
|||
|
|||
if (length == 0) return; |
|||
|
|||
var buffer = new char[length]; |
|||
sr.Read(buffer, start, length); |
|||
|
|||
if (skipFirstCharacter) |
|||
{ |
|||
length--; |
|||
start++; |
|||
} |
|||
|
|||
aggregated.Append(buffer, start, length); |
|||
|
|||
sr.Dispose(); |
|||
} |
|||
|
|||
async Task WriteObjectDetectionFile() |
|||
{ |
|||
var stringBuilder = new StringBuilder(); |
|||
|
|||
stringBuilder.Append("{"); |
|||
|
|||
// Create the json header
|
|||
CreateHeaderInfo(stringBuilder); |
|||
stringBuilder.Append(","); |
|||
|
|||
CreateLicenseInfo(stringBuilder); |
|||
|
|||
// Read in the contents of the captures
|
|||
stringBuilder.Append(",\"images\":"); |
|||
AggregateFile(m_RgbCaptureFilename, stringBuilder); |
|||
|
|||
// Read in the contents of the object detection
|
|||
stringBuilder.Append(",\"annotations\":"); |
|||
AggregateFile(m_ObjectDetectionFilename, stringBuilder); |
|||
stringBuilder.Append(","); |
|||
|
|||
// Read in the contents of the object detection categories
|
|||
AggregateFile(m_ObjectDetectionCategoryFilename, stringBuilder, true); |
|||
|
|||
var json = stringBuilder.ToString(); |
|||
|
|||
if (m_PrettyPrint) |
|||
{ |
|||
json = JToken.Parse(json).ToString(Formatting.Indented); |
|||
} |
|||
|
|||
Debug.Log($"SS - COCO - writing to path: {m_DirectoryName}, file: coco_object_detection_annotations.json"); |
|||
|
|||
// Write out the files
|
|||
var filename = Path.Combine(m_DirectoryName, "coco_object_detection_annotations.json"); |
|||
|
|||
Debug.Log($"SS - COCO - file: {filename}"); |
|||
|
|||
|
|||
var cocoStream = File.CreateText(filename); |
|||
await cocoStream.WriteAsync(json); |
|||
cocoStream.Close(); |
|||
|
|||
Manager.Instance.ConsumerFileProduced(filename); |
|||
|
|||
File.Delete(m_ObjectDetectionFilename); |
|||
File.Delete(m_ObjectDetectionCategoryFilename); |
|||
} |
|||
|
|||
async Task WriteKeypointFile() |
|||
{ |
|||
var stringBuilder = new StringBuilder(); |
|||
|
|||
stringBuilder.Append("{"); |
|||
|
|||
// Create the json header
|
|||
CreateHeaderInfo(stringBuilder); |
|||
stringBuilder.Append(","); |
|||
|
|||
CreateLicenseInfo(stringBuilder); |
|||
|
|||
// Read in the contents of the captures
|
|||
stringBuilder.Append(",\"images\":"); |
|||
AggregateFile(m_RgbCaptureFilename, stringBuilder); |
|||
|
|||
// Read in the contents of the object detection
|
|||
stringBuilder.Append(",\"annotations\":"); |
|||
AggregateFile(m_KeypointFilename, stringBuilder); |
|||
stringBuilder.Append(","); |
|||
|
|||
// Read in the contents of the object detection categories
|
|||
AggregateFile(m_KeypointCategoryFilename, stringBuilder, true); |
|||
|
|||
var json = stringBuilder.ToString(); |
|||
|
|||
if (m_PrettyPrint) |
|||
{ |
|||
json = JToken.Parse(json).ToString(Formatting.Indented); |
|||
} |
|||
|
|||
// Write out the files
|
|||
var filename = Path.Combine(m_DirectoryName, "coco_keypoint_annotations.json"); |
|||
var cocoStream = File.CreateText(filename); |
|||
await cocoStream.WriteAsync(json); |
|||
cocoStream.Dispose(); |
|||
|
|||
Manager.Instance.ConsumerFileProduced(filename); |
|||
|
|||
File.Delete(m_KeypointFilename); |
|||
File.Delete(m_KeypointCategoryFilename); |
|||
} |
|||
|
|||
bool m_DataCaptured; |
|||
|
|||
void WriteOutCategories() |
|||
{ |
|||
// 3 cases
|
|||
// 1) Just have object detection
|
|||
// 2) Just have keypoint detection
|
|||
// 3) Have both, which includes writing out object detection in object detection coco output
|
|||
// and merging the object detection & keypoints and writing out that data in the keypoint
|
|||
// coco output data
|
|||
if (m_ReportingObjectDetection) |
|||
{ |
|||
m_ObjectDetectionCategoryStream = File.CreateText(m_ObjectDetectionCategoryFilename); |
|||
var json = JsonUtility.ToJson(m_ObjectDetectionCategories); |
|||
m_ObjectDetectionCategoryWritingTask = m_ObjectDetectionCategoryStream.WriteAsync(json); |
|||
} |
|||
|
|||
if (m_ReportingKeypoints) |
|||
{ |
|||
// TODO - revisit this, but right now we are going to add the keypoint info to all of the categories,
|
|||
// we can get away with this because we only support one set of keypoint definitions per simulation
|
|||
// currently.
|
|||
|
|||
if (m_KeypointCategories.categories.Length < 1) return; |
|||
|
|||
m_KeypointCategoryStream = File.CreateText(m_KeypointCategoryFilename); |
|||
|
|||
var merged = m_KeypointCategories; |
|||
|
|||
if (m_ReportingObjectDetection) |
|||
{ |
|||
merged = new CocoTypes.KeypointCategories |
|||
{ |
|||
categories = new CocoTypes.KeypointCategory[m_ObjectDetectionCategories.categories.Count] |
|||
}; |
|||
|
|||
var i = 0; |
|||
foreach (var odc in m_ObjectDetectionCategories.categories) |
|||
{ |
|||
merged.categories[i++] = MergeCategories(odc, m_KeypointCategories.categories[0]); |
|||
} |
|||
} |
|||
|
|||
#if false
|
|||
var json = JsonUtility.ToJson(merged); |
|||
#else
|
|||
var builder = new StringBuilder(); |
|||
var sw = new StringWriter(builder); |
|||
|
|||
var serializer = new JsonSerializer(); |
|||
|
|||
using (var writer = new JsonTextWriter(sw)) |
|||
{ |
|||
serializer.Serialize(writer, merged); |
|||
} |
|||
|
|||
var json = builder.ToString(); |
|||
#endif
|
|||
m_KeypointCategoryWritingTask = m_KeypointCategoryStream.WriteAsync(json); |
|||
} |
|||
} |
|||
|
|||
public void OnAnnotationRegistered<TSpec>(Guid annotationId, TSpec[] values) |
|||
{ |
|||
if (annotationId.ToString() == BoundingBox2DLabeler.annotationIdForCocoExport) |
|||
{ |
|||
m_ReportingObjectDetection = true; |
|||
m_ObjectDetectionCategories = new CocoTypes.ObjectDetectionCategories |
|||
{ |
|||
categories = new List<CocoTypes.ObjectDetectionCategory>() |
|||
}; |
|||
|
|||
foreach (var value in values) |
|||
{ |
|||
if (value is IdLabelConfig.LabelEntrySpec spec) |
|||
{ |
|||
var rec = new CocoTypes.ObjectDetectionCategory |
|||
{ |
|||
id = spec.label_id, |
|||
name = spec.label_name, |
|||
supercategory = spec.label_name |
|||
}; |
|||
|
|||
m_ObjectDetectionCategories.categories.Add(rec); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (annotationId.ToString() == KeypointLabeler.annotationIdForCocoExport) |
|||
{ |
|||
m_ReportingKeypoints = true; |
|||
var categories = new CocoTypes.KeypointCategory[values.Length]; |
|||
var i = 0; |
|||
|
|||
foreach (var value in values) |
|||
{ |
|||
if (value is KeypointLabeler.KeypointJson keypointJson) |
|||
{ |
|||
categories[i++] = AnnotationHandler.ToKeypointCategory(keypointJson); |
|||
} |
|||
} |
|||
|
|||
m_KeypointCategories = new CocoTypes.KeypointCategories |
|||
{ |
|||
categories = categories |
|||
}; |
|||
} |
|||
} |
|||
|
|||
|
|||
static string versionEntry = "0.0.1"; |
|||
static string descriptionEntry = "Description of dataset"; |
|||
static string contributorEntry = "Anonymous"; |
|||
static string urlEntry = "Not Set"; |
|||
|
|||
static void CreateHeaderInfo(StringBuilder stringBuilder) |
|||
{ |
|||
stringBuilder.Append("\"info\":"); |
|||
|
|||
var dateTime = DateTime.Today; |
|||
var info = new CocoTypes.Info |
|||
{ |
|||
year = int.Parse(dateTime.ToString("yyyy")), |
|||
version = versionEntry, |
|||
description = descriptionEntry, |
|||
contributor = contributorEntry, |
|||
url = urlEntry, |
|||
date_created = DateTime.Today.ToString("D") |
|||
}; |
|||
stringBuilder.Append(JsonUtility.ToJson(info)); |
|||
} |
|||
|
|||
static void CreateLicenseInfo(StringBuilder stringBuilder) |
|||
{ |
|||
var licenses = new CocoTypes.Licenses |
|||
{ |
|||
licenses = new[] |
|||
{ |
|||
new CocoTypes.License |
|||
{ |
|||
id = 0, |
|||
name = "No License", |
|||
url = "Not Set" |
|||
} |
|||
} |
|||
}; |
|||
|
|||
var tmpJson = JsonUtility.ToJson(licenses); |
|||
|
|||
// Remove the start and end '{' from the licenses json
|
|||
stringBuilder.Append(tmpJson.Substring(1, tmpJson.Length - 2)); |
|||
} |
|||
|
|||
bool m_FirstBoxAnnotation = true; |
|||
bool m_FirstKeypointAnnotation = true; |
|||
|
|||
bool m_FirstCapture = true; |
|||
Task m_RgbCaptureWritingTask; |
|||
|
|||
static CocoTypes.KeypointCategory MergeCategories(CocoTypes.ObjectDetectionCategory od, CocoTypes.KeypointCategory kp) |
|||
{ |
|||
return new CocoTypes.KeypointCategory |
|||
{ |
|||
id = od.id, |
|||
name = od.name, |
|||
supercategory = od.supercategory, |
|||
keypoints = kp.keypoints, |
|||
skeleton = kp.skeleton |
|||
}; |
|||
} |
|||
|
|||
public async Task ProcessPendingCaptures(List<SimulationState.PendingCapture> pendingCaptures, SimulationState simState) |
|||
{ |
|||
var boxJson = string.Empty; |
|||
var keypointJson = string.Empty; |
|||
|
|||
foreach (var cap in pendingCaptures) |
|||
{ |
|||
var boxes = new Dictionary<int, CocoTypes.ObjectDetectionAnnotation>(); |
|||
|
|||
foreach (var annotation in cap.Annotations) |
|||
{ |
|||
var tmp = ProcessBoundingBoxAnnotations(annotation.Item2.RawValues); |
|||
|
|||
foreach (var box in tmp.Values) |
|||
{ |
|||
boxes[box.id] = box; |
|||
|
|||
if (m_FirstBoxAnnotation) |
|||
{ |
|||
boxJson = "["; |
|||
m_FirstBoxAnnotation = false; |
|||
} |
|||
else |
|||
boxJson += ","; |
|||
|
|||
boxJson += JsonUtility.ToJson(box); |
|||
} |
|||
|
|||
} |
|||
|
|||
foreach (var annotation in cap.Annotations) |
|||
{ |
|||
var keypoints = ProcessKeypointAnnotations(annotation.Item2.RawValues, boxes); |
|||
|
|||
foreach (var kp in keypoints.Values) |
|||
{ |
|||
if (m_FirstKeypointAnnotation) |
|||
{ |
|||
keypointJson = "["; |
|||
m_FirstKeypointAnnotation = false; |
|||
} |
|||
else |
|||
keypointJson += ","; |
|||
|
|||
var builder = new StringBuilder(); |
|||
var stringWriter = new StringWriter(builder); |
|||
|
|||
var serializer = new JsonSerializer(); |
|||
|
|||
using (var writer = new JsonTextWriter(stringWriter)) |
|||
{ |
|||
serializer.Serialize(writer, kp); |
|||
} |
|||
|
|||
keypointJson += builder.ToString(); |
|||
|
|||
} |
|||
} |
|||
} |
|||
|
|||
if (m_ObjectDetectionWritingTask != null) |
|||
await m_ObjectDetectionWritingTask; |
|||
|
|||
if (boxJson != string.Empty) |
|||
{ |
|||
InitializeCaptureFiles(); |
|||
m_ObjectDetectionWritingTask = m_ObjectDetectionStream.WriteAsync(boxJson); |
|||
} |
|||
|
|||
if (m_KeypointDetectionWritingTask != null) |
|||
await m_KeypointDetectionWritingTask; |
|||
|
|||
if (keypointJson != string.Empty) |
|||
{ |
|||
InitializeCaptureFiles(); |
|||
m_KeypointDetectionWritingTask = m_KeypointDetectionStream.WriteAsync(keypointJson); |
|||
} |
|||
} |
|||
|
|||
static Dictionary<int, CocoTypes.ObjectDetectionAnnotation> ProcessBoundingBoxAnnotations(IEnumerable<object> annotations) |
|||
{ |
|||
var map = new Dictionary<int, CocoTypes.ObjectDetectionAnnotation>(); |
|||
foreach (var annotation in annotations) |
|||
{ |
|||
if (annotation is BoundingBox2DLabeler.BoundingBoxValue bbox) |
|||
{ |
|||
var coco = CocoTypes.ObjectDetectionAnnotation.FromBoundingBoxValue(bbox); |
|||
map[coco.id] = coco; |
|||
} |
|||
} |
|||
|
|||
return map; |
|||
} |
|||
|
|||
static Dictionary<int, CocoTypes.KeypointAnnotation> ProcessKeypointAnnotations(IEnumerable<object> annotations, Dictionary<int, CocoTypes.ObjectDetectionAnnotation> boundingBoxes) |
|||
{ |
|||
var map = new Dictionary<int, CocoTypes.KeypointAnnotation>(); |
|||
|
|||
foreach (var annotation in annotations) |
|||
{ |
|||
if (annotation is KeypointLabeler.KeypointEntry keypoint) |
|||
{ |
|||
var coco = CocoTypes.KeypointAnnotation.FromKeypointValue(keypoint); |
|||
if (boundingBoxes.ContainsKey(coco.id)) |
|||
{ |
|||
coco.CopyObjectDetectionData(boundingBoxes[coco.id]); |
|||
} |
|||
|
|||
map[coco.id] = coco; |
|||
} |
|||
} |
|||
|
|||
return map; |
|||
} |
|||
|
|||
public async Task OnCaptureReported(int frame, int width, int height, string filename) |
|||
{ |
|||
InitializeCaptureFiles(); |
|||
|
|||
var json = string.Empty; |
|||
|
|||
var converted = AnnotationHandler.HandleCameraCapture(frame, width, height, filename); |
|||
if (m_FirstCapture) |
|||
{ |
|||
json = "["; |
|||
m_FirstCapture = false; |
|||
} |
|||
else |
|||
json += ","; |
|||
|
|||
json += JsonUtility.ToJson(converted); |
|||
|
|||
if (m_RgbCaptureWritingTask != null) |
|||
await m_RgbCaptureWritingTask; |
|||
|
|||
if (json != string.Empty) |
|||
m_RgbCaptureWritingTask = m_RgbCaptureStream.WriteAsync(json); |
|||
|
|||
m_DataCaptured = true; |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue