识别照片时的时间差异Swift

问题描述

我创建了一个识别照片中花朵的应用程序。照片可以来自画廊,也可以用相机拍摄。我有功能

func detectFlower(image: CIImage,completion: @escaping (_ getString:String?,_ error:Error?,_ getDouble:Double?,_ getArray:Array<VNConfidence>?,_ getArray:Array<String>?)-> Void)  {
        
        guard let model = try? VNCoreMLModel(for: NewFlowersModel().model) else {
            
            fatalError("Cannot import a model.")
        }
        let methodStart = Date()
        let request = VNCoreMLRequest(model: model) { (request,error) in
            
            let classifiednameOfFlower = request.results?.first as? VNClassificationObservation
            let classifiedValues = request.results as? [VNClassificationObservation]
            let methodFinish = Date()
            let nameOfFlower = String(classifiednameOfFlower?.identifier ?? "Unexpected type")
            let executionTime = methodFinish.timeIntervalSince(methodStart)
            
            let classificationConfidences = classifiedValues?.prefix(10).map {
                ($0.confidence)
            }
            
            let classificationIdentifiers = classifiedValues?.prefix(10).map {
                ($0.identifier)
            }
            completion(nameOfFlower,nil,executionTime,classificationConfidences,classificationIdentifiers)
        }
        
        let handler = VNImageRequestHandler(ciImage: image)
        do {
            try handler.perform([request])
        } catch {
            print(error)
            completion(nil,error,nil)
        }
    }

用于识别。 let methodStart = Date()let methodFinish = Date()中有两个常数用于测量时间。在代码的后面,有一个常数可计算差异let executionTime = methodFinish.timeIntervalSince(methodStart)

我注意到一个奇怪的依赖关系-当我运行应用程序时,第一次扫描返回时差,例如0.395959秒下次扫描返回的时间要短得多,例如0.033615秒。这可能是什么结果?是什么原因导致时间差,而您第一次扫描,这个时间总是最长的?

解决方法

这段时间大部分时间可能是从磁盘加载模型。每次进行检测时,您都会重新创建整个模型:

guard let model = try? VNCoreMLModel(for: NewFlowersModel().model) else { ... }

首次执行此操作时,需要从磁盘上加载大量数据。在那之后,很多数据将被缓存,但这通常不是正确的方法,因为您仍在浪费大量精力来重建数据结构。

您想要做的是仅一次创建模型和请求,可能在应用程序启动期间,或者当您进入此屏幕时,或者在您希望用户想要ML引擎的任何时候。将其存储在属性或共享对象中。然后,每次获取新图像时,只需创建VNImageRequestHandler并执行它即可。