【发布时间】:2019-01-09 04:49:19
【问题描述】:
我目前正在使用 ARKit 2.0(测试版)进行一些图像识别,但我正在为一件事而苦苦挣扎。 当我检测到我的图像时,我会在它旁边放一个对象(不管是什么对象,它只是一个节点,其材质基于我找到的图像)。
我的问题是:当找到的图像重新出现时是否触发了 ARKit 函数(因此节点也与 imageanchor 相关联)?我正在搜索正确的知道,但我没有找到任何好东西
【问题讨论】:
我目前正在使用 ARKit 2.0(测试版)进行一些图像识别,但我正在为一件事而苦苦挣扎。 当我检测到我的图像时,我会在它旁边放一个对象(不管是什么对象,它只是一个节点,其材质基于我找到的图像)。
我的问题是:当找到的图像重新出现时是否触发了 ARKit 函数(因此节点也与 imageanchor 相关联)?我正在搜索正确的知道,但我没有找到任何好东西
【问题讨论】:
当您为检测图像配置 ARKit 会话时,会在检测到图像并调用 renderer(renderer: nodeFor anchor:) 方法时将锚点添加到场景中。
当图像被隐藏并“重新出现”在屏幕上时,我猜应该调用 renderer(renderer: didUpdate node: 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)
}
}
【讨论】:
我只是要把我的两分钱扔在这里。
如果您查看 ARKit 文档 - 它说:
https://developer.apple.com/documentation/arkit/recognizing_images_in_an_ar_experience
考虑何时允许检测每个图像来触发(或重复) AR交互。 ARKit 将图像锚点添加到会话中恰好一次 对于会话配置中的每个参考图像 检测图像数组。如果您的 AR 体验将虚拟内容添加到 检测到图像时的场景,默认情况下该动作将 只发生一次。让用户再次体验该内容 无需重新启动您的应用程序,调用会话的 remove(anchor:) 方法 删除相应的 ARImageAnchor。锚定后 移除后,ARKit 将在下次检测到 图片。
我还想指出,ARkit 中有两个不同的 ARConfiguration 子类允许图像检测:
ARWorldTracking 配置: https://developer.apple.com/documentation/arkit/arworldtrackingconfiguration
ARImageTracking配置: https://developer.apple.com/documentation/arkit/arimagetrackingconfiguration
我不知道这是否对你有帮助,但我只是想我会为这篇文章的未来读者指出这一点。
我们都通过分享我们所知道的来学习
智能狗
【讨论】:
尝试在func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) 的末尾使用self.session.remove(anchor: imageAnchor)。在func 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)
}
}
}
}
【讨论】:
我从上面回答的内容和我已经拥有的内容中得到了一些指导,这对我有用:
//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 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)
}
}
【讨论】: