Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check whether the ARReferenceImage is no longer visible in the camera's view

Tags:

I would like to check whether the ARReferenceImage is no longer visible in the camera's view. At the moment I can check if the image's node is in the camera's view, but this node is still visible in the camera's view when the ARReferenceImage is covered with another image or when the image is removed.

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    guard let node = self.currentImageNode else { return }

    if let pointOfView = sceneView.pointOfView {
        let isVisible = sceneView.isNode(node, insideFrustumOf: pointOfView)
        print("Is node visible: \(isVisible)")
    }
}

So I need to check if the image is no longer visible instead of the image's node visibility. But I can't find out if this is possible. The first screenshot shows three boxes that are added when the image beneath is found. When the found image is covered (see screenshot 2) I would like to remove the boxes.

Found image with boxes

Convered image with boxes

like image 746
KNV Avatar asked Apr 24 '18 08:04

KNV


2 Answers

I managed to fix the problem! Used a little bit of Maybe1's code and his concept to solving the problem, but in a different way. The following line of code is still used to reactivate the image recognition.

// Delete anchor from the session to reactivate the image recognition
sceneView.session.remove(anchor: anchor) 

Let me explain. First we need to add some variables.

// The scnNodeBarn variable will be the node to be added when the barn image is found. Add another scnNode when you have another image.    
var scnNodeBarn: SCNNode = SCNNode()
// This variable holds the currently added scnNode (in this case scnNodeBarn when the barn image is found)     
var currentNode: SCNNode? = nil
// This variable holds the UUID of the found Image Anchor that is used to add a scnNode    
var currentARImageAnchorIdentifier: UUID?
// This variable is used to call a function when there is no new anchor added for 0.6 seconds    
var timer: Timer!

The complete code with comments below.

/// - Tag: ARImageAnchor-Visualizing
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    guard let imageAnchor = anchor as? ARImageAnchor else { return }

    let referenceImage = imageAnchor.referenceImage

    // The following timer fires after 0.6 seconds, but everytime when there found an anchor the timer is stopped.
    // So when there is no ARImageAnchor found the timer will be completed and the current scene node will be deleted and the variable will set to nil
    DispatchQueue.main.async {
        if(self.timer != nil){
            self.timer.invalidate()
        }
        self.timer = Timer.scheduledTimer(timeInterval: 0.6 , target: self, selector: #selector(self.imageLost(_:)), userInfo: nil, repeats: false)
    }

    // Check if there is found a new image on the basis of the ARImageAnchorIdentifier, when found delete the current scene node and set the variable to nil
    if(self.currentARImageAnchorIdentifier != imageAnchor.identifier &&
        self.currentARImageAnchorIdentifier != nil
        && self.currentNode != nil){
            //found new image
            self.currentNode!.removeFromParentNode()
            self.currentNode = nil
    }

    updateQueue.async {

        //If currentNode is nil, there is currently no scene node
        if(self.currentNode == nil){

            switch referenceImage.name {
                case "barn":
                    self.scnNodeBarn.transform = node.transform
                    self.sceneView.scene.rootNode.addChildNode(self.scnNodeBarn)
                    self.currentNode = self.scnNodeBarn
                default: break
            }

        }

        self.currentARImageAnchorIdentifier = imageAnchor.identifier

        // Delete anchor from the session to reactivate the image recognition
        self.sceneView.session.remove(anchor: anchor)
    }

}

Delete the node when the timer is finished indicating that there was no new ARImageAnchor found.

@objc
    func imageLost(_ sender:Timer){
        self.currentNode!.removeFromParentNode()
        self.currentNode = nil
    }

In this way the currently added scnNode wil be deleted when the image is covered or when there is found a new image.

enter image description here

This solution does unfortunately not solve the positioning problem of images because of the following:

ARKit doesn’t track changes to the position or orientation of each detected image.

like image 59
KNV Avatar answered Oct 10 '22 06:10

KNV


I don't think this is currently possible.

From the Recognizing Images in an AR Experience documentation:

Design your AR experience to use detected images as a starting point for virtual content.

ARKit doesn’t track changes to the position or orientation of each detected image. If you try to place virtual content that stays attached to a detected image, that content may not appear to stay in place correctly. Instead, use detected images as a frame of reference for starting a dynamic scene.


New Answer for iOS 12.0

ARKit 2.0 and iOS 12 finally adds this feature, either via ARImageTrackingConfiguration or via the ARWorldTrackingConfiguration.detectionImages property that now also tracks the position of the images.

The Apple documentation to ARImageTrackingConfiguration lists advantages of both methods:

With ARImageTrackingConfiguration, ARKit establishes a 3D space not by tracking the motion of the device relative to the world, but solely by detecting and tracking the motion of known 2D images in view of the camera. ARWorldTrackingConfiguration can also detect images, but each configuration has its own strengths:

  • World tracking has a higher performance cost than image-only tracking, so your session can reliably track more images at once with ARImageTrackingConfiguration.

  • Image-only tracking lets you anchor virtual content to known images only when those images are in view of the camera. World tracking with image detection lets you use known images to add virtual content to the 3D world, and continues to track the position of that content in world space even after the image is no longer in view.

  • World tracking works best in a stable, nonmoving environment. You can use image-only tracking to add virtual content to known images in more situations—for example, an advertisement inside a moving subway car.

like image 38
jlsiewert Avatar answered Oct 10 '22 04:10

jlsiewert