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