tacite
tacite

Reputation: 21

ARKit image detected reappear

I'm currently using ARKit 2.0 (beta) to do some image recognition, and I am struggling with one thing. When I detect my image I put an object beside it (doesn't matter what object it's just a node with a material based on the image I've found).

My question is: Is there an ARKit function trigerred when the image found reappear (so the node associted with the imageanchor too) ? I'm searching right know but I don't find anything good

Upvotes: 1

Views: 1717

Answers (5)

EdmundBillary
EdmundBillary

Reputation: 61

In ARKit 3, I managed to detect when the image disappeared from view using renderer(_:didUpdate:for) and checking when the anchor's isTracked property was set to false.

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
    if let imageAnchor = anchor as? ARImageAnchor, imageAnchor.isTracked == false {
        view?.sceneView.session.remove(anchor: anchor)
    }
}

Upvotes: 6

JAlves
JAlves

Reputation: 31

I took a few pointer from what was answered above and what I already had, and this is what worked for me:

//add a variable to store the last image detected
var lastImageAnchor: ARAnchor!

//at every frame, detect image, compare with the last image stored, and show the node corresponding with the image
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    guard let imageAnchor = anchor as? ARImageAnchor else { return }
    if self.lastImageAnchor != nil && self.lastImageAnchor != imageAnchor {
        self.sceneView.session.remove(anchor: self.lastImageAnchor)
    }
    //add whatever code you need to have your nodes appear

    //lastly change the lastImageAnchor to the one what you just detected
    self.lastImageAnchor = imageAnchor
}

hope this helps ;)

Upvotes: 2

Yerzhan Serikbay
Yerzhan Serikbay

Reputation: 11

Try to use self.session.remove(anchor: imageAnchor) on the end of the func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor). After func renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) function will be called. This answer isn't perfect, but you can work with this to make suitable for you.

My solution:

In my app, I did like this. Created var lastImageAnchor: ARAnchor!. In func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) added self.lastImageAnchor = imageAnchor. After this function:

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
        updateQueue.async {
            if let imageAnchor = anchor as? ARImageAnchor {
                guard let lastAnchor = self.lastImageAnchor else { return }
                if imageAnchor != lastAnchor {
                    self.session.remove(anchor: lastAnchor)
                }
            }
        }
    }

Upvotes: 1

smartdog
smartdog

Reputation: 123

I am just going to throw my two cents in here.

If you look at the ARKit Documentation - it says:

https://developer.apple.com/documentation/arkit/recognizing_images_in_an_ar_experience

Consider when to allow detection of each image to trigger (or repeat) AR interactions. ARKit adds an image anchor to a session exactly once for each reference image in the session configuration’s detectionImages array. If your AR experience adds virtual content to the scene when an image is detected, that action will by default happen only once. To allow the user to experience that content again without restarting your app, call the session’s remove(anchor:) method to remove the corresponding ARImageAnchor. After the anchor is removed, ARKit will add a new anchor the next time it detects the image.

I would also like to point out there are two different ARConfiguration subclasses in ARkit that allow image Detection:

ARWorldTrackingConfiguration: https://developer.apple.com/documentation/arkit/arworldtrackingconfiguration

ARImageTrackingConfiguration: https://developer.apple.com/documentation/arkit/arimagetrackingconfiguration

I don’t know if this helps you out at all, but I just thought I would point this out for future readers of this post.

We all learn by sharing what we know

Smartdog

Upvotes: 1

michael-martinez
michael-martinez

Reputation: 797

When you configure an ARKit session for detecting images, an anchor is added to the scene when the image is detected and the renderer(renderer: nodeFor anchor:) method is called.

When the image is hidden and "reappear" on screen I guess the renderer(renderer: didUpdate node: for anchor:) should be called.

If not, then it would call the renderer(renderer: nodeFor anchor:) method again and you could insert some simple boolean based logic to check if it is the first detection or not.

EDIT:

I did it with a card game. You have an ARReferenceImage store with some name. When you present the target, renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? is called.

Store its name as an optional in foundImagesNames: [String].

Then remove it from camera, show it back, it is called again. You then just have to check if it has already been detected.

if let imageAnchor = anchor as? ARImageAnchor,
   let name = imageAnchor.referenceImage.name {

if self.foundImagesNames.contains(name) {
    //already presented
}
else {
    //first time presenting
    self.foundImagesNames.append(name)
}
}

Upvotes: 1

Related Questions