Search code examples
iosflutterdebugginggoogle-mlkithandwriting-recognition

MLKit Digital Ink Recognition throws error when initializing recognizer


I'm developing a Flutter app which makes use of the Digital Ink Recognition of ML Kit to recognize handwriting.

I have the following code to perform the recognition on iOS (swift code).

let ink = Ink.init(strokes: mlStrokes)

let identifier = DigitalInkRecognitionModelIdentifier(forLanguageTag: languageTag)
if identifier == nil {
    flutterResult(FlutterError(code: "ERROR", message: "No model for language tag found or the language tag could not be parsed", details: nil))
}

let model = DigitalInkRecognitionModel.init(modelIdentifier: identifier!)

// Get a recognizer for the given language
let options: DigitalInkRecognizerOptions = DigitalInkRecognizerOptions.init(model: model)
digitalInkRecognizer = DigitalInkRecognizer.digitalInkRecognizer(options: options)

digitalInkRecognizer.recognize(
    ink: ink,
    completion: {
        (result: DigitalInkRecognitionResult?, error: Error?) in
        if let result = result {
            var flutterCandidates : [[String: Any?]] = []
            for candidate in result.candidates {
                flutterCandidates.append(
                    ["text" : candidate.text, "score" : candidate.score]
                )
            }
            // Return recognised candidates to Flutter.
            self.flutterResult(flutterCandidates)
        } else {
            self.flutterResult(FlutterError(code: "ERROR", message: "Unable to recognize handwriting", details: error))
        }
    })

I'm recognizing a single letter at a time.

This works well for some time, the correct letter is returned in the completion callback and then send back to my Flutter app, but after the method is called a few times (~20), the following error is thrown in the console and my app crashes.

I1025 10:03:01.607888       1 lstm_recognizer.cc:77] Loaded tflite model.
2021-10-25 10:03:01.621992+0200 Runner[796:125890] Unsupported value: Error Domain=com.google.mlkit Code=13 "Unable to initialize recognizer: generic::internal: Unable to mmap file descriptor (Cannot allocate memory). (research/handwriting/util/mmap_data.cc:49)" UserInfo={NSLocalizedDescription=Unable to initialize recognizer: generic::internal: Unable to mmap file descriptor (Cannot allocate memory). (research/handwriting/util/mmap_data.cc:49)} of type NSError
2021-10-25 10:03:01.623350+0200 Runner[796:125890] *** Assertion failure in -[FlutterStandardWriter writeValue:], FlutterStandardCodec.mm:334
2021-10-25 10:03:01.632824+0200 Runner[796:125890] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unsupported value for standard codec'
*** First throw call stack:
(0x20ff2e180 0x20f1069f8 0x20fe4788c 0x21090bb38 0x1034b8138 0x1034b8898 0x1034b5890 0x100c4f0f4 0x100c522fc 0x100c523a8 0x1052536f4 0x105254c78 0x1052626fc 0x20febfb20 0x20febaa58 0x20feb9fb4 0x2120bb79c 0x23c197c38 0x100c4f464 0x20f97d8e0)
libc++abi.dylib: terminating with uncaught exception of type NSException

The error seems linked to a memory issue (Unsupported value: Error Domain=com.google.mlkit Code=13 "Unable to initialize recognizer: generic::internal: Unable to mmap file descriptor (Cannot allocate memory), but I don't find the reason.

Do I have to release something after the digitalInkRecognizer.recognize() method is called? I can't find anything related to this in the documentation.

Thanks in advance for any idea.


Solution

  • I found that the issue was linked to the lifecycle management of the ModelManager and recognizer which I was recreating each time I was performing the digital ink recognition.

    After changing this behaviour and keeping a reference to them once created, the issue was solved.

    This example was helpful to understand how to work with the ModelManager (see implementation of the StrokeManager).