ARKit 图像检测和从 Assets.xcassets 添加图像

Posted

技术标签:

【中文标题】ARKit 图像检测和从 Assets.xcassets 添加图像【英文标题】:ARKit Image Detection and Add Image From Assets.xcassets 【发布时间】:2020-10-05 17:43:40 【问题描述】:

我正在使用从 Apple 开发者网站下载的关于 AR 图像检测的代码。一旦检测到图像,我正在尝试对其进行修改以在 Resources/Assets.xcassets 的 AR 资源文件夹中显示特定图像。我看到 2 年前发布了一个类似的问题,我尝试了一个唯一的答案,但没有成功。任何人都可以帮忙吗?谢谢!

导入 ARKit 导入场景套件 导入 UIKit

类 ViewController: UIViewController, ARSCNViewDelegate

@IBOutlet var sceneView: ARSCNView!

@IBOutlet weak var blurView: UIVisualEffectView!

/// The view controller that displays the status and "restart experience" UI.
lazy var statusViewController: StatusViewController = 
    return children.lazy.compactMap( $0 as? StatusViewController ).first!
()

/// A serial queue for thread safety when modifying the SceneKit node graph.
let updateQueue = DispatchQueue(label: Bundle.main.bundleIdentifier! +
    ".serialSceneKitQueue")

/// Convenience accessor for the session owned by ARSCNView.
var session: ARSession 
    return sceneView.session


// MARK: - View Controller Life Cycle

override func viewDidLoad() 
    super.viewDidLoad()

    sceneView.delegate = self
    sceneView.session.delegate = self

    // Hook up status view controller callback(s).
    statusViewController.restartExperienceHandler =  [unowned self] in
        self.restartExperience()
    


override func viewDidAppear(_ animated: Bool) 
    super.viewDidAppear(animated)

    // Prevent the screen from being dimmed to avoid interuppting the AR experience.
    UIApplication.shared.isIdleTimerDisabled = true

    // Start the AR experience
    resetTracking()


override func viewWillDisappear(_ animated: Bool) 
    super.viewWillDisappear(animated)

    session.pause()


// MARK: - Session management (Image detection setup)

/// Prevents restarting the session while a restart is in progress.
var isRestartAvailable = true

/// Creates a new AR configuration to run on the `session`.
/// - Tag: ARReferenceImage-Loading
func resetTracking() 

    guard let referenceImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else 
        fatalError("Missing expected asset catalog resources.")
    

    let configuration = ARWorldTrackingConfiguration()
    configuration.detectionImages = referenceImages
    session.run(configuration, options: [.resetTracking, .removeExistingAnchors])

    statusViewController.scheduleMessage("Look around to detect images", inSeconds: 7.5, messageType: .contentPlacement)


// 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)
        let planeNode = SCNNode(geometry: plane)
        planeNode.opacity = 0.25

        /*
         `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.
         */
        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.
         */
        planeNode.runAction(self.imageHighlightAction)
        plane.materials = [SCNMaterial()]
        plane.materials[0].diffuse.contents = UIImage(named: "Macbook 12-inch")

        // Add the plane visualization to the scene.
        node.addChildNode(planeNode)



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




var imageHighlightAction: SCNAction 
    return .sequence([
        .wait(duration: 0.25),
        .fadeOpacity(to: 0.85, duration: 0.25),
        .fadeOpacity(to: 0.15, duration: 0.25),
        .fadeOpacity(to: 0.85, duration: 0.25),
        .fadeOut(duration: 0.5),
        .removeFromParentNode()
    ])

【问题讨论】:

【参考方案1】:

在 Xcode 的 Assets 文件夹中,单击 + 按钮并为参考图像创建一个文件夹(使用.png.jpg 格式)。在 Xcode 的目录中,此文件夹将获得 .arresourcegroup 扩展名。

//      AR and Textures –> AR Resource Group

您可以重命名此文件夹。无需将高分辨率图像放入此文件夹中。每个图像的适当分辨率为 400x400。放在那里不超过100张图片。就是这样。

您的代码可能如下所示:

guard let images = ARReferenceImage.referenceImages(
                                               inGroupNamed: "AR Resources",
                                                     bundle: nil)
else  return 

let config = ARWorldTrackingConfiguration()
config.detectionImages = images
config.maximumNumberOfTrackedImages = 3

arView.session.run(config, options: [])

【讨论】:

以上是关于ARKit 图像检测和从 Assets.xcassets 添加图像的主要内容,如果未能解决你的问题,请参考以下文章

结合 CoreML 对象检测和 ARKit 2D 图像检测

ARKit 可以将特定表面检测为平面吗?

ARKit 显示损坏的 UIWebView

ARKit 无法识别参考图像

ARKit 中的 ChromaKey 视频

向 ARKit 添加自定义视图