123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine;
- using UnityEngine.UI;
- public class ZED2DObjectVisualizer : MonoBehaviour
- {
-
-
-
-
- [Tooltip("The scene's ZEDManager.\r\n" +
- "If you want to visualize detections from multiple ZEDs at once you will need multiple ZED3DObjectVisualizer commponents in the scene. ")]
- public ZEDManager zedManager;
-
-
-
-
- [Tooltip("The scene's canvas. This will be adjusted to have required settings/components so that the bounding boxes " +
- "will line up properly with the ZED video feed.")]
- public Canvas canvas;
-
-
-
-
- [Tooltip("If true, the ZED Object Detection manual will be started as soon as the ZED is initiated. " +
- "This avoids having to press the Start Object Detection button in ZEDManager's Inspector.")]
- public bool startObjectDetectionAutomatically = true;
-
-
-
-
-
- [Space(5)]
- [Header("Box Appearance")]
- [Tooltip("Prefab object that's instantiated to represent detected objects. " +
- "This class expects the object to have the default Unity cube as a mesh - otherwise, it may be scaled incorrectly.\r\n" +
- "It also expects a BBox3DHandler component in the root object, but you won't have errors if it lacks one. ")]
- public GameObject boundingBoxPrefab;
-
-
-
- [Tooltip("The colors that will be cycled through when assigning colors to new bounding boxes. ")]
-
- public List<Color> boxColors = new List<Color>()
- {
- new Color(.231f, .909f, .69f, 1),
- new Color(.098f, .686f, .816f, 1),
- new Color(.412f, .4f, .804f, 1),
- new Color(1, .725f, 0f, 1),
- new Color(.989f, .388f, .419f, 1)
- };
-
-
-
-
-
-
- private Dictionary<int, Color> idColorDict = new Dictionary<int, Color>();
-
-
-
- [Space(5)]
- [Header("Mask")]
- public bool showObjectMask = true;
-
-
-
- private bool lastShowObjectMaskValue;
-
-
-
- [Space(5)]
- [Header("Filters")]
- [Tooltip("Display bounding boxes of objects that are actively being tracked by object tracking, where valid positions are known. ")]
- public bool showONTracked = true;
-
-
-
- [Tooltip("Display bounding boxes of objects that were actively being tracked by object tracking, but that were lost very recently.")]
- public bool showSEARCHINGTracked = false;
-
-
-
- [Tooltip("Display bounding boxes of objects that are visible but not actively being tracked by object tracking (usually because object tracking is disabled in ZEDManager).")]
- public bool showOFFTracked = false;
-
-
-
- private int nextColorIndex = 0;
-
-
-
- private Stack<GameObject> bboxPool = new Stack<GameObject>();
-
-
-
-
- private Dictionary<int, RectTransform> liveBBoxes = new Dictionary<int, RectTransform>();
-
-
-
- private List<Texture2D> lastFrameMasks = new List<Texture2D>();
- private void Start()
- {
- if (!zedManager)
- {
- zedManager = FindObjectOfType<ZEDManager>();
- }
- zedManager.OnObjectDetection += Visualize2DBoundingBoxes;
- zedManager.OnZEDReady += OnZEDReady;
- if (!canvas)
- {
- GameObject canvasgo = new GameObject("Canvas - " + zedManager.name);
- canvas = canvasgo.AddComponent<Canvas>();
- }
- lastShowObjectMaskValue = showObjectMask;
- }
- private void OnZEDReady()
- {
- if (startObjectDetectionAutomatically && !zedManager.IsObjectDetectionRunning)
- {
- zedManager.StartObjectDetection();
- }
-
- canvas.renderMode = RenderMode.ScreenSpaceCamera;
- canvas.worldCamera = zedManager.GetLeftCamera();
-
- canvas.planeDistance = 1;
- CanvasScaler scaler = canvas.GetComponent<CanvasScaler>();
- if (!scaler)
- {
- scaler = canvas.gameObject.AddComponent<CanvasScaler>();
- }
- scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
- scaler.referenceResolution = new Vector2(zedManager.zedCamera.ImageWidth, zedManager.zedCamera.ImageHeight);
- }
-
- private void Update()
- {
-
- }
-
-
-
-
-
- public void Visualize2DBoundingBoxes(DetectionFrame dframe)
- {
-
- DestroyLastFrameMaskTextures();
-
-
-
- List<int> activeids = liveBBoxes.Keys.ToList();
- List<DetectedObject> newobjects = dframe.GetFilteredObjectList(showONTracked, showSEARCHINGTracked, showOFFTracked);
-
- foreach (DetectedObject dobj in newobjects)
- {
-
- if (activeids.Contains(dobj.id)) activeids.Remove(dobj.id);
-
- RectTransform bbox = GetBBoxForObject(dobj);
- BBox2DHandler idtext = bbox.GetComponentInChildren<BBox2DHandler>();
- if (idtext)
- {
- float disttobox = Vector3.Distance(dobj.detectingZEDManager.GetLeftCameraTransform().position, dobj.Get3DWorldPosition());
- idtext.SetDistance(disttobox);
- }
- #if UNITY_2018_3_OR_NEWER
- float xmod = canvas.GetComponent<RectTransform>().rect.width / zedManager.zedCamera.ImageWidth;
- Rect objrect = dobj.Get2DBoundingBoxRect(xmod);
- #else
- Rect objrect = dobj.Get2DBoundingBoxRect();
- #endif
-
- bbox.sizeDelta = new Vector2(objrect.width, objrect.height);
- bbox.anchoredPosition = new Vector2(objrect.x, objrect.y);
-
-
- if (showObjectMask)
- {
-
- Texture2D maskimage;
- if (dobj.GetMaskTexture(out maskimage, false))
- {
- idtext.SetMaskImage(maskimage);
- lastFrameMasks.Add(maskimage);
- }
- }
- }
-
- foreach (int id in activeids)
- {
- ReturnBoxToPool(id, liveBBoxes[id]);
- }
- SortActiveObjectsByDepth();
- }
-
-
-
-
-
- private RectTransform GetBBoxForObject(DetectedObject dobj)
- {
- if (!liveBBoxes.ContainsKey(dobj.id))
- {
- GameObject newbox = GetAvailableBBox();
- newbox.transform.SetParent(canvas.transform, false);
- newbox.name = "Object #" + dobj.id;
- Color col;
- if (idColorDict.ContainsKey(dobj.id))
- {
- col = idColorDict[dobj.id];
- }
- else
- {
- col = GetNextColor();
- idColorDict.Add(dobj.id, col);
- }
- BBox2DHandler boxhandler = newbox.GetComponent<BBox2DHandler>();
- if (boxhandler)
- {
- boxhandler.SetColor(col);
- boxhandler.SetID(dobj.id);
- }
- RectTransform newrecttrans = newbox.GetComponent<RectTransform>();
- if (!newrecttrans)
- {
- Debug.LogError("BBox prefab needs a RectTransform in the root object.");
- return null;
- }
- liveBBoxes[dobj.id] = newrecttrans;
- return newrecttrans;
- }
- else return liveBBoxes[dobj.id];
- }
-
-
-
-
-
- private GameObject GetAvailableBBox()
- {
- if (bboxPool.Count == 0)
- {
- GameObject newbbox = Instantiate(boundingBoxPrefab);
- newbbox.transform.SetParent(transform, false);
- bboxPool.Push(newbbox);
- }
- GameObject bbox = bboxPool.Pop();
- bbox.SetActive(true);
- return bbox;
- }
-
-
-
-
- private void ReturnBoxToPool(int id, RectTransform bbox)
- {
- bbox.gameObject.SetActive(false);
- bbox.name = "Unused";
- bboxPool.Push(bbox.gameObject);
- if (liveBBoxes.ContainsKey(id))
- {
- liveBBoxes.Remove(id);
- }
- else
- {
- Debug.LogError("Tried to remove object ID " + id + " from active bboxes, but it wasn't in the dictionary.");
- }
- }
-
-
-
-
-
- private Color GetNextColor()
- {
- if (boxColors.Count == 0)
- {
- return new Color(.043f, .808f, .435f, 1);
- }
- if (nextColorIndex >= boxColors.Count)
- {
- nextColorIndex = 0;
- }
- Color returncol = boxColors[nextColorIndex];
- nextColorIndex++;
- return returncol;
- }
-
-
-
- private void SortActiveObjectsByDepth()
- {
- List<BBox2DHandler> handlers = new List<BBox2DHandler>();
- foreach (Transform child in canvas.transform)
- {
- BBox2DHandler handler = child.GetComponent<BBox2DHandler>();
- if (handler) handlers.Add(handler);
- }
- handlers.Sort((x, y) => y.currentDistance.CompareTo(x.currentDistance));
- for (int i = 0; i < handlers.Count; i++)
- {
- handlers[i].transform.SetSiblingIndex(i);
- }
- }
-
-
-
-
- private void DestroyLastFrameMaskTextures()
- {
- if (lastFrameMasks.Count > 0)
- {
- for (int i = 0; i < lastFrameMasks.Count; i++)
- {
- Destroy(lastFrameMasks[i]);
- }
- lastFrameMasks.Clear();
- }
- }
- private void OnValidate()
- {
-
- if (Application.isPlaying && showObjectMask != lastShowObjectMaskValue)
- {
- lastShowObjectMaskValue = showObjectMask;
- if (!zedManager) zedManager = ZEDManager.GetInstance(sl.ZED_CAMERA_ID.CAMERA_ID_01);
- if(showObjectMask == true && zedManager != null && zedManager.objectDetection2DMask == false)
- {
- Debug.LogError("ZED2DObjectVisualizer has showObjectMask enabled, but its ZEDManager has objectDetection2DMask disabled. " +
- "objectDetection2DMask must be enabled when Object Detection is started or masks will not be visible.");
- }
- }
- }
- private void OnDestroy()
- {
- if (zedManager)
- {
- zedManager.OnObjectDetection -= Visualize2DBoundingBoxes;
- zedManager.OnZEDReady -= OnZEDReady;
- }
- DestroyLastFrameMaskTextures();
- }
- }
|