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);
        }
Example #3
0
        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);
                }
            }
        }