0

I created an application that recognizes the flowers in the photo. The photo can be from a gallery or taken with a camera. I have function:

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)
        }
    }

which is used for recognition. There are two constants in it let methodStart = Date() and let methodFinish = Date() for measuring time. Later in the code there is a constant that computes the difference let executionTime = methodFinish.timeIntervalSince(methodStart).

I noticed a strange dependence - when I run the application, the first scan returns a time difference, e.g. 0.395959 sec. The next scan returns a much shorter time, eg 0.033615 sec. What could this be the result of? What causes the time difference, and that the first time you scan, this time is always the longest?

Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
newbieHere
  • 276
  • 2
  • 15

1 Answers1

2

Loading the model from disk is probably eating most of this time. You're recreating the whole model every time you do a detection:

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

The first time you do that, you need to load a lot of data off of disk. After that, much of it will be cached, but this isn't the right way to do it generally because you're still wasting a lot of effort recreating the data structures.

What you want to do is create the model and the request just one time, possibly during application start, or when you come to this screen, or whenever you expect the user is going to want the ML engine. Store it in a property, or in a shared object. Then, each time you get a new image, just create the VNImageRequestHandler and perform it.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610