Creación de una aplicación de Android para el reconocimiento de texto en 10 minutos. Mobile Vision CodeLab

Versión en video del tutorial



El reconocimiento óptico de caracteres ( OCR ) le da a la computadora la capacidad de leer texto en una imagen, permitiendo a las aplicaciones comprender letreros, artículos, volantes, páginas de texto, menús o cualquier cosa en forma de texto. Mobile Vision Text API proporciona a los desarrolladores de Android una función de OCR potente y confiable que admite la mayoría de los dispositivos Android y no aumenta el tamaño de su aplicación.


En este tutorial, creará una aplicación en la que todo el texto que cae en el marco será reconocido y reproducido durante el proceso de grabación de video.


También publicamos artículos sobre otras características de Mobile Vision:



El código fuente se puede descargar aquí .


O clone el repositorio de GitHub desde la línea de comandos:


 $ git clone https://github.com/googlesamples/android-vision.git 

El repositorio de visionSamples contiene muchos proyectos de muestra relacionados con Mobile Vision . Solo se usan dos en esta lección:


  • ocr-codelab / ocr-reader-start es el código inicial que usará en esta lección.
  • ocr-codelab / ocr-reader-complete : el código completo para la aplicación finalizada. Puede usarlo para solucionar problemas o ir directamente a la aplicación de trabajo.

Actualización de servicios de Google Play


Es posible que deba actualizar su versión instalada de Google Repository para usar la Mobile Vision Text API .


Abra Android Studio y abra el SDK Manager :




Asegúrese de que el Google Repository actualizado. Debe ser al menos la versión 26 .




Agregue una dependencia de Google Play Services y cree una aplicación de inicio


Ahora puede abrir el proyecto inicial:


  1. Elija un directorio de inicio ocr-reader del código descargado ( Archivo > Abrir > ocr-codelab/ocr-reader-start ).


  2. Agregue la dependencia de Google Play Services a la aplicación. Sin esta dependencia, la Text API no estará disponible.



El proyecto puede indicar la ausencia del archivo entero / google_play_services_version y dar un error. Esto es normal, lo arreglaremos en el siguiente paso.


Abra el archivo build.gradle en el módulo de la app y cambie el bloque de dependencia para incluir la dependencia de play-services-vision allí. Cuando todo esté listo, el archivo debería verse así:


 dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:support-v4:26.1.0' implementation 'com.android.support:design:26.1.0' implementation 'com.google.android.gms:play-services-vision:15.0.0' } 

  1. Haga clic en Gradle sincronización Gradle .


  2. Haga clic en botón de inicio



Después de unos segundos, verá la pantalla Leer texto, pero esta es solo una pantalla en negro.




No está sucediendo nada en este momento porque CameraSource no CameraSource configurado. Hagámoslo


Si no tiene éxito, puede abrir un proyecto ocr-reader-complete y asegúrese de que funcione correctamente. Este proyecto es una versión preparada de la lección, y si esta versión no funciona, debe verificar que todo esté en orden con su dispositivo y la configuración de Android Studio .


Configurar TextRecognizer y CameraSource


Para comenzar, crearemos nuestro TextRecognizer . Este objeto detector procesa las imágenes y determina qué texto aparece dentro de ellas. Después de la inicialización, TextRecognizer se puede usar para detectar texto en todo tipo de imágenes. Encuentre el método createCameraSource y cree un TextRecognizer :


