You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift Playground无法找到已编译CoreML模型(.mlmodelc)求助

在Swift Playgrounds中集成MobileNetV2 CoreML模型时遇到nil解包错误

我已经调试这个问题超过10小时了,尝试在Swift Playgrounds中集成苹果的MobileNetV2 CoreML模型,执行了以下步骤:

  • 在常规Xcode项目中编译CoreML模型
  • 将编译后的CoreML模型(MobileNetV2.mlmodelc)移动到Swift Playground的Resources文件夹
  • 将模型类(MobileNetV2.swift)复制粘贴到Swift Playground的Sources文件夹
  • 使用UIImage扩展来调整图片大小并将UIImage转换为CVBuffer
  • 实现运行模型的基础代码

但每次运行都会出现错误:

MobileNetV2.swift:100: Fatal error: Unexpectedly found nil while unwrapping an Optional value

该错误来自自动生成的模型类函数:

/// URL of model assuming it was installed in the same bundle as this class
class var urlOfModelInThisBundle : URL {
    let bundle = Bundle(for: self)
    return bundle.url(forResource: "MobileNetV2", withExtension:"mlmodelc")!
}

模型可以正常构建,我的ContentView代码如下:

import SwiftUI

struct ContentView: View {
    
    
    func test() -> String{

            // 1. 从Resources文件夹加载图片
            let newImage = UIImage(named: "img")
            
            // 2. 将图片调整为Core ML模型要求的输入尺寸
            // 方法来自UIImage+Extension.swift
            let newSize = CGSize(width: 224, height: 224)
            guard let resizedImage = newImage?.resizeImageTo(size: newSize) else {
                fatalError("⚠️ 图片无法找到或调整大小")
            }

            // 3. 将调整后的图片转换为CVPixelBuffer,这是Core ML模型要求的输入类型
            // 方法来自UIImage+Extension.swift
            guard let convertedImage = resizedImage.convertToBuffer() else {
                fatalError("⚠️ 图片无法转换为CVPixelBugger")
            }
            
            // 1. 从Sources文件夹的模型类创建ML模型实例
            let mlModel = MobileNetV2()

            // 2. 获取预测输出
            guard let prediction = try? mlModel.prediction(image: convertedImage) else {
                fatalError("⚠️ 模型无法返回预测结果")
            }


            // 3. 检查预测结果
            let mostLikelyImageCategory = prediction.classLabel
            let probabilityOfEachCategory = prediction.classLabelProbs

            var highestProbability: Double {
                let probabilty = probabilityOfEachCategory[mostLikelyImageCategory] ?? 0.0
                let roundedProbability = (probabilty * 100).rounded(.toNearestOrEven)
                
                return roundedProbability
            }

            return("\(mostLikelyImageCategory): \(highestProbability)%")
    }
    
    
    var body: some View {
        VStack {
            let _ = print(test())
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
            Image(uiImage: UIImage(named: "img")!)
        }
    }
}

打印我的bundle内容得到:

["_CodeSignature", "metadata.json", "__PlaceholderAppIcon76x76@2x~ipad.png", "Info.plist", "__PlaceholderAppIcon60x60@2x.png", "coremldata.bin", "{App Name}", "PkgInfo", "Assets.car", "embedded.mobileprovision"]

任何帮助都将不胜感激 🙏

作为额外参考,我的ExtImage.swift中的UIImage扩展如下:

// 感谢github用户@mprecke提供的UIImage扩展方法

import Foundation
import UIKit

extension UIImage {
    
    func resizeImageTo(size: CGSize) -> UIImage? {
        
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
        self.draw(in: CGRect(origin: CGPoint.zero, size: size))
        let resizedImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return resizedImage
    }
    
     func convertToBuffer() -> CVPixelBuffer? {
        
        let attributes = [
            kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
            kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue
        ] as CFDictionary
        
        var pixelBuffer: CVPixelBuffer?
        
        let status = CVPixelBufferCreate(
            kCFAllocatorDefault, Int(self.size.width),
            Int(self.size.height),
            kCVPixelFormatType_32ARGB,
            attributes,
            &pixelBuffer)
        
        guard (status == kCVReturnSuccess) else {
            return nil
        }
        
        CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
        
        let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)
        let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
        
        let context = CGContext(
            data: pixelData,
            width: Int(self.size.width),
            height: Int(self.size.height),
            bitsPerComponent: 8,
            bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!),
            space: rgbColorSpace,
            bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue)
        
        context?.translateBy(x: 0, y: self.size.height)
        context?.scaleBy(x: 1.0, y: -1.0)
        
        UIGraphicsPushContext(context!)
        self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height))
        UIGraphicsPopContext()
        
        CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
        
        return pixelBuffer
    }

}

内容的提问来源于stack exchange,提问作者ColoredOwl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 17:40:39