You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

ARKit 1.5 图像识别:固定显示UI元素的解决方案

Hey there! I get exactly what you're dealing with—ARKit 1.5's image recognition has that annoying limitation where ARImageAnchor doesn't track after initial detection, and it lacks the center property that ARPlaneAnchor has. Let's break down how to fix this and get those UI elements (images, buttons, labels) staying put like you want.

First, Understand the Limitation

ARKit 1.5 only performs one-time image detection, not continuous tracking. That means once the anchor is added, it won't update as the camera moves or the image shifts. So we need to work around this by reusing the initial anchor's transform to lock our UI elements in place.

Solution 1: Lock 3D Content (SceneKit Nodes) to the Initial Anchor Position

If you're using SceneKit to display 3D content (like a plane with your UI rendered onto it), you can save the initial transform of the ARImageAnchor and force your node to stick to that position every frame.

Here's a code example:

import ARKit
import SceneKit

class ViewController: UIViewController, ARSCNViewDelegate {
    @IBOutlet var sceneView: ARSCNView!
    
    // Store the initial anchor transform and your custom node
    private var imageAnchorTransform: simd_float4x4?
    private var trackedContentNode: SCNNode?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        sceneView.delegate = self
        sceneView.scene = SCNScene()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        let configuration = ARImageTrackingConfiguration()
        // Add your reference images to the configuration
        guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else {
            fatalError("No reference images found")
        }
        configuration.trackingImages = referenceImages
        sceneView.session.run(configuration)
    }
    
    // Capture the initial anchor transform when the image is first detected
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let imageAnchor = anchor as? ARImageAnchor else { return }
        
        // Save the initial transform
        imageAnchorTransform = imageAnchor.transform
        
        // Create your custom content (e.g., a plane with a button texture, or a 3D label)
        let imageSize = imageAnchor.referenceImage.physicalSize
        let planeGeometry = SCNPlane(width: imageSize.width, height: imageSize.height)
        planeGeometry.firstMaterial?.diffuse.contents = UIImage(named: "your-ui-image")
        
        let planeNode = SCNNode(geometry: planeGeometry)
        planeNode.eulerAngles.x = -.pi / 2 // Rotate to match the image plane
        
        trackedContentNode = planeNode
        node.addChildNode(trackedContentNode!)
        
        // Optional: Set a timer to hide the plane after a set duration
        Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) { [weak self] _ in
            self?.trackedContentNode?.isHidden = true
        }
    }
    
    // Force the node to keep using the initial transform every frame
    func renderer(_ renderer: SCNSceneRenderer, didUpdate frame: ARFrame) {
        guard let initialTransform = imageAnchorTransform, let contentNode = trackedContentNode else { return }
        contentNode.transform = initialTransform
    }
}

Solution 2: Fix UIKit Elements (Buttons, Labels) to the Screen

If you want to display native UIKit elements (like a UIButton or UILabel) over the AR view, you can convert the initial anchor's 3D position to screen coordinates and update the UI's position every frame.

Add this to the previous example (or your existing code):

@IBOutlet var customButton: UIButton!

func renderer(_ renderer: SCNSceneRenderer, didUpdate frame: ARFrame) {
    guard let initialTransform = imageAnchorTransform else { return }
    
    // Extract the anchor's 3D position from its transform
    let anchorPosition = simd_float3(initialTransform.columns.3)
    // Convert 3D position to screen coordinates
    let screenPoint = sceneView.projectPoint(SCNVector3(anchorPosition))
    
    // Update the button's position (adjust for any offset you need)
    customButton.center = CGPoint(
        x: CGFloat(screenPoint.x),
        y: CGFloat(screenPoint.y)
    )
}

Key Notes

  • Since ARKit 1.5 doesn't track the image after initial detection, this method locks your UI to the first detected position. If the image moves, the UI won't follow—but this matches the "fixed display" behavior you're aiming for.
  • For the plane visibility timer, adjust the TimeInterval value to control how long the plane stays visible after detection.

内容的提问来源于stack exchange,提问作者magohamote

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:06:43