【VP开发如此简单】Vision pro 实现图片跟踪

在这里插入图片描述

使用vision pro实现图片识别,真的很简单。本文阅读约3分钟,读完你就能复刻一个在visionpro上图片识别的app。

创建项目

首先创建VP项目
在这里插入图片描述

在项目中选择Window,空间渲染选择realityKit,沉浸空间选择混合。Mixed支持窗口和全景融合。Include Tests可选可不选。

设置Image Tracker

这里随便找一张图片即可,比如我们使用下面的图片
在这里插入图片描述

在Xcode中,选择Assets。默认是没有图片集合的,因此我们点击Assets窗口下面的+,在选中+/AR and Textures/Texture Set。
在这里插入图片描述

添加图片到1x中。
在这里插入图片描述

Image Set方便我们直接方便通过代码在程序包体中加载图片。IOS中的图片加载细节参考:https://juejin.cn/post/6844903978262773774

添加模型

模型可以直接从Apple的测试模型网站中获得。https://developer.apple.com/jp/augmented-reality/quick-look/
这个网站中提供了多个USDZ的模型下载地址。
在这里插入图片描述

这里我们下载小飞机模型文件。下载完成后,将下载好的usdz文件直接拖拽到项目中即可。

编写代码

import SwiftUI

@main
struct VisionOSImageTrackingSampleApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }

        ImmersiveSpace(id: "ImmersiveSpace") {
            ImageTrackingView()
        }
    }
}

代码中ContentView是我们等会要声明的面板类的描述,而ImageTrackingView是在空间中的自由画面的类描述。下面对ContentView的内容进行实现。创建一个新的脚本ContentView.swift在脚本中添加如下脚本。

import SwiftUI
import RealityKit
import RealityKitContent

struct ContentView: View {

    @State private var showImmersiveSpace = false
    @State private var immersiveSpaceIsShown = false

    @Environment(\.openImmersiveSpace) var openImmersiveSpace
    @Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace

    var body: some View {
        VStack {
            Model3D(named: "toy_biplane_idle")
                .padding(.bottom, 50)

            Text("Image Tracking Sample")

            Toggle("Image Tracking Immersive Space", isOn: $showImmersiveSpace)
                .toggleStyle(.button)
                .padding(.top, 50)
        }
        .padding()
        .onChange(of: showImmersiveSpace) { _, newValue in
            Task {
                if newValue {
                    switch await openImmersiveSpace(id: "ImmersiveSpace") {
                    case .opened:
                        immersiveSpaceIsShown = true
                    case .error, .userCancelled:
                        fallthrough
                    @unknown default:
                        immersiveSpaceIsShown = false
                        showImmersiveSpace = false
                    }
                } else if immersiveSpaceIsShown {
                    await dismissImmersiveSpace()
                    immersiveSpaceIsShown = false
                }
            }
        }
    }
}

#Preview(windowStyle: .automatic) {
    ContentView()
}

创建一个ImageTrackingView.swift脚本,复制下面代码进去。

import ARKit
import SwiftUI
import RealityKit

struct ImageTrackingView: View {
    
    @State private var imageTrackingProvider:ImageTrackingProvider?
    @State private var entityMap: [UUID: Entity] = [:]
    @State private var contentEntity: Entity?
    private let session = ARKitSession()
    
    var body: some View {
        RealityView { content in
            contentEntity = try! await Entity(named: "toy_biplane_idle")
            content.add(contentEntity!)
        }.task {
            await loadImage()
            await runSession()
            await processImageTrackingUpdates()
        }
    }
    
    func loadImage() async {
        let uiImage = UIImage(named: "oneplanet_applevisionpro_marker")
        let cgImage = uiImage?.cgImage
        let referenceImage = ReferenceImage(cgimage: cgImage!, physicalSize: CGSize(width: 1920, height: 1005))
        imageTrackingProvider = ImageTrackingProvider(
            referenceImages: [referenceImage]
        )
    }
    
    func runSession() async {
        do {
            if ImageTrackingProvider.isSupported {
                try await session.run([imageTrackingProvider!])
                print("image tracking initializing in progress.")
            } else {
                print("image tracking is not supported.")
            }
        } catch {
            print("Error during initialization of image tracking. [\(type(of: self))] [\(#function)] \(error)")
        }
    }
    
    func processImageTrackingUpdates() async {
        for await update in imageTrackingProvider!.anchorUpdates {
            updateImage(update.anchor)
        }
    }
    
    private func updateImage(_ anchor: ImageAnchor) {
        if entityMap[anchor.id] == nil {
            entityMap[anchor.id] = contentEntity
        }
        if anchor.isTracked {
            contentEntity!.isEnabled = true
            let transform = Transform(matrix: anchor.originFromAnchorTransform)
            entityMap[anchor.id]?.transform.translation = transform.translation
            entityMap[anchor.id]?.transform.rotation = transform.rotation
        } else {
            contentEntity!.isEnabled = false
        }
    }
}

#Preview {
    ImageTrackingView()
}

脚本的内容很容易理解。首先来看ContentView中,VStack描述界面的布局。在最上面绘制了一个三维模型。中间声明了一个文本内容,下面为一个选择按钮。

VStack {
    Model3D(named: "toy_biplane_idle")
        .padding(.bottom, 50)

    Text("Image Tracking Sample")

    Toggle("Image Tracking Immersive Space", isOn: $showImmersiveSpace)
        .toggleStyle(.button)
        .padding(.top, 50)
}

ImageTrackingView的内容也很好理解。
首先加载Texture Set中的图片

 let uiImage = UIImage(named: "oneplanet_applevisionpro_marker")

然后作为ImageTrackingProvider的图片源传入。

imageTrackingProvider = ImageTrackingProvider(
            referenceImages: [referenceImage]
        )

最后将图片获取到的空间位姿传给模型,实现模型和图片的匹配。

let transform = Transform(matrix: anchor.originFromAnchorTransform)
entityMap[anchor.id]?.transform.translation = transform.translation
entityMap[anchor.id]?.transform.rotation = transform.rotation

声明

首先声明:参考文章
其次声明:首先vp的模拟器目前是不支持手势、平面、图片等对象的追踪,因此希望开发这两个效果的朋友,需要使用真机进行验证。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值