La reconnaissance d'encre numérique de ML Kit vous permet de reconnaître du texte manuscrit une surface numérique dans des centaines de langues, et de classer des croquis.
<ph type="x-smartling-placeholder">Essayer
- Testez l'application exemple pour : consultez un exemple d'utilisation de cette API.
Avant de commencer
<ph type="x-smartling-placeholder">- Dans le fichier
build.gradle
au niveau du projet, veillez à inclure le dépôt Maven de Google à la fois dans vos sectionsbuildscript
etallprojects
. - Ajoutez les dépendances des bibliothèques Android ML Kit au fichier Gradle au niveau de l'application de votre module, qui est généralement
app/build.gradle
:
dependencies {
// ...
implementation 'com.google.mlkit:digital-ink-recognition:18.1.0'
}
Vous êtes maintenant prêt à commencer à reconnaître du texte dans les objets Ink
.
Créer un objet Ink
La principale façon de créer un objet Ink
consiste à le dessiner sur un écran tactile. Activé
Android, vous pouvez utiliser
Canevas pour
à cette fin. Votre
Gestionnaires d'événements tactiles
doit appeler addNewTouchEvent()
indiquée dans l'extrait de code suivant pour stocker les points entre les traits
l'utilisateur s'appuie sur l'objet Ink
.
Ce schéma général est illustré dans l'extrait de code suivant. Consultez le Exemple de guide de démarrage rapide pour ML Kit pour obtenir un exemple plus complet.
Kotlin
var inkBuilder = Ink.builder() lateinit var strokeBuilder: Ink.Stroke.Builder // Call this each time there is a new event. fun addNewTouchEvent(event: MotionEvent) { val action = event.actionMasked val x = event.x val y = event.y var t = System.currentTimeMillis() // If your setup does not provide timing information, you can omit the // third paramater (t) in the calls to Ink.Point.create when (action) { MotionEvent.ACTION_DOWN -> { strokeBuilder = Ink.Stroke.builder() strokeBuilder.addPoint(Ink.Point.create(x, y, t)) } MotionEvent.ACTION_MOVE -> strokeBuilder!!.addPoint(Ink.Point.create(x, y, t)) MotionEvent.ACTION_UP -> { strokeBuilder.addPoint(Ink.Point.create(x, y, t)) inkBuilder.addStroke(strokeBuilder.build()) } else -> { // Action not relevant for ink construction } } } ... // This is what to send to the recognizer. val ink = inkBuilder.build()
Java
Ink.Builder inkBuilder = Ink.builder(); Ink.Stroke.Builder strokeBuilder; // Call this each time there is a new event. public void addNewTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); long t = System.currentTimeMillis(); // If your setup does not provide timing information, you can omit the // third paramater (t) in the calls to Ink.Point.create int action = event.getActionMasked(); switch (action) { case MotionEvent.ACTION_DOWN: strokeBuilder = Ink.Stroke.builder(); strokeBuilder.addPoint(Ink.Point.create(x, y, t)); break; case MotionEvent.ACTION_MOVE: strokeBuilder.addPoint(Ink.Point.create(x, y, t)); break; case MotionEvent.ACTION_UP: strokeBuilder.addPoint(Ink.Point.create(x, y, t)); inkBuilder.addStroke(strokeBuilder.build()); strokeBuilder = null; break; } } ... // This is what to send to the recognizer. Ink ink = inkBuilder.build();
Obtenir une instance de DigitalInkReconnaissance
Pour effectuer la reconnaissance, envoyez l'instance Ink
à un
DigitalInkRecognizer
. Le code ci-dessous montre comment instancier un tel
depuis un tag BCP-47.
Kotlin
// Specify the recognition model for a language var modelIdentifier: DigitalInkRecognitionModelIdentifier try { modelIdentifier = DigitalInkRecognitionModelIdentifier.fromLanguageTag("en-US") } catch (e: MlKitException) { // language tag failed to parse, handle error. } if (modelIdentifier == null) { // no model was found, handle error. } var model: DigitalInkRecognitionModel = DigitalInkRecognitionModel.builder(modelIdentifier).build() // Get a recognizer for the language var recognizer: DigitalInkRecognizer = DigitalInkRecognition.getClient( DigitalInkRecognizerOptions.builder(model).build())
Java
// Specify the recognition model for a language DigitalInkRecognitionModelIdentifier modelIdentifier; try { modelIdentifier = DigitalInkRecognitionModelIdentifier.fromLanguageTag("en-US"); } catch (MlKitException e) { // language tag failed to parse, handle error. } if (modelIdentifier == null) { // no model was found, handle error. } DigitalInkRecognitionModel model = DigitalInkRecognitionModel.builder(modelIdentifier).build(); // Get a recognizer for the language DigitalInkRecognizer recognizer = DigitalInkRecognition.getClient( DigitalInkRecognizerOptions.builder(model).build());
Traiter un objet Ink
Kotlin
recognizer.recognize(ink) .addOnSuccessListener { result: RecognitionResult -> // `result` contains the recognizer's answers as a RecognitionResult. // Logs the text from the top candidate. Log.i(TAG, result.candidates[0].text) } .addOnFailureListener { e: Exception -> Log.e(TAG, "Error during recognition: $e") }
Java
recognizer.recognize(ink) .addOnSuccessListener( // `result` contains the recognizer's answers as a RecognitionResult. // Logs the text from the top candidate. result -> Log.i(TAG, result.getCandidates().get(0).getText())) .addOnFailureListener( e -> Log.e(TAG, "Error during recognition: " + e));
L'exemple de code ci-dessus part du principe que le modèle de reconnaissance téléchargée, comme décrit dans la section suivante.
Gérer les téléchargements de modèles
Bien que l'API de reconnaissance d'encre numérique soit compatible avec des centaines de langues, chacune
nécessite le téléchargement de certaines données avant toute reconnaissance. À proximité
20 Mo d'espace de stockage sont requis par langue. Cette opération est gérée
RemoteModelManager
.
Télécharger un nouveau modèle
Kotlin
import com.google.mlkit.common.model.DownloadConditions import com.google.mlkit.common.model.RemoteModelManager var model: DigitalInkRecognitionModel = ... val remoteModelManager = RemoteModelManager.getInstance() remoteModelManager.download(model, DownloadConditions.Builder().build()) .addOnSuccessListener { Log.i(TAG, "Model downloaded") } .addOnFailureListener { e: Exception -> Log.e(TAG, "Error while downloading a model: $e") }
Java
import com.google.mlkit.common.model.DownloadConditions; import com.google.mlkit.common.model.RemoteModelManager; DigitalInkRecognitionModel model = ...; RemoteModelManager remoteModelManager = RemoteModelManager.getInstance(); remoteModelManager .download(model, new DownloadConditions.Builder().build()) .addOnSuccessListener(aVoid -> Log.i(TAG, "Model downloaded")) .addOnFailureListener( e -> Log.e(TAG, "Error while downloading a model: " + e));
Vérifier si un modèle a déjà été téléchargé
Kotlin
var model: DigitalInkRecognitionModel = ... remoteModelManager.isModelDownloaded(model)
Java
DigitalInkRecognitionModel model = ...; remoteModelManager.isModelDownloaded(model);
Supprimer un modèle téléchargé
La suppression d'un modèle de l'espace de stockage d'un appareil libère de l'espace.
Kotlin
var model: DigitalInkRecognitionModel = ... remoteModelManager.deleteDownloadedModel(model) .addOnSuccessListener { Log.i(TAG, "Model successfully deleted") } .addOnFailureListener { e: Exception -> Log.e(TAG, "Error while deleting a model: $e") }
Java
DigitalInkRecognitionModel model = ...; remoteModelManager.deleteDownloadedModel(model) .addOnSuccessListener( aVoid -> Log.i(TAG, "Model successfully deleted")) .addOnFailureListener( e -> Log.e(TAG, "Error while deleting a model: " + e));
Conseils pour améliorer la précision de la reconnaissance de texte
La précision de la reconnaissance de texte peut varier d'une langue à l'autre. La précision dépend également sur le style d'écriture. La reconnaissance d'encre numérique est entraînée à gérer de nombreux styles d'écriture. les résultats peuvent varier d'un utilisateur à l'autre.
Voici quelques conseils pour améliorer la précision d'un outil de reconnaissance de texte. Notez que ces techniques ne s'appliquent pas aux classificateurs de dessins pour les emoji, AutoDraw et les formes.
Zone d'écriture
De nombreuses applications disposent d'un espace d'écriture bien défini pour les entrées utilisateur. La signification d'un symbole est partiellement déterminée par sa taille par rapport à celle de la zone d’écriture qui la contient. Par exemple, la différence entre une lettre minuscule ou un "o" ou « c », et une virgule par rapport à un .
Vous pouvez indiquer au programme de reconnaissance la largeur et la hauteur de la zone d'écriture pour améliorer la précision. Toutefois, l'outil de reconnaissance suppose que la zone d'écriture ne contient qu'une seule ligne de texte. Si le serveur physique que la zone d'écriture soit suffisamment grande pour permettre à l'utilisateur d'écrire deux lignes ou plus, vous pouvez en spécifiant une zone d'écriture dont la hauteur est votre meilleure estimation de la hauteur sur une seule ligne de texte. Il n'est pas nécessaire que l'objet "WriteArea" que vous transmettez à l'outil de reconnaissance exactement avec la zone d'écriture physique à l'écran. Modifier la hauteur de WriteArea de cette manière fonctionne mieux dans certaines langues que dans d'autres.
Lorsque vous spécifiez la zone d'écriture, spécifiez sa largeur et sa hauteur dans les mêmes unités que le trait. coordonnées. Les arguments des coordonnées x,y n'ont pas d'unité requise : l'API normalise toutes unités, donc la seule chose qui compte est la taille et la position relatives des traits. Vous êtes libre de transmettre les coordonnées à n'importe quelle échelle pour votre système.
Pré-contexte
Le pré-contexte est le texte qui précède immédiatement les traits dans l'Ink
que vous
que vous essayez de reconnaître. Vous pouvez l'aider en lui parlant du contexte préalable.
Par exemple, les lettres cursives "n" et "u" sont souvent confondus. Si l'utilisateur a a déjà saisi le mot partiel "arg", il peut continuer avec des traits qui peuvent être reconnus comme "ument" ou "nment". Spécifier l'argument de pré-contexte "arg" résout l'ambiguïté, puisque le mot "argument" est plus probable que "argnment".
Le pré-contexte peut également aider l'outil de reconnaissance à identifier les coupures, les espaces entre les mots. Vous pouvez taper un caractère d'espacement mais vous ne pouvez pas en dessiner un, alors comment un outil de reconnaissance peut-il déterminer quand un mot se termine et que la suivante commence ? Si l'utilisateur a déjà écrit "hello" et continue avec l'écriture écrite "world", sans pré-contexte, le programme de reconnaissance renvoie la chaîne "world". Toutefois, si vous spécifiez le paramètre pré-contexte "hello", le modèle renvoie la chaîne " "hello", avec un espace au début, du monde" est plus logique que "helloword".
Vous devez fournir la chaîne pré-contexte la plus longue possible, jusqu'à 20 caractères, y compris des espaces. Si la chaîne est plus longue, le programme de reconnaissance n'utilise que les 20 derniers caractères.
L'exemple de code ci-dessous montre comment définir une zone d'écriture et utiliser un
Un objet RecognitionContext
pour spécifier le pré-contexte.
Kotlin
var preContext : String = ...; var width : Float = ...; var height : Float = ...; val recognitionContext : RecognitionContext = RecognitionContext.builder() .setPreContext(preContext) .setWritingArea(WritingArea(width, height)) .build() recognizer.recognize(ink, recognitionContext)
Java
String preContext = ...; float width = ...; float height = ...; RecognitionContext recognitionContext = RecognitionContext.builder() .setPreContext(preContext) .setWritingArea(new WritingArea(width, height)) .build(); recognizer.recognize(ink, recognitionContext);
Ordre des traits
La précision de la reconnaissance dépend de l'ordre des traits. Les programmes de reconnaissance s'attendent à ce que les traits se produire dans l'ordre dans lequel les gens écrivent naturellement ; par exemple de gauche à droite pour l'anglais. N'importe quel cas qui s'écarte de ce modèle, comme écrire une phrase en anglais commençant par le dernier mot, donne des résultats moins précis.
Autre exemple : un mot situé au milieu d'un élément Ink
est supprimé et remplacé par
un autre mot. La révision est probablement au milieu d'une phrase, mais ses traits
se trouvent à la fin de la séquence de trait.
Dans ce cas, nous vous recommandons d'envoyer le mot nouvellement écrit séparément à l'API et de fusionner les
avec les reconnaissances précédentes
à l'aide de votre propre logique.
Gérer les formes ambiguës
Dans certains cas, la signification de la forme fournie à l'outil de reconnaissance est ambiguë. Pour Par exemple, un rectangle aux bords très arrondis peut être considéré comme un rectangle ou une ellipse.
Ces cas peu clairs peuvent être gérés à l'aide des scores de reconnaissance lorsqu'ils sont disponibles. Uniquement
les classificateurs de formes fournissent des scores. Si le modèle est très confiant, le score du meilleur résultat sera
bien mieux que le deuxième meilleur. En cas d'incertitude, les scores des deux premiers résultats
d'être proche. Gardez également à l'esprit que les classificateurs de formes interprètent l'intégralité de la Ink
comme
une seule forme. Par exemple, si Ink
contient un rectangle et une ellipse à côté de chaque
le programme de reconnaissance peut renvoyer l'un ou l'autre (ou quelque chose de complètement différent)
résultat, car un seul candidat à la reconnaissance ne peut pas représenter deux formes.