iPad Swift Playgrounds中实现AR图像检测跟踪

c92c3178bab34c348c3fffbac1678114.gif

在Xcode中我们可以通过在Assets下创建”AR Resource Group"来添加需要检测与跟踪的图片(ARReferenceImage), 通过对每张图片的属性设定(如Name, Size, 和Units)以此来达到更好的显示效果。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP54mm54mbNjY2,size_20,color_FFFFFF,t_70,g_se,x_16watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP54mm54mbNjY2,size_20,color_FFFFFF,t_70,g_se,x_16 

但截至目前2022年3月10日, Swift Playgrounds Version 4.0.2还没有功能菜单创建AR Resource Group,也没有对图片属性添加的功能窗口。所以为了解决此问题,我们必须通过手动添加参考图像库,参考图片,以及参考图片属性来实现相同的功能,以下为实现过程。

1. 添加照片到资源文件

点击左侧“添加”- 选择“照片”,注意这里一定要添加格式为PNG或JPEG的图片,手机或ipad拍摄的照片格式为HEIF, 可以通过截屏来获取PNG格式。添加后,图片会在“资源”下显示,长按图片可以“重命名”为英文或拼音。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP54mm54mbNjY2,size_20,color_FFFFFF,t_70,g_se,x_16

2. 添加3D模型到“资源”文件

点击左侧“添加”- 选择“插入自”,选择你想要展示的格式为usdz的3D模型。添加完成后,模型文件会在左侧“资源”文件下显示。这里可以更改图片名称与相对应模型名称一致。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP54mm54mbNjY2,size_20,color_FFFFFF,t_70,g_se,x_16

 3. 创建参考图片库,生成参考图片,设置参考图片属性,添加参考图片到库,

        3.1 我们需要手动创建参考图片库.

var trackedImageLibs = Set()

        3.2 将图片转变为UIImage, 然后转变为CGImage,最后转变为ARReferenceImage, 并设置属性:朝向,实际宽度.

let teapotUIImage = UIImage(named: "teapot")
let carUIImage = UIImage(named: "toy_car")
let drummerUIImage = UIImage(named: "toy_drummer")let teapotRefImg = ARReferenceImage(teapotUIImage!.cgImage!, orientation: .up, physicalWidth: 0.075)
let carRefImg = ARReferenceImage(carUIImage!.cgImage!, orientation: .up, physicalWidth: 0.075)
let drummerRefImg = ARReferenceImage(drummerUIImage!.cgImage!, orientation: .up, physicalWidth: 0.075)

        3.3 给每一个ARReferenceImage的name属性一个值,这个值类型为Optional String. 注意这里的name和资源库里图片的名字是两个东西,如果你在Xcode中添加了参考图片,这里的name就是参考图片属性窗口里的name。如果你手动创建参考图片,这里的name默认值为nil。

teapotRefImg.name = "teapot"
carRefImg.name = "toy_car"
drummerRefImg.name = "toy_drummer"

        3.4 将所有参考图片添加进参考图片库

trackedImageLibs.insert(teapotRefImg)
trackedImageLibs.insert(carRefImg)
trackedImageLibs.insert(drummerRefImg)

4. 将我们创建的参考图片库分配给ARImageTrackingConfiguration里的trackingImages(跟踪图片库),因为ARKit只会把trackingImages库里的图片拿去与用户环境中的图片做检测和跟踪。

config.trackingImages = trackedImageLibs

5. 当ARKit检测到相关图片并生成ARImageAnchor时,可以利用ARImageAnchor的referenceImage属性里的name属性,用来加载与之对应的模型。

        5.1 如果检测到特征点相匹配的图片,生成ARImageAnchor

guard let imageAnchor = anchors[0] as? ARImageAnchor else {return}

        5.2 将ARImageAnchor里的参考图片里的名称分配给一个新的类型为String的常量

let referImageName: String = imageAnchor.referenceImage.name ?? "example"

        5.3 根据获得的参考图片名称,加载与之对应的模型

ModelEntity.loadModelAsync(named: referImageName)

优点补充:在swift playgrounds上编写AR应用可以及时预览所呈现效果,避免了在Xcode中需要连接真机安装部署才能测试,其次还避免了免费用户在Xcode每周开发安装App数量限制的问题(未来swift playgrounds会不会有限制,不知道,希望永远不会)

缺点补充:在Xcode中,上传的参考图像会被检测是否具有高对比,多特征等因素,从而指导开发者筛选调整出更容易检测和跟踪的参考图像,优化用户体验。而在swift playgrounds中,开发者目前只能通过自身经验去挑选一些对比度高,特征信息丰富的图片。

以下为完整代码:

import SwiftUI
import ARKit
import RealityKit
import Combinestruct ContentView: View {var body: some View {ZStack{ARViewContainer()}}
}struct ARViewContainer: UIViewRepresentable {func makeUIView(context: Context) -> ARView {let arView = ARView(frame: .zero)let config = ARImageTrackingConfiguration()var trackedImageLibs = Set()let teapotUIImage = UIImage(named: "teapot")let carUIImage = UIImage(named: "toy_car")let drummerUIImage = UIImage(named: "toy_drummer")let teapotRefImg = ARReferenceImage(teapotUIImage!.cgImage!, orientation: .up, physicalWidth: 0.075)let carRefImg = ARReferenceImage(carUIImage!.cgImage!, orientation: .up, physicalWidth: 0.075)let drummerRefImg = ARReferenceImage(drummerUIImage!.cgImage!, orientation: .up, physicalWidth: 0.075)teapotRefImg.name = "teapot"carRefImg.name = "toy_car"drummerRefImg.name = "toy_drummer"trackedImageLibs.insert(teapotRefImg)trackedImageLibs.insert(carRefImg)trackedImageLibs.insert(drummerRefImg)config.trackingImages = trackedImageLibsconfig.maximumNumberOfTrackedImages = 4arView.session.run(config, options: [])arView.session.delegate = arViewreturn arView}func updateUIView(_ uiView: UIViewType, context: Context) {}
}extension ARView: ARSessionDelegate {public func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {guard let imageAnchor = anchors[0] as? ARImageAnchor else {return}let imageAnchorEntity = AnchorEntity(anchor: imageAnchor)let referImageName = imageAnchor.referenceImage.name ?? "example"var cancellable: AnyCancellable? = nil cancellable = ModelEntity.loadModelAsync(named: referImageName).sink(receiveCompletion: { status inprint("Completion: \(status)")cancellable?.cancel()}, receiveValue: { entity inimageAnchorEntity.addChild(entity)})self.scene.addAnchor(imageAnchorEntity)}
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部