【问题标题】:Adding reference images to ARKit from the app从应用程序向 ARKit 添加参考图像
【发布时间】:2018-09-04 05:44:23
【问题描述】:

我正在学习使用 ARKIT,我想知道是否有办法从应用程序中添加参考图像(要识别的图像)(基于用户的选择)。根据文档,这可以通过将参考图像添加到资产(在开发阶段)来完成,这会限制应用程序的可用性。我想知道是否有一种方法可以让我们根据用户的选择下载/添加这些图像并将这些图像用作参考图像(在应用程序内)。

【问题讨论】:

    标签: ios swift arkit


    【解决方案1】:

    如果您查看以下文档:ARReferenceImage,您会注意到手动生成 ARReferenceImages 的方法有两种:

    init(CGImage, orientation: CGImagePropertyOrientation, physicalWidth: CGFloat)
    init(CVPixelBuffer, orientation: CGImagePropertyOrientation, physicalWidth: CGFloat)
    

    如果您从服务器下载,则需要第一个,这需要使用CGImage

    因此,您下载的任何图像都需要使用此方法进行转换。

    要首先从服务器下载图像,您需要使用URLSession 将这些图像下载到您设备上的某个位置,例如Documents Directory

    一个简单的例子如下所示:

    /// Downloads An Image From A Remote URL
    func downloadImageTask(){
    
            //1. Get The URL Of The Image
            guard let url = URL(string: "http://www.blackmirrorz.tech/images/BlackMirrorz/blackMirrorzLogo.png") else { return }
    
            //2. Create The Download Session
            let downloadSession = URLSession(configuration: URLSession.shared.configuration, delegate: self, delegateQueue: nil)
    
            //3. Create The Download Task & Run It
            let downloadTask = downloadSession.downloadTask(with: url)
            downloadTask.resume()      
        }
    
     }
    

    创建 URLSession 后,您需要注册 URLSessionDownloadDelegate 和以下方法:

    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)
    

    其中location 参数指的是:

    临时文件的文件 URL。因为文件是临时的,你 必须打开文件进行读取或将其移动到永久 返回之前在您应用的沙箱容器目录中的位置 来自这个委托方法。

    因此,您的回调可能如下所示:

    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
    
        //1. Create The Filename
        let fileURL = getDocumentsDirectory().appendingPathComponent("image.png")
    
        //2. Copy It To The Documents Directory
        do {
            try FileManager.default.copyItem(at: location, to: fileURL)
    
            print("Successfuly Saved File \(fileURL)")
    
        } catch {
    
            print("Error Saving: \(error)")
        }
    
    }
    

    我使用以下函数获取用户Documents Directory

    /// Returns The Documents Directory
    ///
    /// - Returns: URL
    func getDocumentsDirectory() -> URL {
    
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    let documentsDirectory = paths[0]
    return documentsDirectory
    
    }
    

    现在我们已经下载了图像,然后我们将创建一个函数来检索这些图像并返回ARWorldTrackingConfiguration 所需的一组ARReferenceImage

    /// Creates A Set Of ARReferenceImages From All PNG Content In The Documents Directory
    ///
    /// - Returns: Set<ARReferenceImage>
    func loadedImagesFromDirectoryContents() -> Set<ARReferenceImage>?{
    
        var index = 0
        var customReferenceSet = Set<ARReferenceImage>()
        let documentsDirectory = getDocumentsDirectory()
    
        do {
    
            let directoryContents = try FileManager.default.contentsOfDirectory(at: documentsDirectory, includingPropertiesForKeys: nil, options: [])
    
            let filteredContents = directoryContents.filter{ $0.pathExtension == "png" }
    
            filteredContents.forEach { (url) in
    
                do{
    
                    //1. Create A Data Object From Our URL
                    let imageData = try Data(contentsOf: url)
                    guard let image = UIImage(data: imageData) else { return }
    
                    //2. Convert The UIImage To A CGImage
                    guard let cgImage = image.cgImage else { return }
    
                    //3. Get The Width Of The Image
                    let imageWidth = CGFloat(cgImage.width)
    
                    //4. Create A Custom AR Reference Image With A Unique Name
                    let customARReferenceImage = ARReferenceImage(cgImage, orientation: CGImagePropertyOrientation.up, physicalWidth: imageWidth)
                    customARReferenceImage.name = "MyCustomARImage\(index)"
    
                    //4. Insert The Reference Image Into Our Set
                    customReferenceSet.insert(customARReferenceImage)
    
                    print("ARReference Image == \(customARReferenceImage)")
    
                    index += 1
    
                }catch{
    
                    print("Error Generating Images == \(error)")
    
                }
    
            }
    
        } catch {
    
            print("Error Reading Directory Contents == \(error)")
    
        }
    
        //5. Return The Set
        return customReferenceSet
    }
    

    因此,要将最后一个函数落实到位,您需要执行以下操作:

    let detectionImages = loadedImagesFromDirectoryContents()
    
    configuration.detectionImages = detectionImages
    
    augmentedRealitySession.run(configuration, options: [.resetTracking, .removeExistingAnchors])
    

    希望对你有帮助...

    【讨论】:

    • :) 很高兴它有帮助 :)
    • @BlackMirrorz 为什么我们每次都需要下载它有没有办法只下载一次并使用。
    • ARReferenceImage 的属性 physicalWidth 是您希望探测器搜索的物理尺寸(以米为单位),而不是图像的宽度(以像素为单位)。
    • 我不知道你是如何使用customReferenceSet...
    猜你喜欢
    • 2019-03-06
    • 2021-12-26
    • 2018-08-06
    • 2020-10-05
    • 2018-07-30
    • 2023-03-10
    • 1970-01-01
    • 2018-09-17
    • 1970-01-01
    相关资源
    最近更新 更多