将CoreML与ARKit结合使用

5
我正在尝试在我的项目中使用Apple 网站 上提供的inceptionV3模型,将CoreML和ARKit相结合。
我从ARKit的标准模板(Xcode 9 beta 3)开始。
我不是实例化一个新的相机会话,而是重用了由ARSCNView启动的会话。
在我的viewDelegate的末尾,我编写了以下内容:
sceneView.session.delegate = self

我会把我的视图控制器扩展,以符合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、像素缓冲区为<RGB,<299,299>的像素缓冲区。
虽然不推荐这样做,但我想我只需调整我的帧大小,然后尝试从中获取预测。我正在使用此函数进行调整大小(从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方法,错误完全相同。

编辑2: 因此,我将像素格式更改为kCVPixelFormatType_32BGRA(而不是传递给resizePixelBuffer的pixelBuffer的相同格式)。

let pixelFormat = kCVPixelFormatType_32BGRA // line 48

我不再有错误了。但是一旦我尝试进行预测,AVCaptureSession就会停止。看起来我遇到了Enric_SA在苹果开发者论坛上遇到的相同问题。 编辑3:所以我尝试实现rickster的解决方案。对于inceptionV3效果很好。我想尝试一个特征观察(VNClassificationObservation)。此时,使用TinyYolo无法正常工作。绑定不正确。正在努力解决它。

迄今为止,我会推荐的是一篇博客(http://machinethink.net/blog/yolo-coreml-versus-mps-graph/)和相关的代码库(https://github.com/hollance/YOLO-CoreML-MPSNNGraph)。是的,这与YOLO和CoreML(以及相当深入的ML)有关,但该代码具有将UIImage调整为224x224并返回CVPixelBuffer的好方法。我在两天前在另一个问题上发表了评论 - 您可以通过搜索“pixel buffer”和“Swift”,按问题日期排序来找到该代码。 - user7014451
@dfd 尝试过了,结果(错误)是一样的。该项目直接使用相机会话,而不尝试重用 ARSCNView 会话。 - Swift Rabbit
1个回答

8
不要自己处理图像并将其提供给Core ML,使用Vision。 (不,不是那个。这个。)Vision接受ML模型和多种图像类型(包括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)
    }
}

请参考这篇答案以获取更多相关建议。


你好@rickster。使用VNClassificationObservation一切正常,但是我在使用来自tiny-yolo示例(https://github.com/hollance/YOLO-CoreML-MPSNNGraph)的VNCoreMLFeatureValueObservation时遇到了问题。我的边界框似乎大小不对。这很奇怪,但我还无法找出原因。 - Swift Rabbit
1
很难在没有更详细的诊断信息的情况下确定(即使有了这些信息,这也不是我的专长范围),但如果我必须猜测的话,可能与像素尺寸、归一化图像坐标和裁剪/缩放选项有关,还有一些可能性是视频清晰孔径也可能导致问题。 - rickster
@ina:自那时起,我没有花太多时间在这个问题上。但我的最佳猜测是将请求结果转换为[ VNCoreMLFeatureValueObservation ],没有正确解析观察结果的 multiArrayValue。这可能是导致边界框偏移的原因。但我不确定,我需要将数组通过矩阵或类似方法进行运行才能确认。 - Swift Rabbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接