KNV*_*KNV 18 xcode scenekit swift arkit aranchor
我想检查相机视图中是否不再显示ARReferenceImage.目前我可以检查图像的节点是否在摄像机的视图中,但是当ARReferenceImage被另一个图像覆盖或者图像被移除时,该节点仍然可以在摄像机的视图中看到.
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)")
}
}
Run Code Online (Sandbox Code Playgroud)
所以我需要检查图像是否不再可见,而不是图像的节点可见性.但我不知道这是否可行.第一个屏幕截图显示了找到下方图像时添加的三个框.当覆盖找到的图像时(见截图2)我想删除这些框.
KNV*_*KNV 13
我设法解决了这个问题!使用了一点MaybeI的代码和他的概念来解决问题,但以不同的方式.以下代码行仍用于重新激活图像识别.
// Delete anchor from the session to reactivate the image recognition
sceneView.session.remove(anchor: anchor)
Run Code Online (Sandbox Code Playgroud)
让我解释.首先,我们需要添加一些变量.
// 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!
Run Code Online (Sandbox Code Playgroud)
完整的代码,下面有评论.
/// - 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)
}
}
Run Code Online (Sandbox Code Playgroud)
在计时器完成时删除节点,表明没有找到新的ARImageAnchor.
@objc
func imageLost(_ sender:Timer){
self.currentNode!.removeFromParentNode()
self.currentNode = nil
}
Run Code Online (Sandbox Code Playgroud)
通过这种方式,当覆盖图像或找到新图像时,将删除当前添加的scnNode.
遗憾的是,该解决方案无法解决图像的定位问题,原因如下:
ARKit不跟踪每个检测到的图像的位置或方向的变化.
我认为目前不可能.
设计您的AR体验,将检测到的图像用作虚拟内容的起点.
ARKit不跟踪每个检测到的图像的位置或方向的变化.如果您尝试将虚拟内容保留在检测到的图像上,则该内容可能无法正确保留.而是使用检测到的图像作为启动动态场景的参照系.
ARKit 2.0和iOS 12最终通过ARImageTrackingConfiguration
或通过ARWorldTrackingConfiguration.detectionImages
现在也跟踪图像位置的属性添加此功能.
Apple文档ARImageTrackingConfiguration
列出了两种方法的优点:
使用ARImageTrackingConfiguration,ARKit不是通过跟踪设备相对于世界的运动来建立3D空间,而是仅通过检测和跟踪相机视图中已知2D图像的运动来建立3D空间.ARWorldTrackingConfiguration也可以检测图像,但每种配置都有自己的优势:
与仅图像跟踪相比,世界跟踪具有更高的性能成本,因此您的会话可以使用ARImageTrackingConfiguration一次性可靠地跟踪更多图像.
仅图像跟踪允许您仅在这些图像在摄像机视图中时才将虚拟内容锚定到已知图像.通过图像检测进行世界跟踪,您可以使用已知图像将虚拟内容添加到3D世界,并在图像不再可见时继续跟踪该内容在世界空间中的位置.
世界跟踪在稳定,不动的环境中运行最佳.您可以使用仅图像跟踪在更多情况下将虚拟内容添加到已知图像 - 例如,移动地铁车厢内的广告.
检查ARKit当前是否跟踪的图像的正确方法是使用didUpdate节点上的ARImageAnchor中的“ isTracked”属性作为锚点功能。
为此,我使用下一个结构:
struct TrackedImage {
var name : String
var node : SCNNode?
}
Run Code Online (Sandbox Code Playgroud)
然后是带有所有图像名称的该结构的数组。
var trackedImages : [TrackedImage] = [ TrackedImage(name: "image_1", node: nil) ]
Run Code Online (Sandbox Code Playgroud)
然后在didAdd节点中进行锚定,将新内容设置为场景,并将该节点添加到trackedImages数组中的相应元素
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
// Check if the added anchor is a recognized ARImageAnchor
if let imageAnchor = anchor as? ARImageAnchor{
// Get the reference ar image
let referenceImage = imageAnchor.referenceImage
// Create a plane to match the detected image.
let plane = SCNPlane(width: referenceImage.physicalSize.width, height: referenceImage.physicalSize.height)
plane.firstMaterial?.diffuse.contents = UIColor(red: 1, green: 1, blue: 1, alpha: 0.5)
// Create SCNNode from the plane
let planeNode = SCNNode(geometry: plane)
planeNode.eulerAngles.x = -.pi / 2
// Add the plane to the scene.
node.addChildNode(planeNode)
// Add the node to the tracked images
for (index, trackedImage) in trackedImages.enumerated(){
if(trackedImage.name == referenceImage.name){
trackedImage[index].node = planeNode
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后,在didUpdate节点的锚函数中,我们在数组中搜索锚名称,并检查isTracked属性是否为false。
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
var trackedImages : [TrackedImage] = [ TrackedImage(name: "image_1", node: nil) ]
if let imageAnchor = anchor as? ARImageAnchor{
// Search the corresponding node for the ar image anchor
for (index, trackedImage) in trackedImages.enumerated(){
if(trackedImage.name == referenceImage.name){
// Check if track is lost on ar image
if(imageAnchor.isTracked){
// The image is being tracked
trackedImage.node?.isHidden = false // Show or add content
}else{
// The image is lost
trackedImage.node?.isHidden = true // Hide or delete content
}
break
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
当您想同时跟踪多个图像并知道何时丢失任何图像时,此解决方案有效。
注意:为了使此解决方案起作用,maximumNumberOfTrackedImages
必须将AR配置中的设置为非零数字。
小智 5
不管它的价值如何,我花了几个小时试图找出如何不断检查图像引用。didUpdate 函数就是答案。然后您只需使用 .isTracked 属性测试参考图像是否被跟踪。此时,您可以将 .isHidden 属性设置为 true 或 false。这是我的例子:
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
let trackedNode = node
if let imageAnchor = anchor as? ARImageAnchor{
if (imageAnchor.isTracked) {
trackedNode.isHidden = false
print("\(trackedNode.name)")
}else {
trackedNode.isHidden = true
//print("\(trackedImageName)")
print("No image in view")
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4372 次 |
最近记录: |