是否可以使用从 iOS 11.3.1 上的图像以编程方式创建的 ARReferenceImage 对象

Is it possible to use ARReferenceImage objects created programatically from the images on iOS 11.3.1

我最近用原生的 ARKit 替换了笨重的 OpenCV 来进行图像检测和跟踪。我要跟踪的图像从 Web 服务下载并存储在本地。我正在使用以下代码从它们创建 ARImageReference 对象:

guard
    let image = UIImage(contentsOfFile: imageLocalPath),
    let cgImage = image.cgImage
else {
    return nil
}

return ARReferenceImage(cgImage, orientation: .up, physicalWidth: 0.12)

宽度小,因为图片也没有那么大,每张大约180 x 240像素,但打印的可能更大。

根据当前 iOS 版本配置的会话,因为 ARImageTrackingConfiguration 不适用于 iOS 11:

private lazy var configuration: ARConfiguration = {
    if #available(iOS 12.0, *),
        ARImageTrackingConfiguration.isSupported {
        return ARImageTrackingConfiguration()
    }

    return ARWorldTrackingConfiguration()
}()

if #available(iOS 12.0, *),
    let imagesTrackingConfig = configuration as? ARImageTrackingConfiguration {
    imagesTrackingConfig.trackingImages = referenceImages
} else if let worldTrackingConfig = configuration as? ARWorldTrackingConfiguration {
    worldTrackingConfig.detectionImages = referenceImages
}

session.run(configuration, options: [.resetTracking, .removeExistingAnchors])

即使我使用 ARWorldTrackingConfiguration,上面的代码也适用于 iOS 版本 12 和 13。 ARKit 正确检测到的图像。但是当我在 iOS 11.3.1 上尝试 运行 它时,应用程序立即崩溃并出现以下错误:

Assert: /BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleCV3D/AppleCV3D-1.13.11/library/VIO/OdometryEngine/src/FrameDownsampleNode/FrameDownsampler.cpp, 62: std::abs(static_cast(aspect_1) - static_cast(src_frame.image.width * output_frame_height_)) < max_slack (lldb)

12.0 以下的 iOS 版本是否无法以编程方式创建动态标记,或者我做错了什么?不幸的是,我无法找到有关特定版本的任何信息。任何反馈表示赞赏。谢谢。

所以过了一段时间,我终于找到了问题的根源,所以我把它贴在这里,因为它可能对遇到同样问题的其他人有用。

答案是 YES,可以通过编程方式创建 ARReferenceImage 对象,并在 iOS 11.3.1 上使用它们进行图像检测。

我的问题出在源图像本身,看起来 CGImage 的比例不当导致了崩溃。从 API 下载的图像为 180x240。通过检查用于创建 ARReferenceImageCGImage 的大小,我意识到它们没有正确缩放,所以 CGImage 大小与源 [=16] 相同=].

我决定尝试使用以下方法重新绘制图像:

func getRedrawnCgImage(_ originalImage: UIImage) -> CGImage? {
    guard let cgImage = originalImage.cgImage else { return nil }

    let size = CGSize(width: cgImage.width, height: cgImage.height)
    
    UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
    originalImage.draw(in: CGRect(origin: .zero, size: size))
    let redrawnImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return redrawnImage?.cgImage
}

结果 CGImage 的大小为 540x720,因此原始大小应为 x3。通过使用那些重新绘制的图像,我摆脱了崩溃,但这是一种解决方法,而不是目前的正确解决方案。