结合 CoreML 和 ARKit
Posted
技术标签:
【中文标题】结合 CoreML 和 ARKit【英文标题】:Combining CoreML and ARKit 【发布时间】:2017-12-26 13:35:12 【问题描述】:我正在尝试使用 Apple website 上给定的 inceptionV3 模型在我的项目中。
我从 ARKit 的标准模板开始(Xcode 9 beta 3)
我没有启动新的相机会话,而是重用 ARSCNView 已启动的会话。
在我的 viewDelegate 结束时,我写道:
sceneView.session.delegate = self
然后我扩展我的 viewController 以符合 ARSessionDelegate 协议(可选协议)
// MARK: ARSessionDelegate
extension ViewController: ARSessionDelegate
func session(_ session: ARSession, didUpdate frame: ARFrame)
do
let prediction = try self.model.prediction(image: frame.capturedImage)
DispatchQueue.main.async
if let prob = prediction.classLabelProbs[prediction.classLabel]
self.textLabel.text = "\(prediction.classLabel) \(String(describing: prob))"
catch let error as NSError
print("Unexpected error ocurred: \(error.localizedDescription).")
起初我尝试了该代码,但后来注意到 inception 需要一个 Image 类型的像素缓冲区。 。
虽然没有重新开始,但我想我会调整框架的大小,然后尝试从中获得预测。我正在使用这个函数调整大小(取自https://github.com/yulingtianxia/Core-ML-Sample)
func resize(pixelBuffer: CVPixelBuffer) -> CVPixelBuffer?
let imageSide = 299
var ciImage = CIImage(cvPixelBuffer: pixelBuffer, options: nil)
let transform = CGAffineTransform(scaleX: CGFloat(imageSide) / CGFloat(CVPixelBufferGetWidth(pixelBuffer)), y: CGFloat(imageSide) / CGFloat(CVPixelBufferGetHeight(pixelBuffer)))
ciImage = ciImage.transformed(by: transform).cropped(to: CGRect(x: 0, y: 0, width: imageSide, height: imageSide))
let ciContext = CIContext()
var resizeBuffer: CVPixelBuffer?
CVPixelBufferCreate(kCFAllocatorDefault, imageSide, imageSide, CVPixelBufferGetPixelFormatType(pixelBuffer), nil, &resizeBuffer)
ciContext.render(ciImage, to: resizeBuffer!)
return resizeBuffer
不幸的是,这还不足以让它发挥作用。这是捕获的错误:
Unexpected error ocurred: Input image feature image does not match model description.
2017-07-20 AR+MLPhotoDuplicatePrediction[928:298214] [core]
Error Domain=com.apple.CoreML Code=1
"Input image feature image does not match model description"
UserInfo=NSLocalizedDescription=Input image feature image does not match model description,
NSUnderlyingError=0x1c4a49fc0 Error Domain=com.apple.CoreML Code=1
"Image is not expected type 32-BGRA or 32-ARGB, instead is Unsupported (875704422)"
UserInfo=NSLocalizedDescription=Image is not expected type 32-BGRA or 32-ARGB, instead is Unsupported (875704422)
不确定我能从这里做什么。
如果有更好的建议将两者结合起来,我会全力以赴。
编辑:我也尝试了@dfd建议的YOLO-CoreML-MPSNNGraph中的resizePixelBuffer方法,错误是完全一样的。
Edit2:所以我把像素格式改成了kCVPixelFormatType_32BGRA(和resizePixelBuffer中传入的pixelBuffer格式不一样)。
let pixelFormat = kCVPixelFormatType_32BGRA // line 48
我没有错误了。但是一旦我尝试做出预测, AVCaptureSession 就会停止。似乎我在 apple developers forum 上运行 Enric_SA 时遇到了同样的问题。
Edit3:所以我尝试实施 rickster 解决方案。与 inceptionV3 配合良好。我想尝试一个特征观察(VNClassificationObservation)。目前,它无法使用TinyYolo。边界是错误的。试图弄清楚。
【问题讨论】:
到目前为止,我给出的建议是博客 (machinethink.net/blog/yolo-coreml-versus-mps-graph) 和相关的 repo (github.com/hollance/YOLO-CoreML-MPSNNGraph)。是的,这与 YOLO 和 CoreML 一样多(并且对 ML 非常深入),但是代码有一个很好的方法来将 UIImage 调整为 224x224 并返回一个 CVPixelBuffer。大约 2 天前,我在这里评论了另一个问题 - 您可能会通过搜索“像素缓冲区”和“Swift”找到该代码,并按问题日期排序。 @dfd 试过了,结果(错误)是一样的。该项目直接使用相机会话,它不会尝试重用 ARSCNView 会话。 【参考方案1】:不要自己处理图像以将它们提供给 Core ML。使用Vision。 (不,不是那个。This one。)Vision 采用 ML 模型和多种图像类型中的任何一种 (including CVPixelBuffer
) 并自动将图像获取到正确的大小、纵横比和像素格式以供模型评估,然后给你模型的结果。
这是您需要的代码的粗略框架:
var request: VNRequest
func setup()
let model = try VNCoreMLModel(for: MyCoreMLGeneratedModelClass().model)
request = VNCoreMLRequest(model: model, completionHandler: myResultsMethod)
func classifyARFrame()
let handler = VNImageRequestHandler(cvPixelBuffer: session.currentFrame.capturedImage,
orientation: .up) // fix based on your UI orientation
handler.perform([request])
func myResultsMethod(request: VNRequest, error: Error?)
guard let results = request.results as? [VNClassificationObservation]
else fatalError("huh")
for classification in results
print(classification.identifier, // the scene label
classification.confidence)
请参阅this answer 到另一个问题以获取更多指示。
【讨论】:
你好@rickster。它适用于 VNClassificationObservation,但我直接从 tiny-yolo 示例 (github.com/hollance/YOLO-CoreML-MPSNNGraph) 遇到 VNCoreMLFeatureValueObservation 问题。就像我的边界框大小不合适。很奇怪,但我不知道为什么。 很难说没有更详细的诊断(即使那时它也有点超出我的管辖范围),但如果我不得不冒险猜测它可能与像素尺寸、标准化图像坐标与裁剪/比例有关选项,视频清洁光圈也有一些可能性。 @ina :从那以后我没有花太多时间研究它。但我最有根据的猜测是将请求结果转换为? [VNCoreMLFeatureValueObservation] 没有以应有的方式解析观察结果的 multiArrayValue。这可以解释为什么边界框是关闭的。不过我不确定,我必须通过矩阵或类似的东西来运行数组。以上是关于结合 CoreML 和 ARKit的主要内容,如果未能解决你的问题,请参考以下文章