Reputation: 21
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
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
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
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
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
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