如何在 ARKit 1.5 中初始检测后跟踪图像锚点?

2024-02-13

我想ARKit 1.5具有图像识别功能,正如我们可以在代码中读到的Apple 的示例项目 https://developer.apple.com/documentation/arkit/recognizing_images_in_an_ar_experience: 初始检测后不会跟踪图像锚点,因此创建一个 限制平面可视化显示持续时间的动画。

An ARImageAnchor没有center: vector_float3 like ARPlaneAnchor已经,并且我找不到如何跟踪检测到的图像锚点。

我想在这方面实现类似的目标video https://www.youtube.com/watch?v=LX8BFFFWtFw,也就是说,有一个固定图像、按钮、标签等,停留在检测到的图像之上,我不明白如何实现这一点。

下面是图像检测结果的代码:

// MARK: - ARSCNViewDelegate (Image detection results)
/// - 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
    updateQueue.async {

        // Create a plane to visualize the initial position of the detected image.
        let plane = SCNPlane(width: referenceImage.physicalSize.width,
                         height: referenceImage.physicalSize.height)
        plane.materials.first?.diffuse.contents = UIColor.blue.withAlphaComponent(0.20)
        self.planeNode = SCNNode(geometry: plane)

        self.planeNode?.opacity = 1

        /*
         `SCNPlane` is vertically oriented in its local coordinate space, but
         `ARImageAnchor` assumes the image is horizontal in its local space, so
         rotate the plane to match.
         */
        self.planeNode?.eulerAngles.x = -.pi / 2

        /*
         Image anchors are not tracked after initial detection, so create an
         animation that limits the duration for which the plane visualization appears.
         */

        // Add the plane visualization to the scene.
        if let planeNode = self.planeNode {
            node.addChildNode(planeNode)
        }

        if let imageName = referenceImage.name {
            plane.materials = [SCNMaterial()]
            plane.materials[0].diffuse.contents = UIImage(named: imageName)
        }
    }

    DispatchQueue.main.async {
        let imageName = referenceImage.name ?? ""
        self.statusViewController.cancelAllScheduledMessages()
        self.statusViewController.showMessage("Detected image “\(imageName)”")
    }
}

您已经完成了大部分工作 - 您的代码将一个平面放置在检测到的图像上方,因此很明显,那里正在发生一些事情,成功地将平面的中心位置设置为图像锚点的中心位置。也许您的第一步应该是更好地理解您拥有的代码......

ARPlaneAnchor has a center (and extent)因为在 ARKit 最初检测到平面后,平面可以有效地生长。当你第一次获得平面锚时,它transform告诉您一小块水平(或垂直)平面的位置和方向。仅此一点就足以让您将一些虚拟内容放置在那一小块表面的中间。

随着时间的推移,ARKit 会找出更多相同平坦表面的位置,因此平面锚点的extent变大。但你可能一开始会检测到桌子的一端,然后识别出更多远端——这意味着平坦的表面并不以检测到的第一个补丁为中心。而不是改变transform主播的新情况,ARKit告诉你center(这是关系到进行变换)。

An ARImageAnchor不会增长——ARKit 要么立即检测到整个图像,要么根本不检测到图像。因此,当您检测到图像时,锚点的transform告诉您图像中心的位置和方向。 (如果你想知道大小/范围,你可以从physicalSize检测到的参考图像的,就像示例代码一样。)

因此,要将一些 SceneKit 内容放置在ARImageAnchor(或任何其他ARAnchor子类),您可以:

  • 只需将其添加为子节点即可SCNNodeARKit 在该委托方法中为您创建。如果您不做任何事情来改变它们,它的位置和方向将与拥有它的节点的位置和方向相匹配。 (这就是您引用的 Apple 示例代码的作用。)

  • 将其放置在世界空间中(即,作为场景的子级)rootNode),使用锚点transform获取位置或方向或两者。

    (You can extract the translation — that is, relative position — from a transform matrix: grab the first three elements of the last column; e.g. transform.columns.3 is a float4 vector whose xyz elements are your position and whose w element is 1.)


不过,您链接到的演示视频并没有将事物放入 3D 空间中,而是将 2D UI 元素放在屏幕上,其位置跟踪锚点在世界空间中相对于 3D 相机的移动。

你可以很容易地得到kind效果(第一近似值)通过使用ARSKView(ARKit+SpriteKit)而不是ARSCNView(ARKit+SceneKit)。这使您可以将 2D 精灵与世界空间中的 3D 位置相关联,然后ARSKView自动移动和缩放它们,使它们看起来保持附着在这些 3D 位置上。这是一种常见的 3D 图形技巧,称为“广告牌”,其中 2D 精灵始终保持直立并面向相机,但会四处移动和缩放以匹配 3D 视角。

如果这就是您正在寻找的效果,也有一个应用程序(示例代码)。这通过 ARKit 实时使用视觉 https://developer.apple.com/documentation/arkit/using_vision_in_real_time_with_arkit示例主要是关于其他主题,但它does展示如何使用ARSKView显示与关联的标签ARAnchor职位。 (正如您在上面所看到的,放置内容以匹配锚点位置是相同的,无论哪种ARAnchor您正在使用的子类。)这是他们代码中的关键部分:

