Донецкий техникум промышленной автоматики

Створення Android програми для розпізнавання тексту за 10 Хвилин. Mobile Vision CodeLab

  1. Оновлення сервісів Google Play
  2. Додавання залежності Google Play Services і створення програми для запуску
  3. Налаштуйте TextRecognizer і CameraSource
  4. створення OcrDetectorProcessor
  5. Малювання тексту на екрані
  6. Відтворення тексту при натисканні на ньому
  7. завершення

... або склоніровать репозиторій GitHub з командного рядка:

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

Репозиторій visionSamples містить багато прикладів проектів, пов'язаних з Mobile Vision. У цьому уроці використовується тільки два:

Оновлення сервісів Google Play

Можливо, вам буде потрібно оновити встановлену версію Google Repository, щоб використовувати Mobile Vision Text API.

Відкрийте Android Studio і відкрийте SDK Manager:
Відкрийте Android Studio і відкрийте SDK Manager:

Переконайтеся, що Google Repository оновлений. Він повинен бути не менше 26 версії.
Переконайтеся, що Google Repository оновлений

Додавання залежності Google Play Services і створення програми для запуску

Тепер можна відкривати стартовий проект:

  1. Виберіть каталог запуску ocr-reader з завантаженого коду (File> Open> ocr-codelab / ocr-reader-start).
  2. Додайте залежність Google Play Services до додатка. Без цієї залежності Text API НЕ буде доступний.

Проект може вказати на відсутність файлу integer / google_play_services_version і видати помилку. Це нормально, ми виправимо це на наступному кроці.

Відкрийте файл build.gradle в app модулі та змініть блок залежностей, включивши туди залежність play-services-vision. Коли все буде готово, файл повинен виглядати так:

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. натисніть кнопку синхронізації Gradle.
  2. натисніть кнопку запуску.

Через кілька секунд ви побачите екран «Read Text», але це всього лише чорний екран.
Через кілька секунд ви побачите екран «Read Text», але це всього лише чорний екран

Зараз нічого не відбувається, тому що CameraSource не налаштований. Давайте зробимо це.

Якщо у вас щось не виходить, ви можете відкрити проект Якщо у вас щось не виходить, ви можете відкрити проект   ocr-reader-complete і переконатися, що він працює правильно ocr-reader-complete і переконатися, що він працює правильно. Цей проект є готовою версією уроку, і якщо ця версія не працює, ви повинні перевірити, що все в порядку з вашим пристроєм і настройками Android Studio.

Налаштуйте TextRecognizer і CameraSource

Щоб почати роботу, ми створимо наш TextRecognizer. Цей об'єкт-детектор обробляє зображення і визначає, який текст з'являється всередині них. Після ініціалізації TextRecognizer може використовуватися для виявлення тексту в усіх типах зображень. Знайдіть метод createCameraSource і створіть 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. }

Тепер TextRecognizer готовий до роботи. Однак, можливо, він ще не працює. Якщо на пристрої недостатньо пам'яті або Google Play Services не може завантажити залежності OCR, об'єкт TextRecognizer працювати не буде. Перш ніж ми почнемо використовувати його для розпізнавання тексту, ми повинні перевірити, що він готовий. Ми додамо цю перевірку в createCameraSource після ініціалізації 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)); }}

Тепер, коли ми перевірили, що TextRecognizer готовий до роботи, ми можемо використовувати його для розпізнавання окремих кадрів. Але ми хочемо зробити щось більш цікаве: читати текст в режимі роботи камери. Для цього ми створимо CameraSource, який попередньо налаштований для управління камерою. Нам необхідно встановити високий дозвіл зйомки і включити автофокусування, щоб впоратися з завданням розпізнавання невеликого тексту. Якщо ви впевнені, що ваші користувачі будуть дивитися на великі блоки тексту, наприклад вивіски, ви можете використовувати більш низький дозвіл, і тоді обробка кадрів відбуватиметься швидше:

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 ();

Ось як повинен виглядати метод createCameraSource, коли ви закінчите:

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 (); }

Якщо ви запустите додаток, то побачите, що почалася відеозйомка! Але для обробки зображень з камери нам потрібно дописати цей останній TODO в createCameraSource: створити Processor для обробки тексту в міру його надходження.

створення OcrDetectorProcessor

Зараз ваше додаток може виявляти текст на окремих кадрах, використовуючи метод виявлення в TextRecognizer. Так можна знайти текст, наприклад, на фотографії. Але для того, щоб читати текст прямо під час відеозйомки, потрібно реалізувати Processor, який буде обробляти текст, як тільки він з'явиться на екрані.

Перейдіть в клас OcrDetectorProcessor реалізуйте інтерфейс Detector.Processor:

OcrDetectorProcessor.java

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

Для реалізації цього інтерфейсу потрібно перевизначити два методи. Перший, receiveDetections, отримує на вхід TextBlocks з TextRecognizer в міру їх виявлення. Другий, release, використовується для звільнення від ресурсів при знищенні TextRecognizer. У цьому випадку нам потрібно просто очистити графічне полотно, що призведе до видалення всіх об'єктів OcrGraphic.

