【发布时间】:2018-09-04 05:44:23
【问题描述】:
我正在学习使用 ARKIT,我想知道是否有办法从应用程序中添加参考图像(要识别的图像)(基于用户的选择)。根据文档,这可以通过将参考图像添加到资产(在开发阶段)来完成,这会限制应用程序的可用性。我想知道是否有一种方法可以让我们根据用户的选择下载/添加这些图像并将这些图像用作参考图像(在应用程序内)。
【问题讨论】:
我正在学习使用 ARKIT,我想知道是否有办法从应用程序中添加参考图像(要识别的图像)(基于用户的选择)。根据文档,这可以通过将参考图像添加到资产(在开发阶段)来完成,这会限制应用程序的可用性。我想知道是否有一种方法可以让我们根据用户的选择下载/添加这些图像并将这些图像用作参考图像(在应用程序内)。
【问题讨论】:
如果您查看以下文档: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])
希望对你有帮助...
【讨论】:
ARReferenceImage 的属性 physicalWidth 是您希望探测器搜索的物理尺寸(以米为单位),而不是图像的宽度(以像素为单位)。
customReferenceSet...