OcrCaptureActivity.java


 private void createCameraSource(boolean autoFocus, boolean useFlash) { Context context = getApplicationContext(); // TODO: Create the TextRecognizer TextRecognizer textRecognizer = new TextRecognizer.Builder(context).build(); // TODO: Set the TextRecognizer's Processor. // TODO: Check if the TextRecognizer is operational. // TODO: Create the mCameraSource using the TextRecognizer. } 

Ahora TextRecognizer listo para funcionar. Sin embargo, es posible que aún no funcione. Si el dispositivo no tiene suficiente memoria o Google Play Services no puede cargar OCR dependencias de OCR , el objeto TextRecognizer no funcionará. Antes de comenzar a usarlo para el reconocimiento de texto, debemos verificar que esté listo. TextRecognizer esta verificación a createCameraSource después de inicializar TextRecognizer :


OcrCaptureActivity.java


 // TODO: Check if the TextRecognizer is operational. if (!textRecognizer.isOperational()) { Log.w(TAG, "Detector dependencies are not yet available."); // Check for low storage. If there is low storage, the native library will not be // downloaded, so detection will not become operational. IntentFilter lowstorageFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW); boolean hasLowStorage = registerReceiver(null, lowstorageFilter) != null; if (hasLowStorage) { Toast.makeText(this, R.string.low_storage_error, Toast.LENGTH_LONG).show(); Log.w(TAG, getString(R.string.low_storage_error)); } } 

Ahora que hemos verificado que TextRecognizer listo para usar, podemos usarlo para reconocer fotogramas individuales. Pero queremos hacer algo más interesante: leer el texto en modo video. Para hacer esto, crearemos un CameraSource que esté preconfigurado para controlar la cámara. Necesitamos establecer una alta resolución para disparar y habilitar el enfoque automático para hacer frente a la tarea de reconocer texto pequeño. Si está seguro de que sus usuarios verán grandes bloques de texto, por ejemplo, signos, puede usar una resolución más baja y luego el procesamiento del marco será más rápido:


OcrCaptureActivity.java


 // TODO: Create the cameraSource using the TextRecognizer. cameraSource = new CameraSource.Builder(getApplicationContext(), textRecognizer) .setFacing(CameraSource.CAMERA_FACING_BACK) .setRequestedPreviewSize(1280, 1024) .setRequestedFps(15.0f) .setFlashMode(useFlash ? Camera.Parameters.FLASH_MODE_TORCH : null) .setFocusMode(autoFocus ? Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO : null) .build(); 

Así es como debería verse el método createCameraSource cuando haya terminado:


OcrCaptureActivity.java


 private void createCameraSource(boolean autoFocus, boolean useFlash) { Context context = getApplicationContext(); // Create the TextRecognizer TextRecognizer textRecognizer = new TextRecognizer.Builder(context).build(); // TODO: Set the TextRecognizer's Processor. // Check if the TextRecognizer is operational. if (!textRecognizer.isOperational()) { Log.w(TAG, "Detector dependencies are not yet available."); // Check for low storage. If there is low storage, the native library will not be // downloaded, so detection will not become operational. IntentFilter lowstorageFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW); boolean hasLowStorage = registerReceiver(null, lowstorageFilter) != null; if (hasLowStorage) { Toast.makeText(this, R.string.low_storage_error, Toast.LENGTH_LONG).show(); Log.w(TAG, getString(R.string.low_storage_error)); } } // Create the cameraSource using the TextRecognizer. cameraSource = new CameraSource.Builder(getApplicationContext(), textRecognizer) .setFacing(CameraSource.CAMERA_FACING_BACK) .setRequestedPreviewSize(1280, 1024) .setRequestedFps(15.0f) .setFlashMode(useFlash ? Camera.Parameters.FLASH_MODE_TORCH : null) .setFocusMode(autoFocus ? Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO : null) .build(); } 

Si ejecuta la aplicación, verá que el video ha comenzado. Pero para procesar imágenes de la cámara, necesitamos agregar este último TODO para crear createCameraSource : crear un Processor para procesar el texto a medida que llega.


Creando OcrDetectorProcessor


Su aplicación ahora puede detectar texto en marcos individuales utilizando el método de descubrimiento en TextRecognizer . Para que pueda encontrar texto, por ejemplo, en una fotografía. Pero para leer el texto directamente durante la filmación de video, debe implementar un Processor que procese el texto tan pronto como aparezca en la pantalla.


Vaya a la clase OcrDetectorProcessor implemente la interfaz Detector.Processor :


OcrDetectorProcessor.java


 public class OcrDetectorProcessor implements Detector.Processor<TextBlock> { private GraphicOverlay<OcrGraphic> graphicOverlay; OcrDetectorProcessor(GraphicOverlay<OcrGraphic> ocrGraphicOverlay) { graphicOverlay = ocrGraphicOverlay; } } 

Para implementar esta interfaz, debe anular dos métodos. El primero, receiveDetections , recibe TextBlocks de TextRecognizer medida que se detectan. El segundo, release , se usa para liberar recursos cuando TextRecognizer destruye un TextRecognizer . En este caso, solo necesitamos borrar el lienzo gráfico, lo que conducirá a la eliminación de todos los objetos OcrGraphic .


OcrGraphic TextBlocks y OcrGraphic objetos OcrGraphic para cada bloque de texto detectado por el procesador. Implementamos la lógica de su dibujo en el siguiente paso.


OcrDetectorProcessor.java


 @Override public void receiveDetections(Detector.Detections<TextBlock> detections) { graphicOverlay.clear(); SparseArray<TextBlock> items = detections.getDetectedItems(); for (int i = 0; i < items.size(); ++i) { TextBlock item = items.valueAt(i); if (item != null && item.getValue() != null) { Log.d("Processor", "Text detected! " + item.getValue()); OcrGraphic graphic = new OcrGraphic(graphicOverlay, item); graphicOverlay.add(graphic); } } } @Override public void release() { graphicOverlay.clear(); } 

Ahora que el procesador está listo, necesitamos configurar textRecognizer para usarlo. Regrese al último TODO restante en el método createCameraSource en OcrCaptureActivity :


OcrCaptureActivity.java


 // Create the TextRecognizer TextRecognizer textRecognizer = new TextRecognizer.Builder(context).build(); // TODO: Set the TextRecognizer's Processor. textRecognizer.setProcessor(new OcrDetectorProcessor(graphicOverlay)); 

Ahora ejecuta la aplicación. En este punto, cuando coloque la cámara sobre el texto, verá mensajes de depuración “¡Texto detectado! en Android Monitor Logcat ! Pero esta no es una forma muy visual de visualizar lo que TextRecognizer ve, ¿verdad?


En el siguiente paso, dibujaremos este texto en la pantalla.


Dibujar texto en pantalla


Implementemos el método de draw en OcrGraphic . Necesitamos entender si hay texto en la imagen, convertir las coordenadas de sus bordes en marcos de lienzo y luego dibujar los bordes y el texto.


OcrGraphic.java


 @Override public void draw(Canvas canvas) { // TODO: Draw the text onto the canvas. if (text == null) { return; } // Draws the bounding box around the TextBlock. RectF rect = new RectF(text.getBoundingBox()); rect = translateRect(rect); canvas.drawRect(rect, rectPaint); // Render the text at the bottom of the box. canvas.drawText(text.getValue(), rect.left, rect.bottom, textPaint); } 

Inicie la aplicación y pruébela en este texto de muestra:



¡Debería ver que aparece un marco en la pantalla con texto! Puedes jugar con el color del texto usando TEXT_COLOR .


¿Qué tal esto?



El marco alrededor del texto parece correcto, pero el texto está en la parte inferior.




Esto se debe a que el motor transfiere todo el texto que reconoce en TextBlock como una sola oración, incluso si ve una oración dividida en varias líneas. Si necesita obtener toda la oferta, entonces esto es muy conveniente. Pero, ¿qué sucede si desea saber dónde se encuentra cada línea de texto individual?


Puede obtener Lines desde un TextBlock llamando a getComponents y luego, clasificando cada línea, puede obtener fácilmente su ubicación y el texto dentro de ella. Esto le permite dibujar texto en el lugar donde realmente aparece.


OcrGraphic.java


 @Override public void draw(Canvas canvas) { // TODO: Draw the text onto the canvas. if (text == null) { return; } // Draws the bounding box around the TextBlock. RectF rect = new RectF(text.getBoundingBox()); rect = translateRect(rect); canvas.drawRect(rect, rectPaint); // Break the text into multiple lines and draw each one according to its own bounding box. List<? extends Text> textComponents = text.getComponents(); for(Text currentText : textComponents) { float left = translateX(currentText.getBoundingBox().left); float bottom = translateY(currentText.getBoundingBox().bottom); canvas.drawText(currentText.getValue(), left, bottom, textPaint); } } 

Intenta este texto nuevamente:



Genial Incluso puede dividir el texto encontrado en componentes aún más pequeños, según sus necesidades. Puede llamar a getComponents en cada línea y obtener Elements (palabras latinas). Es posible configurar textSize para que el texto ocupe tanto espacio como el texto real en la pantalla.




Reproduce texto al hacer clic en él


Ahora el texto de la cámara se convierte en líneas estructuradas, y estas líneas se muestran en la pantalla. Hagamos algo más con ellos.


Usando la TextToSpeech API integrada en Android y el método contains en OcrGraphic , podemos enseñar a la aplicación a hablar en voz alta cuando hace clic en el texto.


Primero, implementemos el método contains en OcrGraphic . Solo necesitamos verificar si las coordenadas y están dentro de los límites del texto que se muestra.
OcrGraphic.java


 public boolean contains(float x, float y) { // TODO: Check if this graphic's text contains this point. if (text == null) { return false; } RectF rect = new RectF(text.getBoundingBox()); rect = translateRect(rect); return rect.contans(x, y); } 

¡Puede notar que hay mucho en común con el método Draw ! En este proyecto, debería poder reutilizar el código, pero aquí lo dejamos todo como es solo por el ejemplo.


Ahora pasemos al método onTap en OcrCaptureActivity y OcrCaptureActivity el clic en el texto, si hay uno en este lugar.


OcrCaptureActivity.java


 private boolean onTap(float rawX, float rawY) { // TODO: Speak the text when the user taps on screen. OcrGraphic graphic = graphicOverlay.getGraphicAtLocation(rawX, rawY); TextBlock text = null; if (graphic != null) { text = graphic.getTextBlock(); if (text != null && text.getValue() != null) { Log.d(TAG, "text data is being spoken! " + text.getValue()); // TODO: Speak the string. } else { Log.d(TAG, "text data is null"); } } else { Log.d(TAG,"no text detected"); } return text != null; } 

Puede ejecutar la aplicación y asegurarse de que al hacer clic en el texto se esté procesando a través de Android Monitor Logcat .


¡Hagamos que nuestra aplicación hable! Vaya al comienzo de la Activity y encuentre el método onCreate . Al iniciar la aplicación, debemos inicializar el motor TextToSpeech para su uso futuro.


OcrCaptureActivity.java


 @Override public void onCreate(Bundle bundle) { // (Portions of this method omitted) // TODO: Set up the Text To Speech engine. TextToSpeech.OnInitListener listener = new TextToSpeech.OnInitListener() { @Override public void onInit(final int status) { if (status == TextToSpeech.SUCCESS) { Log.d("TTS", "Text to speech engine started successfully."); tts.setLanguage(Locale.US); } else { Log.d("TTS", "Error starting the text to speech engine."); } } }; tts = new TextToSpeech(this.getApplicationContext(), listener); } 

A pesar del hecho de que hemos inicializado correctamente TextToSpeech , como regla general, aún debe manejar los errores generales, por ejemplo, cuando el motor aún no está listo la primera vez que hace clic en el texto.


TextToSpeech también depende del idioma. Puede cambiar el idioma en función del idioma del texto reconocido. El reconocimiento de idioma no está integrado en la Mobile Vision Text API , pero está disponible a través de la Google Translate API . Como idioma para el reconocimiento de texto, puede usar el idioma del dispositivo del usuario.


Genial, todo lo que queda es agregar el código de reproducción de texto en el método onTap .


OcrCaptureActivity.java


 private boolean onTap(float rawX, float rawY) { // TODO: Speak the text when the user taps on screen. OcrGraphic graphic = graphicOverlay.getGraphicAtLocation(rawX, rawY); TextBlock text = null; if (graphic != null) { text = graphic.getTextBlock(); if (text != null && text.getValue() != null) { Log.d(TAG, "text data is being spoken! " + text.getValue()); // Speak the string. tts.speak(text.getValue(), TextToSpeech.QUEUE_ADD, null, "DEFAULT"); } else { Log.d(TAG, "text data is null"); } } else { Log.d(TAG,"no text detected"); } return text != null; } 

Ahora, cuando inicie la aplicación y haga clic en el texto detectado, su dispositivo lo reproducirá. ¡Pruébalo!


Finalización


¡Ahora tiene una aplicación que puede reconocer el texto de la cámara y hablarlo en voz alta!


Puede aplicar el conocimiento adquirido del reconocimiento de texto en sus otras aplicaciones. Por ejemplo, lea direcciones y números de teléfono de tarjetas de negocios, busque el texto de fotografías de varios documentos. En resumen, use OCR donde sea que necesite reconocer texto en una imagen.


Fuente

Source: https://habr.com/ru/post/es412679/


All Articles