Ми отримаємо TextBlocks і створимо об'єкти OcrGraphic для кожного текстового блоку, виявленого процесором. Логіку їх малювання ми реалізуємо на наступному кроці.

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 (); }

Тепер, коли процесор готовий, ми повинні налаштувати textRecognizer для його використання. Поверніться до останнього залишився TODO в методі createCameraSource в OcrCaptureActivity:

OcrCaptureActivity.java

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

Тепер запустіть додаток. На цьому етапі при наведенні камери на текст ви побачите налагоджувальні повідомлення «Text detected!» В Android Monitor Logcat! Але це не дуже наочний спосіб візуалізації того, що бачить TextRecognizer, правда?

На наступному кроці ми отрісуем цей текст на екрані.

Малювання тексту на екрані

Давайте реалізуємо метод draw в OcrGraphic. Нам потрібно зрозуміти, чи є на зображенні текст, перетворити координати його кордонів в рамки кинувся, а потім намалювати і кордони, і текст.

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); }

Відкрийте програму і протестуйте його на цьому зразку тексту:
Відкрийте програму і протестуйте його на цьому зразку тексту:

Ви повинні побачити, що на екрані з'являється рамка з текстом в ній! Ви можете пограти з кольором тексту, використовуючи TEXT_COLOR.

Як на рахунок цього?
Як на рахунок цього

Рамка навколо тексту виглядає правильно, але текст знаходиться в нижній її частині.
Рамка навколо тексту виглядає правильно, але текст знаходиться в нижній її частині

Це пов'язано з тим, що движок передає весь текст, який він розпізнає в TextBlock у вигляді одного речення, навіть якщо він бачить пропозицію, розбите на кілька рядків. Якщо вам потрібно отримати ціле речення, то це дуже зручно. Але що, якщо ви хочете знати, де розташована кожна окрема рядок тексту?

Ви можете отримати Lines з TextBlock, викликавши getComponents, а потім, перебираючи кожен рядок, запросто отримати її місце розташування і текст всередині неї. Це дозволяє малювати текст в тому місці, де він дійсно з'являється.

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); }}

Спробуйте знову цей текст:
Спробуйте знову цей текст:

Відмінно! Ви навіть можете розбивати знайдений текст на ще більш дрібні складові, виходячи з ваших потреб. Можна викликати getComponents на кожному рядку і отримати Elements (слова на латиниці). Є можливість налаштування textSize, щоб текст займав стільки місця, скільки займає реальний текст на екрані.

Відтворення тексту при натисканні на ньому

Тепер текст з камери перетворюється в структуровані рядки, і ці рядки відображаються на екрані. Давайте зробимо з ними що-небудь ще.

Використовуючи TextToSpeech API, вбудований в Android, і метод contains в OcrGraphic, ми можемо навчити додаток говорити вголос, при натисканні на текст.

Спочатку давайте реалізуємо метод contains в OcrGraphic. Нам просто потрібно перевірити, чи знаходяться координати x і y в межах рамки тексту, що відображається.

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); }

Ви можете помітити, що тут багато спільного з методом Draw! У цьому проекті вам варто було б домогтися перевикористання коду, але тут ми залишимо все як є просто заради прикладу.

Тепер перейдемо до методу onTap в OcrCaptureActivity і опрацюємо натискання по тексту, якщо він є в цьому місці.

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; }

Ви можете запустити додаток і через Android Monitor Logcat переконатися, що натискання на текст дійсно обробляється.

Давайте ж змусимо наш додаток говорити! Перейдіть в початок Activity і знайдіть метод onCreate. При запуску програми ми повинні ініціалізувати движок TextToSpeech для подальшого використання.

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); }

Незважаючи на те, що ми коректно ініціалізували TextToSpeech, як правило, все одно потрібно обробляти загальні помилки, наприклад, коли движок все ще не готовий при вашому першому натисканні на текст.

TextToSpeech також залежимо від мови розпізнавання. Ви можете змінити мову на основі мови розпізнаного тексту. Розпізнавання мови не вбудовані в Mobile Vision Text API, але воно є через Google Translate API. В якості мови для розпізнавання тексту можна використовувати мову пристрою користувача.

Відмінно, залишилося тільки додати код відтворення тексту в методі 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; }

Тепер, коли ви запустите додаток і натиснете на виявлений текст, ваш пристрій відтворить його. Спробуйте!

завершення

Тепер у вас є додаток, яке може розпізнавати текст з камери і проговорювати його вголос!

Отримані знання з розпізнавання тексту ви можете застосувати і в інших ваших додатках. Наприклад, читати адреси і номери телефонів з візитних карток, проводити пошук по тексту з фотографій різних документів. Одним словом, застосовуйте OCR всюди, де вам може знадобитися розпізнати текст на зображенні.

→ Створення Android програми для виявлення осіб в режимі реального часу
→ Розпізнавання об'єктів і людських емоцій

Переклад статті «See and Understand Text using OCR with Mobile Vision Text API for Android »

UseFlash?
AutoFocus ?
UseFlash?
AutoFocus ?
Але це не дуже наочний спосіб візуалізації того, що бачить TextRecognizer, правда?
Як на рахунок цього?
Але що, якщо ви хочете знати, де розташована кожна окрема рядок тексту?
List <?