我正在学习使用ARKIT,我想知道是否有一种方法可以从应用程序内(根据用户的选择)添加参考图像(要识别的图像)。根据文档,这可以通过在开发阶段将参考图像添加到资产中来完成,这会限制应用程序的可用性。我想知道是否有一种方法可以根据用户的选择下载/添加这些图像并将这些图像用作参考图像(在应用程序内)。
答案 0 :(得分: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
}
现在我们已经下载了图像,然后创建一个函数来检索这些图像并返回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])
希望有帮助...