Swift中使用Vision框架调用CoreML模型时,如何获取MLMultiArray类型输出
Swift中使用Vision框架调用CoreML模型时,如何获取MLMultiArray类型输出
嘿,兄弟,我刚好碰到过一模一样的问题!你现在的问题出在没有正确识别Vision返回的观测对象类型——普通的VNObservation是个基类,根本装不下你的CoreML模型输出的MLMultiArray,你需要的是它的子类VNCoreMLFeatureValueObservation,这才是真正存储模型特征输出的对象。
直接给你修正核心代码,把你原来的VNCoreMLRequest回调部分换成下面这段:
let request = VNCoreMLRequest(model: model) { finishReq, err in // 第一步:把结果转换成正确的VNCoreMLFeatureValueObservation数组 guard let results = finishReq.results as? [VNCoreMLFeatureValueObservation] else { print("无法解析模型输出结果") return } // 第二步:取第一个观测结果(如果你的模型只有一个输出的话) guard let coreMLResult = results.first else { print("模型没有返回任何结果") return } // 第三步:从特征值中提取MLMultiArray guard let mlMultiArray = coreMLResult.featureValue.multiArrayValue else { print("无法将特征值转换为MLMultiArray格式") return } // 到这里你就成功拿到MLMultiArray了!接下来把它赋值给你的currentMLArray self.currentMLArray = mlMultiArray // 顺便把你的绘图逻辑移到这里来,确保拿到数据后再执行 DispatchQueue.main.async { [weak self] in guard let self = self, let mlArray = self.currentMLArray else { return } let aWidth = CGFloat(mlArray.shape[0].intValue) let aHeight = CGFloat(mlArray.shape[1].intValue) UIGraphicsBeginImageContext(CGSize(width: aWidth, height: aHeight)) guard let ctx = UIGraphicsGetCurrentContext() else { UIGraphicsEndImageContext() return } ctx.clear(CGRect(x: 0.0, y: 0.0, width: Double(aWidth), height: Double(aHeight))) for j in 0..<Int(aHeight) { for i in 0..<Int(aWidth) { let aValue = (mlArray[j * Int(aHeight) + i].floatValue >= 0.5) ? 1.0 : 0.0 let aRect = CGRect(x: CGFloat(i), y: CGFloat(j), width: 1.0, height: 1.0) let aColor = UIColor(displayP3Red: 0.0, green: 0.0, blue: 0.0, alpha: CGFloat(aValue)) aColor.setFill() UIRectFill(aRect) } } if let anImage = UIGraphicsGetImageFromCurrentImageContext() { self.imageView.image = anImage } UIGraphicsEndImageContext() } }
给你划几个重点:
- 类型转换要准确:必须把
finishReq.results转换成[VNCoreMLFeatureValueObservation],这样才能访问到featureValue属性 - 提取MultiArray:通过
featureValue.multiArrayValue就能直接拿到你需要的MLMultiArray对象 - 线程注意:绘图操作一定要放到主队列执行,不然会崩溃
- 安全校验:每一步都加
guard判断,避免因为空值导致程序崩溃
另外,你原来的代码里把绘图逻辑放在了perform方法外面,这会导致currentMLArray还没被赋值就执行,肯定拿不到数据,所以我把绘图逻辑移到了回调里面,确保拿到MLMultiArray后再执行。
这样改完应该就能正常获取并使用MLMultiArray了!
备注:内容来源于stack exchange,提问作者jasoninthecloud
相关产品推荐
相关产品推荐

