/// <summary> /// Returs the RectTransform within the GameObject (instantiated from boundingBoxPrefab) that represents the provided DetectedObject. /// If none exists, it retrieves one from the pool (or instantiates a new one if none is available) and /// sets it up with the proper ID and colors. /// </summary> 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) { UnityEngine.Debug.LogError("BBox prefab needs a RectTransform in the root object."); return(null); } liveBBoxes[dobj.id] = newrecttrans; return(newrecttrans); } else { return(liveBBoxes[dobj.id]); } }
/// <summary> /// Sorts all objects in the canvas based on their distance from the camera, so that closer objects overlap further objects. /// </summary> 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); } }
/// <summary> /// Given a frame of object detections, positions a canvas object to represent every visible object /// to encompass the object within the 2D image from the ZED. /// <para>Called from ZEDManager.OnObjectDetection each time there's a new detection frame available.</para> /// </summary> public void Visualize2DBoundingBoxes(DetectionFrame dframe) { //Clear any masks that were displayed last frame, to avoid memory leaks. DestroyLastFrameMaskTextures(); //Debug.Log("Received frame with " + dframe.detectedObjects.Count + " objects."); //Get a list of all active IDs from last frame, and we'll remove each box that's visible this frame. //At the end, we'll clear the remaining boxes, as those are objects no longer visible to the ZED. List <int> activeids = liveBBoxes.Keys.ToList(); List <DetectedObject> newobjects = dframe.GetFilteredObjectList(showONTracked, showSEARCHINGTracked, showOFFTracked); //Test just setting box to first available. foreach (DetectedObject dobj in newobjects) { //Remove the ID from the list we'll use to clear no-longer-visible boxes. if (activeids.Contains(dobj.id)) { activeids.Remove(dobj.id); } //Get the relevant box. This function will create a new one if it wasn't designated yet. 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 //Adjust the size of the RectTransform to encompass the object. bbox.sizeDelta = new Vector2(objrect.width, objrect.height); bbox.anchoredPosition = new Vector2(objrect.x, objrect.y); /* #if UNITY_2018_3_OR_NEWER * float xmod = canvas.GetComponent<RectTransform>().rect.width / zedManager.zedCamera.ImageWidth; * bbox.anchoredPosition = new Vector2(bbox.anchoredPosition.x * xmod, bbox.anchoredPosition.y); * bbox.sizeDelta *= xmod; #endif */ //Apply the mask. if (showObjectMask) { //Make a new image for this new mask. Texture2D maskimage; if (dobj.GetMaskTexture(out maskimage, false)) { idtext.SetMaskImage(maskimage); //Apply to 2D bbox. lastFrameMasks.Add(maskimage); //Cache the texture so it's deleted next time we update our objects. } } } //Remove boxes for objects that the ZED can no longer see. foreach (int id in activeids) { ReturnBoxToPool(id, liveBBoxes[id]); } SortActiveObjectsByDepth(); //Sort all object transforms so that ones with further depth appear behind objects that are closer. }