我目前正在使用 ARKit 2.0 (beta) 来做一些图像识别,我正在为一件事而苦苦挣扎。当我检测到我的图像时,我将一个对象放在它旁边(不管是什么对象,它只是一个节点,其材质基于我找到的图像)。
我的问题是:当找到的图像重新出现时是否会触发 ARKit 函数(因此节点也与 imageanchor 相关联)?我正在寻找正确的知道,但我没有找到任何好东西
在 ARKit 3 中,我设法检测到图像何时从视图中消失,renderer(_:didUpdate:for)
并检查锚的isTracked
属性何时设置为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)
}
}
我从上面回答的内容和我已经拥有的内容中得到了一些指导,这对我有用:
//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
}
希望这可以帮助 ;)
我只是要把我的两分钱扔在这里。
如果您查看 ARKit 文档 - 它说:
https://developer.apple.com/documentation/arkit/recognizing_images_in_an_ar_experience
考虑何时允许检测每个图像以触发(或重复)AR 交互。ARKit 为会话配置的 detectionImages 数组中的每个参考图像添加一个图像锚点到会话中。如果您的 AR 体验在检测到图像时将虚拟内容添加到场景中,则默认情况下该操作只会发生一次。要让用户在不重新启动应用的情况下再次体验该内容,请调用会话的 remove(anchor:) 方法来删除相应的 ARImageAnchor。移除锚点后,ARKit 会在下次检测到图像时添加新的锚点。
我还想指出,ARkit 中有两个不同的 ARConfiguration 子类允许图像检测:
ARWorldTrackingConfiguration: https ://developer.apple.com/documentation/arkit/arworldtrackingconfiguration
ARImageTrackingConfiguration: https ://developer.apple.com/documentation/arkit/arimagetrackingconfiguration
我不知道这是否对你有帮助,但我只是想我会为这篇文章的未来读者指出这一点。
我们都通过分享我们所知道的来学习
智能狗
当您为检测图像配置 ARKit 会话时,会在检测到图像并调用renderer(renderer: nodeFor anchor:)方法时将锚点添加到场景中。
当图像被隐藏并在屏幕上“重新出现”时,我猜应该调用渲染器(渲染器:didUpdate 节点:for anchor:) 。
如果不是,那么它将再次调用 renderer(renderer: nodeFor anchor:) 方法,您可以插入一些基于布尔的简单逻辑来检查它是否是第一次检测。
编辑:
我用纸牌游戏做到了。您有一个带有某个名称的 ARReferenceImage 存储。当你呈现目标时,renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? 叫做。
将其名称作为可选项存储在 foundImagesNames: [String] 中。
然后将其从相机中删除,将其显示回来,再次调用它。然后,您只需检查它是否已被检测到。
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)
}
}
尝试self.session.remove(anchor: imageAnchor)
在结尾使用func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor)
。Afterfunc renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor)
函数将被调用。这个答案并不完美,但您可以使用它来使其适合您。
我的解决方案:
在我的应用程序中,我确实这样做了。创建var lastImageAnchor: ARAnchor!
. 在func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor)
添加self.lastImageAnchor = imageAnchor
. 在这个函数之后:
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)
}
}
}
}