从应用程序向 ARKit 添加参考图像

Adding reference images to ARKit from the app

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

如果您查看以下文档: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参数指的是:

A file URL for the temporary file. Because the file is temporary, you must either open the file for reading or move it to a permanent location in your app’s sandbox container directory before returning from this delegate method.

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

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

}

现在我们已经下载了图像,然后我们将创建一个函数来检索这些图像和 return 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{ [=15=].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])

希望对您有所帮助...