private GameObject FindCloseBoundingBoxForObject(ObjectClassification objectClassification, Vector3?center) { var candidateBoxes = _boundingBoxes .FindAll(box => box.GetComponent <LabeledBoundingBox>().GetLabel() == objectClassification.label); if (candidateBoxes.Count == 0) { return(null); } var closestBox = candidateBoxes.First(); if (center == null) { return(closestBox); } foreach (var box in candidateBoxes) { if ((closestBox.transform.position - center.Value).magnitude < (box.transform.position - center.Value).magnitude) { closestBox = box; } } return(closestBox); }
// Adds a bounding box game object into the AR world private GameObject GetNewBoundingBoxForClassification(ObjectClassification classification, Vector3 position, float distancePerPixel) { var boundingBox = Instantiate(placedPrefab, position, cameraManager.transform.rotation); boundingBox.cameraManager = cameraManager; boundingBox.SetWidth(classification.box.Size().x *distancePerPixel / LabeledBoundingBoxScale / RectangleScale); boundingBox.SetHeight(classification.box.Size().y *distancePerPixel / LabeledBoundingBoxScale / RectangleScale); boundingBox.SetColor(BoxColors.ColorForItemLabel(classification.label) ?? Color.black); boundingBox.SetLabel(classification.label); boundingBox.SetPredictionScore(classification.score); boundingBox.UpdatesRemaining = TransientBoxUpdateCount; return(boundingBox.gameObject); }
protected override string GetSingleOffsetDescription(Offset oSet, byte[] sectionedData) { // Get the object classification triplet from the BOC field in our container ObjectClassification oc = LowestLevelContainer.GetStructure <BOC>()?.Triplets.OfType <ObjectClassification>().FirstOrDefault(); if (oc != null) { StringBuilder sb = new StringBuilder(); string byteLevel = " bytes"; float byteSize = Data.Length; if (byteSize > 1024) { byteSize /= 1024; byteLevel = "KB"; } if (byteSize > 1024) { byteSize /= 1024; byteLevel = "MB"; } ; if (byteSize % 1 > 0) { byteSize = (float)Math.Round(byteSize, 2); } string dataType = "UNKNOWN"; if (Lookups.OIDs.ContainsKey(oc.RegisteredObjectID)) { dataType = Lookups.OIDs[oc.RegisteredObjectID]; } sb.AppendLine($"Data Type: {dataType}"); sb.AppendLine($"Data Length: {byteSize} {byteLevel}"); return(sb.ToString()); } return("Could not find BOC/Object Classification Triplet"); }
// Adds an ObjectClassification to the AR view, either by creating a new box or reusing an old one that is nearby private void AddObjectClassification(ObjectClassification objectClassification) { List <ARRaycastHit> raycastHits = new List <ARRaycastHit>(); var middle = objectClassification.box.MiddlePoint(); // Convert from y-increases-downward to y-increases-upward coordinate space middle.y = Screen.height - middle.y; // Attempt to raycast if (_arRaycastManager.Raycast(middle, raycastHits, TrackableType.PlaneWithinPolygon)) { var raycastHitPosition = raycastHits[0].pose.position; var surroundingHits = new List <List <ARRaycastHit> >(); new List <Vector2> { Vector2.down, Vector2.left, Vector2.up, Vector2.right } // Go out by several pixels in each direction .ConvertAll(it => it * SurroundingPixelDistance + middle) .ForEachIndexed((position, index) => { surroundingHits.Add(new List <ARRaycastHit>()); // Do a raycast to each surrounding position _arRaycastManager.Raycast(position, surroundingHits[index], TrackableType.PlaneWithinPolygon); }); var validSurroundingPointCount = surroundingHits .FindAll(points => points.Count > 0) .Count; // Find all surrounding distances, divide each by number of distances, then sum for average distance // After dividing by surrounding pixel distance, will result in distance per pixel var distancePerPixel = surroundingHits .FindAll(hits => hits.Count > 0) .ConvertAll(hits => hits.First().pose.position) .Aggregate(0.0f, (avg, position) => avg + (position - raycastHitPosition).magnitude / validSurroundingPointCount / SurroundingPixelDistance); var hitPosition = raycastHits[0].pose.position; var boundingBoxGameObject = FindCloseBoundingBoxForObject(objectClassification, hitPosition); if (boundingBoxGameObject != null) { // Console.WriteLine("Re-using bounding box at center: " + hitPosition); var boundingBox = boundingBoxGameObject.GetComponent <LabeledBoundingBox>(); boundingBox.UpdatesRemaining = TransientBoxUpdateCount; boundingBox.SetPredictionScore(objectClassification.score); } else { // Console.WriteLine("Added bounding box at center: " + hitPosition); _boundingBoxes.Add(GetNewBoundingBoxForClassification(objectClassification, hitPosition, distancePerPixel)); } } else // If it can't raycast, try to reuse any old box with the same label { var boundingBoxWithLabel = FindCloseBoundingBoxForObject(objectClassification, null); if (boundingBoxWithLabel != null) { // Console.WriteLine("Re-using bounding box at old center: " + boundingBoxWithLabel.transform.position); var boundingBox = boundingBoxWithLabel.GetComponent <LabeledBoundingBox>(); boundingBox.UpdatesRemaining = TransientBoxUpdateCount; boundingBox.SetPredictionScore(objectClassification.score); } } }