Dans cet article


Offres d'emploi

Tags

Détecter du texte à partir d'images grâce à Google Vision - Android - Kotlin

Détecter du texte à partir d'images grâce à Google Vision - Android - Kotlin

Reconnaître un texte à partir d’une simple image, voilà un défi corsé ! Enfin, fut un temps. Car aujourd’hui, je vais vous montrer comment intégrer cette fonctionnalité dans toutes vos applications Android en seulement quelques lignes de code grâce à la magnifique librairie Google Vision développée par Google himself.

Google vision, c’est quoi ?

La librairie Google Vision regroupe trois sous-modules :

  • Reconnaissance de texte à partir d’une image,
  • Détection de visages (pas de reconnaissance pour l’instant),
  • Lecture de QR Codes.

Ici, nous nous intéresserons uniquement à la reconnaissance de texte en direct à partir de la caméra d’un smartphone Android. Les deux autres modules ne sont pas très différents du premier et, une fois que vous saurez vous servir de celui-ci, il sera facile pour vous d’apprendre à les maîtriser.

Installation de Google Vision

Commençons par le commencement : intégrer la librairie à votre projet. Pour cela, il suffit d’ajouter la dépendance dans votre build.gradle.

dependencies {
    ...
    implementation 'com.google.android.gms:play-services-vision:11.0.4'
    ...
}

Deuxièmement étape : dans votre Manifest, demander la permission d’utiliser la caméra du téléphone (pour scanner l’image à lire) et une meta-data.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tuts.prakash.simpleocr">
	...
    <uses-permission android:name="android.permission.CAMERA"/>
	...
    <application>
		...
		<meta-data android:name="com.google.android.gms.vision.DEPENDENCIES" android:value="ocr"/>
		...
    </application>
</manifest>

Utilisation de Google Vision

Maintenant que l’API est bien installée, on va pouvoir commencer à l’utiliser !

Le Layout

Dans un premier temps, nous allons créer un simple Layout avec deux view :

  • Une SurfaceView qui affichera ce que voit la caméra.
  • Une TextView pour afficher le texte reconnu.

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    
    <SurfaceView
        android:id="@+id/surfaceView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="4" />
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:textSize="16sp" />
    
    </LinearLayout>
    

Le code

Il va nous falloir 3 objets :

  1. Un SurfaceHolder
  2. Une CameraSource
  3. Un TextRecognizer

    class MainActivity : AppCompatActivity() {
    
    	private lateinit var cameraHolder: SurfaceHolder
    	private lateinit var cameraSource: CameraSource
    	private lateinit var textRecognizer: TextRecognizer
    	
    	...
    	
    }
    

Ensuite, dans la méthode .onCreate() on va initialiser la CameraSource et le TextRecognizer.

override fun onCreate(savedInstanceState: Bundle?) {
	super.onCreate(savedInstanceState)
	setContentView(R.layout.activity_main)

	textRecognizer = TextRecognizer.Builder(this).build()

	cameraSource = CameraSource.Builder(this, textRecognizer)
		.setFacing(CameraSource.CAMERA_FACING_BACK)
		.setAutoFocusEnabled(true)
		.setRequestedFps(3.0f)
		.build()
		
	...
		
}

Pour la CameraSource, plusieurs options sont ajoutées par confort :

  1. .setFacing(CameraSource.CAMERA_FACING_BACK) indique que nous utilisons la caméra à l’arrière du téléphone.
  2. .setAutoFocusEnabled(true) pour que le Focus soit automatique.
  3. .setRequestedFps(3.0f) pour filmer à 3 images par seconde. Pour de la reconnaissance de texte, inutile d’aller au-delà de 3 FPS, cela pourrait même provoquer des erreurs de lecture.

Rien de spécial pour le TextRecognizer.

Pour initialiser la SurfaceHolder, c’est un peu plus tricky ! Il faut ajouter le code suivant dans le .onCreate().

surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
	override fun surfaceCreated(holder: SurfaceHolder) {
		cameraHolder = surfaceView.holder

		if (ActivityCompat.checkSelfPermission(this@MainActivity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
			finish()
		}
		cameraSource.start(cameraHolder)
	}
	override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { }
	override fun surfaceDestroyed(holder: SurfaceHolder) { cameraSource.stop() }
})

L’objet SurfaceHolder ne peut être récupéré qu’après la création de la SurfaceView, d’où la nécessité de faire appel à un Callback. De plus, vous remarquez qu’on vérifie que l’application a bien la permission d’utiliser la Camera. Nous ne verrons pas ici comment accorder cette permission, il est d’ailleurs plus judicieux de demander les permissions au lancement de l’application. Dans la cas où la permission ne serait pas accordée, nous fermons l’activité, mais vous pouvez modifier ce comportement.

Enfin, on lance la caméra et l’affichage de son contenu dans la View créée avec cameraSource.start(cameraHolder).

Allez, on y est presque !

La dernière chose à faire est donc de dire à notre TextRecognizer que faire lorsqu’il déchiffre quelque chose. Pour cela, ajoutez le code suivant :

textRecognizer.setProcessor(object : Detector.Processor<TextBlock> {
	override fun release() {}
	override fun receiveDetections(detections: Detector.Detections<TextBlock>) {
		val items: SparseArray<TextBlock> = detections.detectedItems

		textView.text = (0 until items.size()).joinToString("\n") { items.get(it).value }
	}
})

On peut voir que l’on ajoute un Processor à notre TextRecognizer et que sa méthode .receiveDetections() contient notre logique. Chose à savoir : un objet TextBlock est une entité que Vision a détectée comme un paragraphe. En plus du texte reconnu, il contient notamment la langue de ce texte, si Vision a réussit à l’identifier. Ici, on va simplement rassembler tous les paragraphes et les afficher dans le TextView prévu à cet effet.

Google Vision : on adopte ?

Oui ! Comme beaucoup d’outils développés par Google, Vision est très simple d’utilisation et extrêmement performant !

En seulement quelques lignes de code, vous pouvez l’intégrer à votre projet afin de rapidement vous concentrer sur la logique après avoir déchiffré un texte.

A vous de jouer !

L'équipe AXOPEN

Voir aussi les articles suivants

Utiliser Glide avec Kotlin, la meilleure librairie Android de chargement d'images !
Glide, c’est quoi ? Glide est une librairie Android Open Source de gestion du chargement et de l’affichage d’images pour vos applications mobiles. Glide est simple à prendre en main, facile d’utilisation et propose de nombreuses fonctionnalités… Elle vous fera économiser du temps et de l’énergie dans tous vos développements !
Lire l'article

TUTO – Cordova Tools : Débugger en live un projet Ionic avec Visual Studio Code
Le déboggage est une étape essentielle lors de la création d’une application mobile et même plus simplement quand on code. Avec Ionic, cela peut être compliqué à mettre en place.
Lire l'article

Material design, le pour et le contre…

Material design, le pour et le contre…

Le 15/05/2018 par Pierre Liseron

Il y a quelques années, Google a dévoilé sa vision du design et de l’ergonomie. Petit à petit, le géant du web s’est efforcé de l’intégrer dans toutes ses applications grand public.
Lire l'article