Добавление эталонных изображений в ARKit из приложения - PullRequest
0 голосов
/ 03 сентября 2018

Я учился использовать ARKIT, и мне было интересно, есть ли способ добавить опорные изображения (изображения, которые будут распознаны) из приложения (в зависимости от выбора пользователя). Согласно документации, это можно сделать, добавив эталонные изображения к активам (на этапе разработки), что ограничивает удобство использования приложения. Мне было интересно, есть ли способ, где мы можем скачать / добавить эти изображения на основе выбора пользователя и использовать эти изображения в качестве справочного изображения (в приложении).

1 Ответ

0 голосов
/ 04 сентября 2018

Если вы посмотрите на документацию по: 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

}

Теперь мы загрузили изображения, которые мы затем создали бы, чтобы получить их и вернуть набор ARReferenceImage, необходимый для ARWorldTrackingConfiguration.

/// 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])

Надеюсь, это поможет ...

...