func view(_ view: ARSKView, didAdd node: SKNode, for anchor: ARAnchor) {
    // ... irrelevant bits omitted... 
    let label = TemplateLabelNode(text: labelText)
    node.addChild(label)
}

也就是说,只需执行ARSKView didAdddelegate 方法,并添加您想要的任何 SpriteKit 节点作为 ARKit 提供的子节点。


然而,演示视频不仅仅是精灵广告牌:它与绘画相关的标签不仅保持固定在 2D 方向,而且保持固定的 2D 尺寸(也就是说,它们不会像广告牌精灵那样缩放以模拟透视) 。更重要的是,它们似乎是 UIKit 控件,具有全套继承的交互行为,而不仅仅是 2D 图像(与 SpriteKit 类似)。

Apple 的 API 并未提供“开箱即用”的直接方法,但不难想象将 API 各个部分组合在一起以获得这种结果的某些方法。以下是一些值得探索的途径:

  • 如果你不需要 UIKit 控件,你可能可以在 SpriteKit 中完成这一切,使用约束来匹配“广告牌”节点的位置ARSKView提供但不提供其规模。可能看起来像这样(未经测试,买者自负):

    func view(_ view: ARSKView, didAdd node: SKNode, for anchor: ARAnchor) {
        let label = MyLabelNode(text: labelText) // or however you make your label
        view.scene.addChild(label)
    
        // constrain label to zero distance from ARSKView-provided, anchor-following node
        let zeroDistanceToAnchor = SKConstraint.distance(SKRange(constantValue: 0), to: node)
        label.constraints = [ zeroDistanceToAnchor ]
    }
    
  • 如果您想要 UIKit 元素,请制作ARSKView视图控制器的子视图(不是根视图),并将这些 UIKit 元素设置为其他子视图。然后,在你的 SpriteKit 场景中update方法,通过你的ARAnchor- 以下节点,将它们的位置从 SpriteKit 场景坐标转换为 UIKit 视图坐标,并相应地设置 UIKit 元素的位置。 (该演示似乎正在使用弹出窗口,因此您不会将其作为子视图进行管理......您可能会更新sourceRect https://developer.apple.com/documentation/uikit/uipopoverpresentationcontroller/1622324-sourcerect对于每个弹出窗口。)这涉及更多内容,因此详细信息超出了这个已经很长的答案的范围。


最后一点……希望这个冗长的答案对关键有所帮助issues您的问题(了解锚点位置并在相机移动时放置跟随它们的 3D 或 2D 内容)。

但要澄清一些关键问题并发出警告words在你的问题的早期:

当 ARKit 说它在检测后不跟踪图像时,这意味着它不知道图像何时/是否移动(相对于周围的世界)。 ARKit 仅报告一次图像的位置,因此该位置甚至无法从 ARKit 不断改进其对您周围世界以及您在其中的位置的估计中受益。例如,如果图像在墙上,则报告的图像位置/方向可能与墙上的垂直平面检测结果不一致(尤其是随着时间的推移,随着平面估计的改进)。

Update:在 iOS 12 中,您can启用对检测到的图像的“实时”跟踪。但一次可以追踪的数量是有限制的,因此本建议的其余部分可能仍然适用。

这并不意味着您不能放置看起来“跟踪”世界空间中的静态位置的内容,即随着相机的移动而在屏幕上移动以跟随它。

但这确实意味着,如果您尝试执行依赖于图像位置高精度实时估计的操作,您的用户体验可能会受到影响。因此,不要尝试在你的画作周围放置虚拟框架,或者用动画版本替换画作。但有一个带有箭头的文本标签roughly图像在太空中的位置非常棒。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 ARKit 1.5 中初始检测后跟踪图像锚点? 的相关文章

  • 在故事板中将 UITableView 的 rowHeight 设置为 UITableViewAutomaticDimension ?

    在 Xcode 6 中创建 iOS 8 应用程序时 如何设置 UITableViewrowHeight to UITableViewAutomaticDimension In WWDC 2014 第 226 场会议 表和集合视图中的新增功能
  • 从 IOS 应用程序注销的完美方法是什么?

    下面的代码可以工作 但有一个错误 场景是 我首先登录进入应用程序系统 登录成功后 应用程序将设置 UserDefaults UserId 之后 我可以使用存储的 UserId 导航应用程序视图 一旦我进入设置和选项卡注销 这将清除 User
  • 在 IOS 中从 iPhone 删除资产(图片或视频)

    我正在开发一个 Iphone 应用程序 我可以使用 Assetslibrary 枚举资产并将它们加载到表视图中 用户可以在应用程序中删除一行 图片 视频 但如何直接从我的应用程序更新 Iphone 相册 否则 刷新时 表视图将重新加载之前删
  • Socket.io 400(错误请求)

    我的服务器上有这段代码 var express require express var routes require routes var user require routes user var http require http var
  • iOS 上的 OpenCV - VideoCapture 属性始终返回 1

    我一直在尝试构建一个简单的 OpenCV iOS 应用程序 该应用程序从捆绑包中加载视频并查询其帧数 持续时间等 然后它将尝试从中获取各个帧 不幸的是 当我使用VideoCapture类中 所有属性返回值 1 然后我尝试导航到frame 1
  • 在 hooks 文件夹中使用节点脚本时,cordova 插件安装问题

    Cordova 3 4 hooks 未在 iOS 中正确安装提到的插件 我正在添加install plugins js进入文件夹project project root hooks after platform add其中有以下代码 usr
  • 使 iOS 应用程序与 iPhone 6 和 iPhone 6 尺寸兼容 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我创建了一个应用程序 其中使用 xib 进行布局 目前我使用两种不同的 xib 一种用于iPhone4 320 480 一种用于iPh
  • 在 iOS 中使用 FB SDK 是否需要 Facebook 的成功审核?

    现在我需要使用Facebook SDK来自我的 iOS 应用程序中的 Facebook 所以我填写了有关我的应用程序的信息developer facebook com应用程序详细信息 但是 当我用我的设备测试我的应用程序时 我可以发布到 F
  • 我们能否检测用户是否通过主页按钮或锁定按钮离开而没有监听 darwin 通知?

    我最近向应用程序商店提交了一个新的二进制文件并将其发送以供审核 但它立即被拒绝并显示以下消息 不支持的操作 不允许应用程序监听设备锁定通知 经过一番挖掘后 我发现我们无法使用 com apple springboard lockstate
  • 如何右对齐 UILabel?

    Remark 实施 myLabel textAlignment right does not解决了我的问题 这不是我所要求的 我想要实现的是让标签对齐右对齐 为了更清楚地说明 这就是如何left对齐外观 就是这样justify对齐外观 if
  • 通过 renderInContext 定位要绘制的视图:

    我想画一个UIView在我目前的CGGraphicsContext 我画的是UIView via renderInContext 但它的位置不正确 始终位于左上角 我拥有所有的价值观UIView可用于绘制UIView CGRect fram
  • Swift 3 中的 JSON 解析

    有没有人能够找到一种在 Swift 3 中解析 JSON 文件的方法 我已经能够返回数据 但在将数据分解为特定字段时我没有成功 我会发布示例代码 但我已经尝试了很多不同的方法但没有成功 并且没有保存任何代码 我想要解析的基本格式是这样的 提
  • 调用 SwiftUI 中位置 #11、#12 处的额外参数 [重复]

    这个问题在这里已经有答案了 我在 SwiftUI 中的切换开关上不断收到 调用中位置 11 12 处有额外参数 错误 我见过其他人有 调用中的额外参数 错误 但答案似乎没有帮助 另外 我的错误是 位置 11 12 我还没有看到其他人发生这种
  • 从 iOS 13 开始安排 iOS 后台任务

    我正在实现用于更新数据的BackgroundTasks 框架 但我遇到了以下问题 无法计划刷新App 错误域 BGTaskSchedulerErrorDomain代码 1 空 无法安排数据提取 Error Domain BGTaskSche
  • 查找已用应用程序名称的捆绑包/开发人员

    我正在尝试将应用程序上传到应用程序商店并收到以下错误 很容易理解 The App Name you have entered has already been used 该应用程序不在 iTunes 上 有什么方法可以找出谁拥有该应用程序或
  • 以编程方式从底部裁剪图像

    我正在开发自定义相机应用程序 一切进展顺利 但我在从底部裁剪图像时遇到了问题 即 裁剪后的图像与原始图像具有完全相同的宽度 但高度将为原始图像的 1 3 并且必须从底部开始 斯威夫特3解决方案 func cropBottomImage im
  • 沙盒尝试恢复消耗性 IAP

    我一直在尝试在 iOS 上测试一些消耗性 IAP 但遇到了一个奇怪的错误 弹出一条警报 其中包含以下文本 此应用内购买已被购买 它将恢复为 自由的 环境 沙盒 我已经检查过 并且确定我的 IAP 可以在 iTunesConnect 中使用
  • Xcode 10 Beta 5 — clang:错误:链接器命令失败,退出代码为 1

    有人可以帮我吗 我的项目一切正常 但更新到 Xcode10 Beta5 后 尝试在 iPhone 上运行该应用程序时出现此错误 然而模拟器可以工作 请帮助我 我已经对这个问题进行了网络搜索并发现this https stackoverflo
  • XCode 4.5 给我“SenTestingKit/SenTestKit.h”文件未找到,但适用于 4.4.1

    我刚刚安装了 XCode 4 5 它在我现有的项目之一上给了我一个 SenTestingKit SenTestingKit h 文件未找到错误 此错误仅发生在 XCode 4 5 中 但它在 4 4 1 上编译正常 我已经检查过SenTes
  • iOS 电池监控 Swift

    我已将监控设置为启用 但模拟器和设备中的电池电量仍然为 1 UIDevice currentDevice batteryMonitoringEnabled true var level UIDevice currentDevice batt

随机推荐