Swift 识别照片时的时间差

Swift 识别照片时的时间差,swift,coreml,vision,Swift,Coreml,Vision,我创建了一个应用程序,可以识别照片中的花。照片可以来自画廊,也可以用相机拍摄。我有以下职能: func detectFlower(image: CIImage,completion: @escaping (_ getString:String?,_ error:Error?,_ getDouble:Double?,_ getArray:Array<VNConfidence>?,_ getArray:Array<String>?)-> Void) {

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

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, nil, nil)
        }
    }
func detectFlower(图像:CIImage,完成:@escaping(\uGetString:String?,\uError:error?,\uGetDouble:Double?,\uGetArray:Array?,\uGetArray:Array?)->Void){
guard let model=try?VNCoreMLModel(for:newflowsmodel().model)else{
fatalError(“无法导入模型”)
}
let methodStart=Date()
让request=VNCoreMLRequest(model:model){(request,error)在
让ClassifiedNameOffflower=request.results?.first作为VN ClassificationObservation
让classifiedValues=request.results为?[VNClassificationObservation]
让methodFinish=Date()
让NameOffflower=字符串(ClassifiedNameOffflower?.identifier???“意外类型”)
让executionTime=methodFinish.timeIntervalSince(methodStart)
设classificationConfidences=ClassifiedValue?.prefix(10).map{
($0.信心)
}
设classificationIdentifiers=ClassifiedValue?.prefix(10).map{
($0.标识符)
}
完成(流量名称、无、执行时间、分类机密、分类标识符)
}
let handler=vnimagerrequesthandler(ciImage:image)
做{
尝试处理程序。执行([请求])
}抓住{
打印(错误)
完成(无,错误,无,无,无,无)
}
}
用于识别。其中有两个常量用于测量时间,分别是
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
并执行它。

从磁盘加载模型可能会占用大部分时间。每次执行检测时,您都在重新创建整个模型:

guard let model = try? VNCoreMLModel(for: NewFlowersModel().model) else { ... }
第一次这样做时,需要从磁盘加载大量数据。之后,大部分数据将被缓存,但这通常不是正确的方法,因为您仍然在浪费大量精力重新创建数据结构

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