Google стремится к продвижению расового равенства для чернокожего населения. Смотри как.
Эта страница была переведа с помощью Cloud Translation API.
Switch to English

Признайте текст в изображениях с ML Kit на Android

Вы можете использовать ML Kit для распознавания текста в изображениях. ML Kit имеет как общего назначения, API, пригодный для распознавания текста в изображениях, например, текст улицы знака, и API оптимизирован для распознавания текста документов. Общее назначение API имеет как на устройстве и модели облачной. распознавания текста документа доступны только в качестве модели на основе облака. См обзора для сравнения облака и на устройстве моделей.

Прежде чем вы начнете

  1. Если вы еще не сделали, добавить Firebase в свой Android проекта .
  2. В вашем проектном уровне build.gradle файл, не забудьте включить репозиторий Maven Google, как в вашем buildscript и allprojects секций.
  3. Добавьте зависимости для библиотек ML Kit Android для вашего модуля (приложение уровня) Gradle файл (обычно app/build.gradle ):
    apply plugin: 'com.android.application'
    apply plugin: 'com.google.gms.google-services'
    
    dependencies {
      // ...
    
      implementation 'com.google.firebase:firebase-ml-vision:24.0.3'
    }
    
  4. Необязательно , но рекомендуется: Если вы используете на устройстве API, настроить приложение для автоматической загрузки модели ML на устройство после того, как приложение устанавливается с Play Store.

    Для этого добавьте следующую декларацию вашего приложения AndroidManifest.xml файла:

    <application ...>
      ...
      <meta-data
          android:name="com.google.firebase.ml.vision.DEPENDENCIES"
          android:value="ocr" />
      <!-- To use multiple models: android:value="ocr,model2,model3" -->
    </application>
    
    Если вы не позволяете установить время загрузки модели, модель будет загружена в первый раз, когда вы запускаете детектор на устройстве. Прошу вас сделать до завершения загрузки не даст никакого результата.
  5. Если вы хотите использовать модель на основе облака, и вы уже не позволили API-интерфейсов на основе облака для вашего проекта, сделайте это сейчас:

    1. Откройте страницу ML Kit API , консоли Firebase.
    2. Если вы еще не модернизировал свой проект в план Blaze, нажмите кнопку Upgrade , чтобы сделать это. (Вам будет предложено обновить только если ваш проект не по плану Blaze.)

      Только проекты Blaze уровня могут использовать API-интерфейсы на основе облака.

    3. Если API - интерфейсы на основе облака еще не включен, нажмите Включить API для облачных вычислений.

    Если вы хотите использовать только модель на устройстве, вы можете пропустить этот шаг.

Теперь вы готовы начать распознавание текста в изображениях.

принципы ввода изображения

  • Для ML Комплект для точного распознавания текста, входные изображения должны содержать текст, который представлен достаточных данных пикселя. В идеале, для латинского текста, каждый символ должен быть не менее 16х16 пикселей. Для китайского, японского и корейского текста (поддерживается только облачных API), каждый символ должен быть 24x24 пикселей. Для всех языков, нет вообще никакой точности пользы для символов, чтобы быть больше, чем 24x24 пикселей.

    Так, например, 640х480 изображения может хорошо работать, чтобы отсканировать визитную карточку, которая занимает всю ширину изображения. Для того, чтобы отсканировать документ, напечатанный на букву размера бумаги, может потребоваться 720x1280 пикселей изображения.

  • Плохое фокус изображения может повредить точности распознавания текста. Если вы не получаете приемлемые результаты, попытайтесь спросить пользователя, чтобы вернуть изображение.

  • Если вы распознавание текста в режиме реального времени приложения, вы также можете рассмотреть общие размеры входных изображений. Меньшие изображения могут быть обработаны быстрее, так, чтобы уменьшить время ожидания, захват изображения при более низких разрешениях (имея в виду выше требования к точности) и убедитесь, что текст занимает столько же изображения, как это возможно. Смотрите также советы для повышения производительности в режиме реального времени .


Распознать текст в изображениях

Для распознавания текста в изображении с использованием либо на устройстве или облачной модели, запустить текстовый распознаватель, как описано ниже.

1. Запустите текстовый распознаватель

Для распознавания текста в изображении, создать FirebaseVisionImage объект либо из Bitmap , media.Image , ByteBuffer , массив байтов, или файл на устройстве. Затем передать FirebaseVisionImage объект в FirebaseVisionTextRecognizer «s processImage метода.

  1. Создать FirebaseVisionImage объект из изображения.

    • Чтобы создать FirebaseVisionImage объект из media.Image объекта, например, при захвате изображения с камеры устройства, передать media.Image объект и вращение изображения к FirebaseVisionImage.fromMediaImage() .

      Если вы используете CameraX библиотеку, OnImageCapturedListener и ImageAnalysis.Analyzer классов вычислить значение вращения для вас, так что вам просто нужно , чтобы преобразовать вращение одного из ML Кита ROTATION_ констант перед вызовом FirebaseVisionImage.fromMediaImage() :

      Ява

      private class YourAnalyzer implements ImageAnalysis.Analyzer {
      
          private int degreesToFirebaseRotation(int degrees) {
              switch (degrees) {
                  case 0:
                      return FirebaseVisionImageMetadata.ROTATION_0;
                  case 90:
                      return FirebaseVisionImageMetadata.ROTATION_90;
                  case 180:
                      return FirebaseVisionImageMetadata.ROTATION_180;
                  case 270:
                      return FirebaseVisionImageMetadata.ROTATION_270;
                  default:
                      throw new IllegalArgumentException(
                              "Rotation must be 0, 90, 180, or 270.");
              }
          }
      
          @Override
          public void analyze(ImageProxy imageProxy, int degrees) {
              if (imageProxy == null || imageProxy.getImage() == null) {
                  return;
              }
              Image mediaImage = imageProxy.getImage();
              int rotation = degreesToFirebaseRotation(degrees);
              FirebaseVisionImage image =
                      FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
              // Pass image to an ML Kit Vision API
              // ...
          }
      }
      

      Котлин + KTX

      private class YourImageAnalyzer : ImageAnalysis.Analyzer {
          private fun degreesToFirebaseRotation(degrees: Int): Int = when(degrees) {
              0 -> FirebaseVisionImageMetadata.ROTATION_0
              90 -> FirebaseVisionImageMetadata.ROTATION_90
              180 -> FirebaseVisionImageMetadata.ROTATION_180
              270 -> FirebaseVisionImageMetadata.ROTATION_270
              else -> throw Exception("Rotation must be 0, 90, 180, or 270.")
          }
      
          override fun analyze(imageProxy: ImageProxy?, degrees: Int) {
              val mediaImage = imageProxy?.image
              val imageRotation = degreesToFirebaseRotation(degrees)
              if (mediaImage != null) {
                  val image = FirebaseVisionImage.fromMediaImage(mediaImage, imageRotation)
                  // Pass image to an ML Kit Vision API
                  // ...
              }
          }
      }
      

      Если вы не используете библиотеку камеры, которая дает вам вращение на изображении, вы можете вычислить его от вращения устройства и ориентации датчика камеры в устройстве:

      Ява

      private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
      static {
          ORIENTATIONS.append(Surface.ROTATION_0, 90);
          ORIENTATIONS.append(Surface.ROTATION_90, 0);
          ORIENTATIONS.append(Surface.ROTATION_180, 270);
          ORIENTATIONS.append(Surface.ROTATION_270, 180);
      }
      
      /**
       * Get the angle by which an image must be rotated given the device's current
       * orientation.
       */
      @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
      private int getRotationCompensation(String cameraId, Activity activity, Context context)
              throws CameraAccessException {
          // Get the device's current rotation relative to its "native" orientation.
          // Then, from the ORIENTATIONS table, look up the angle the image must be
          // rotated to compensate for the device's rotation.
          int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
          int rotationCompensation = ORIENTATIONS.get(deviceRotation);
      
          // On most devices, the sensor orientation is 90 degrees, but for some
          // devices it is 270 degrees. For devices with a sensor orientation of
          // 270, rotate the image an additional 180 ((270 + 270) % 360) degrees.
          CameraManager cameraManager = (CameraManager) context.getSystemService(CAMERA_SERVICE);
          int sensorOrientation = cameraManager
                  .getCameraCharacteristics(cameraId)
                  .get(CameraCharacteristics.SENSOR_ORIENTATION);
          rotationCompensation = (rotationCompensation + sensorOrientation + 270) % 360;
      
          // Return the corresponding FirebaseVisionImageMetadata rotation value.
          int result;
          switch (rotationCompensation) {
              case 0:
                  result = FirebaseVisionImageMetadata.ROTATION_0;
                  break;
              case 90:
                  result = FirebaseVisionImageMetadata.ROTATION_90;
                  break;
              case 180:
                  result = FirebaseVisionImageMetadata.ROTATION_180;
                  break;
              case 270:
                  result = FirebaseVisionImageMetadata.ROTATION_270;
                  break;
              default:
                  result = FirebaseVisionImageMetadata.ROTATION_0;
                  Log.e(TAG, "Bad rotation value: " + rotationCompensation);
          }
          return result;
      }

      Котлин + KTX

      private val ORIENTATIONS = SparseIntArray()
      
      init {
          ORIENTATIONS.append(Surface.ROTATION_0, 90)
          ORIENTATIONS.append(Surface.ROTATION_90, 0)
          ORIENTATIONS.append(Surface.ROTATION_180, 270)
          ORIENTATIONS.append(Surface.ROTATION_270, 180)
      }
      /**
       * Get the angle by which an image must be rotated given the device's current
       * orientation.
       */
      @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
      @Throws(CameraAccessException::class)
      private fun getRotationCompensation(cameraId: String, activity: Activity, context: Context): Int {
          // Get the device's current rotation relative to its "native" orientation.
          // Then, from the ORIENTATIONS table, look up the angle the image must be
          // rotated to compensate for the device's rotation.
          val deviceRotation = activity.windowManager.defaultDisplay.rotation
          var rotationCompensation = ORIENTATIONS.get(deviceRotation)
      
          // On most devices, the sensor orientation is 90 degrees, but for some
          // devices it is 270 degrees. For devices with a sensor orientation of
          // 270, rotate the image an additional 180 ((270 + 270) % 360) degrees.
          val cameraManager = context.getSystemService(CAMERA_SERVICE) as CameraManager
          val sensorOrientation = cameraManager
                  .getCameraCharacteristics(cameraId)
                  .get(CameraCharacteristics.SENSOR_ORIENTATION)!!
          rotationCompensation = (rotationCompensation + sensorOrientation + 270) % 360
      
          // Return the corresponding FirebaseVisionImageMetadata rotation value.
          val result: Int
          when (rotationCompensation) {
              0 -> result = FirebaseVisionImageMetadata.ROTATION_0
              90 -> result = FirebaseVisionImageMetadata.ROTATION_90
              180 -> result = FirebaseVisionImageMetadata.ROTATION_180
              270 -> result = FirebaseVisionImageMetadata.ROTATION_270
              else -> {
                  result = FirebaseVisionImageMetadata.ROTATION_0
                  Log.e(TAG, "Bad rotation value: $rotationCompensation")
              }
          }
          return result
      }

      Затем передать media.Image объект и значение поворота к FirebaseVisionImage.fromMediaImage() :

      Ява

      FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);

      Котлин + KTX

      val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)
    • Чтобы создать FirebaseVisionImage объект из файла URI, передать контекст приложения и файл URI в FirebaseVisionImage.fromFilePath() . Это полезно , когда вы используете ACTION_GET_CONTENT намерение предложить пользователю выбрать изображение из галереи их приложения.

      Ява

      FirebaseVisionImage image;
      try {
          image = FirebaseVisionImage.fromFilePath(context, uri);
      } catch (IOException e) {
          e.printStackTrace();
      }

      Котлин + KTX

      val image: FirebaseVisionImage
      try {
          image = FirebaseVisionImage.fromFilePath(context, uri)
      } catch (e: IOException) {
          e.printStackTrace()
      }
    • Чтобы создать FirebaseVisionImage объект из ByteBuffer или массива байтов, сначала вычислить поворот изображения , как описано выше для media.Image ввода.

      Затем создать FirebaseVisionImageMetadata объект , который содержит изображение в высоту, ширину, формат кодирования цвета, и вращение:

      Ява

      FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
              .setWidth(480)   // 480x360 is typically sufficient for
              .setHeight(360)  // image recognition
              .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
              .setRotation(rotation)
              .build();

      Котлин + KTX

      val metadata = FirebaseVisionImageMetadata.Builder()
              .setWidth(480) // 480x360 is typically sufficient for
              .setHeight(360) // image recognition
              .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
              .setRotation(rotation)
              .build()

      Используйте буфер или массив, и объект метаданных, чтобы создать FirebaseVisionImage объекта:

      Ява

      FirebaseVisionImage image = FirebaseVisionImage.fromByteBuffer(buffer, metadata);
      // Or: FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(byteArray, metadata);

      Котлин + KTX

      val image = FirebaseVisionImage.fromByteBuffer(buffer, metadata)
      // Or: val image = FirebaseVisionImage.fromByteArray(byteArray, metadata)
    • Чтобы создать FirebaseVisionImage объект из Bitmap объекта:

      Ява

      FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);

      Котлин + KTX

      val image = FirebaseVisionImage.fromBitmap(bitmap)
      Изображение , представленное Bitmap объект должен быть в вертикальном положении, без дополнительного вращения требуется.

  2. Получить экземпляр FirebaseVisionTextRecognizer .

    Для того, чтобы использовать эту модель на устройстве:

    Ява

    FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance()
            .getOnDeviceTextRecognizer();

    Котлин + KTX

    val detector = FirebaseVision.getInstance()
            .onDeviceTextRecognizer

    Для того, чтобы использовать модель облачных:

    Ява

    FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance()
            .getCloudTextRecognizer();
    // Or, to change the default settings:
    //   FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance()
    //          .getCloudTextRecognizer(options);
    // Or, to provide language hints to assist with language detection:
    // See https://cloud.google.com/vision/docs/languages for supported languages
    FirebaseVisionCloudTextRecognizerOptions options = new FirebaseVisionCloudTextRecognizerOptions.Builder()
            .setLanguageHints(Arrays.asList("en", "hi"))
            .build();
    

    Котлин + KTX

    val detector = FirebaseVision.getInstance().cloudTextRecognizer
    // Or, to change the default settings:
    // val detector = FirebaseVision.getInstance().getCloudTextRecognizer(options)
    // Or, to provide language hints to assist with language detection:
    // See https://cloud.google.com/vision/docs/languages for supported languages
    val options = FirebaseVisionCloudTextRecognizerOptions.Builder()
            .setLanguageHints(listOf("en", "hi"))
            .build()
    
  3. И, наконец, передать изображение на processImage метода:

    Ява

    Task<FirebaseVisionText> result =
            detector.processImage(image)
                    .addOnSuccessListener(new OnSuccessListener<FirebaseVisionText>() {
                        @Override
                        public void onSuccess(FirebaseVisionText firebaseVisionText) {
                            // Task completed successfully
                            // ...
                        }
                    })
                    .addOnFailureListener(
                            new OnFailureListener() {
                                @Override
                                public void onFailure(@NonNull Exception e) {
                                    // Task failed with an exception
                                    // ...
                                }
                            });

    Котлин + KTX

    val result = detector.processImage(image)
            .addOnSuccessListener { firebaseVisionText ->
                // Task completed successfully
                // ...
            }
            .addOnFailureListener { e ->
                // Task failed with an exception
                // ...
            }

2. Извлечь текст из блоков распознанного текста

Если операция распознавания текста успешно установлено , то FirebaseVisionText объект будет передан к слушателю успеха. FirebaseVisionText объект содержит полный текст , признанный в образе и ноль или более TextBlock объектов.

Каждый TextBlock представляет собой прямоугольный блок текста, который содержит ноль или более Line объекты. Каждая Line объекта содержит ноль или более Element объектов, которые представляют собой слова и слова , подобные лиц (даты, номера и так далее).

Для каждого TextBlock , Line и Element объекта, вы можете получить текст , признанный в регионе и ограничивающую координату области.

Например:

Ява

String resultText = result.getText();
for (FirebaseVisionText.TextBlock block: result.getTextBlocks()) {
    String blockText = block.getText();
    Float blockConfidence = block.getConfidence();
    List<RecognizedLanguage> blockLanguages = block.getRecognizedLanguages();
    Point[] blockCornerPoints = block.getCornerPoints();
    Rect blockFrame = block.getBoundingBox();
    for (FirebaseVisionText.Line line: block.getLines()) {
        String lineText = line.getText();
        Float lineConfidence = line.getConfidence();
        List<RecognizedLanguage> lineLanguages = line.getRecognizedLanguages();
        Point[] lineCornerPoints = line.getCornerPoints();
        Rect lineFrame = line.getBoundingBox();
        for (FirebaseVisionText.Element element: line.getElements()) {
            String elementText = element.getText();
            Float elementConfidence = element.getConfidence();
            List<RecognizedLanguage> elementLanguages = element.getRecognizedLanguages();
            Point[] elementCornerPoints = element.getCornerPoints();
            Rect elementFrame = element.getBoundingBox();
        }
    }
}

Котлин + KTX

val resultText = result.text
for (block in result.textBlocks) {
    val blockText = block.text
    val blockConfidence = block.confidence
    val blockLanguages = block.recognizedLanguages
    val blockCornerPoints = block.cornerPoints
    val blockFrame = block.boundingBox
    for (line in block.lines) {
        val lineText = line.text
        val lineConfidence = line.confidence
        val lineLanguages = line.recognizedLanguages
        val lineCornerPoints = line.cornerPoints
        val lineFrame = line.boundingBox
        for (element in line.elements) {
            val elementText = element.text
            val elementConfidence = element.confidence
            val elementLanguages = element.recognizedLanguages
            val elementCornerPoints = element.cornerPoints
            val elementFrame = element.boundingBox
        }
    }
}

Советы по повышению производительности в режиме реального времени

Если вы хотите использовать модель на устройстве для распознавания текста в режиме реального времени приложения, следуйте этим инструкциям, чтобы достичь наилучших частот кадров:

  • Дроссельные вызовы текста распознаватель. Если новый кадр видео становится доступным в то время как текст распознаватель работает, кадр был отброшен.
  • Если вы используете вывод текста распознаватель для наложения графики на входном изображении, первым получить результат от ML Kit, а затем сделать изображение и наложение на один шаг. Поступая таким образом, вы оказываете на поверхность дисплея только один раз для каждого входного кадра.
  • Если вы используете Camera2 API, захват изображения в ImageFormat.YUV_420_888 формате.

    Если вы используете старую API камеры, захватывать изображения в ImageFormat.NV21 формате.

  • Рассмотрим захват изображений с более низким разрешением. Тем не менее, иметь в виду требования размеров изображения этого API.

Следующие шаги


Распознать текст в изображениях документов

Чтобы распознать текст документа, настроить и запустить облачный документ текста распознаватель, как описано ниже.

Документ распознавание текста API, описанный ниже, обеспечивает интерфейс, который предназначен, чтобы быть более удобными для работы с изображениями документов. Однако, если вы предпочитаете интерфейс , предоставляемый в FirebaseVisionTextRecognizer API, вы можете использовать его вместо того, чтобы сканировать документы, настроив облако текста распознаватель , чтобы использовать плотную текстовую модель .

Чтобы использовать API распознавания текста документа:

1. Запустите текстовый распознаватель

Для распознавания текста в изображении, создать FirebaseVisionImage объект либо из Bitmap , media.Image , ByteBuffer , массив байтов, или файл на устройстве. Затем передать FirebaseVisionImage объект в FirebaseVisionDocumentTextRecognizer «s processImage метода.

  1. Создать FirebaseVisionImage объект из изображения.

    • Чтобы создать FirebaseVisionImage объект из media.Image объекта, например, при захвате изображения с камеры устройства, передать media.Image объект и вращение изображения к FirebaseVisionImage.fromMediaImage() .

      Если вы используете CameraX библиотеку, OnImageCapturedListener и ImageAnalysis.Analyzer классов вычислить значение вращения для вас, так что вам просто нужно , чтобы преобразовать вращение одного из ML Кита ROTATION_ констант перед вызовом FirebaseVisionImage.fromMediaImage() :

      Ява

      private class YourAnalyzer implements ImageAnalysis.Analyzer {
      
          private int degreesToFirebaseRotation(int degrees) {
              switch (degrees) {
                  case 0:
                      return FirebaseVisionImageMetadata.ROTATION_0;
                  case 90:
                      return FirebaseVisionImageMetadata.ROTATION_90;
                  case 180:
                      return FirebaseVisionImageMetadata.ROTATION_180;
                  case 270:
                      return FirebaseVisionImageMetadata.ROTATION_270;
                  default:
                      throw new IllegalArgumentException(
                              "Rotation must be 0, 90, 180, or 270.");
              }
          }
      
          @Override
          public void analyze(ImageProxy imageProxy, int degrees) {
              if (imageProxy == null || imageProxy.getImage() == null) {
                  return;
              }
              Image mediaImage = imageProxy.getImage();
              int rotation = degreesToFirebaseRotation(degrees);
              FirebaseVisionImage image =
                      FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
              // Pass image to an ML Kit Vision API
              // ...
          }
      }
      

      Котлин + KTX

      private class YourImageAnalyzer : ImageAnalysis.Analyzer {
          private fun degreesToFirebaseRotation(degrees: Int): Int = when(degrees) {
              0 -> FirebaseVisionImageMetadata.ROTATION_0
              90 -> FirebaseVisionImageMetadata.ROTATION_90
              180 -> FirebaseVisionImageMetadata.ROTATION_180
              270 -> FirebaseVisionImageMetadata.ROTATION_270
              else -> throw Exception("Rotation must be 0, 90, 180, or 270.")
          }
      
          override fun analyze(imageProxy: ImageProxy?, degrees: Int) {
              val mediaImage = imageProxy?.image
              val imageRotation = degreesToFirebaseRotation(degrees)
              if (mediaImage != null) {
                  val image = FirebaseVisionImage.fromMediaImage(mediaImage, imageRotation)
                  // Pass image to an ML Kit Vision API
                  // ...
              }
          }
      }
      

      Если вы не используете библиотеку камеры, которая дает вам вращение на изображении, вы можете вычислить его от вращения устройства и ориентации датчика камеры в устройстве:

      Ява

      private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
      static {
          ORIENTATIONS.append(Surface.ROTATION_0, 90);
          ORIENTATIONS.append(Surface.ROTATION_90, 0);
          ORIENTATIONS.append(Surface.ROTATION_180, 270);
          ORIENTATIONS.append(Surface.ROTATION_270, 180);
      }
      
      /**
       * Get the angle by which an image must be rotated given the device's current
       * orientation.
       */
      @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
      private int getRotationCompensation(String cameraId, Activity activity, Context context)
              throws CameraAccessException {
          // Get the device's current rotation relative to its "native" orientation.
          // Then, from the ORIENTATIONS table, look up the angle the image must be
          // rotated to compensate for the device's rotation.
          int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
          int rotationCompensation = ORIENTATIONS.get(deviceRotation);
      
          // On most devices, the sensor orientation is 90 degrees, but for some
          // devices it is 270 degrees. For devices with a sensor orientation of
          // 270, rotate the image an additional 180 ((270 + 270) % 360) degrees.
          CameraManager cameraManager = (CameraManager) context.getSystemService(CAMERA_SERVICE);
          int sensorOrientation = cameraManager
                  .getCameraCharacteristics(cameraId)
                  .get(CameraCharacteristics.SENSOR_ORIENTATION);
          rotationCompensation = (rotationCompensation + sensorOrientation + 270) % 360;
      
          // Return the corresponding FirebaseVisionImageMetadata rotation value.
          int result;
          switch (rotationCompensation) {
              case 0:
                  result = FirebaseVisionImageMetadata.ROTATION_0;
                  break;
              case 90:
                  result = FirebaseVisionImageMetadata.ROTATION_90;
                  break;
              case 180:
                  result = FirebaseVisionImageMetadata.ROTATION_180;
                  break;
              case 270:
                  result = FirebaseVisionImageMetadata.ROTATION_270;
                  break;
              default:
                  result = FirebaseVisionImageMetadata.ROTATION_0;
                  Log.e(TAG, "Bad rotation value: " + rotationCompensation);
          }
          return result;
      }

      Котлин + KTX

      private val ORIENTATIONS = SparseIntArray()
      
      init {
          ORIENTATIONS.append(Surface.ROTATION_0, 90)
          ORIENTATIONS.append(Surface.ROTATION_90, 0)
          ORIENTATIONS.append(Surface.ROTATION_180, 270)
          ORIENTATIONS.append(Surface.ROTATION_270, 180)
      }
      /**
       * Get the angle by which an image must be rotated given the device's current
       * orientation.
       */
      @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
      @Throws(CameraAccessException::class)
      private fun getRotationCompensation(cameraId: String, activity: Activity, context: Context): Int {
          // Get the device's current rotation relative to its "native" orientation.
          // Then, from the ORIENTATIONS table, look up the angle the image must be
          // rotated to compensate for the device's rotation.
          val deviceRotation = activity.windowManager.defaultDisplay.rotation
          var rotationCompensation = ORIENTATIONS.get(deviceRotation)
      
          // On most devices, the sensor orientation is 90 degrees, but for some
          // devices it is 270 degrees. For devices with a sensor orientation of
          // 270, rotate the image an additional 180 ((270 + 270) % 360) degrees.
          val cameraManager = context.getSystemService(CAMERA_SERVICE) as CameraManager
          val sensorOrientation = cameraManager
                  .getCameraCharacteristics(cameraId)
                  .get(CameraCharacteristics.SENSOR_ORIENTATION)!!
          rotationCompensation = (rotationCompensation + sensorOrientation + 270) % 360
      
          // Return the corresponding FirebaseVisionImageMetadata rotation value.
          val result: Int
          when (rotationCompensation) {
              0 -> result = FirebaseVisionImageMetadata.ROTATION_0
              90 -> result = FirebaseVisionImageMetadata.ROTATION_90
              180 -> result = FirebaseVisionImageMetadata.ROTATION_180
              270 -> result = FirebaseVisionImageMetadata.ROTATION_270
              else -> {
                  result = FirebaseVisionImageMetadata.ROTATION_0
                  Log.e(TAG, "Bad rotation value: $rotationCompensation")
              }
          }
          return result
      }

      Затем передать media.Image объект и значение поворота к FirebaseVisionImage.fromMediaImage() :

      Ява

      FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);

      Котлин + KTX

      val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)
    • Чтобы создать FirebaseVisionImage объект из файла URI, передать контекст приложения и файл URI в FirebaseVisionImage.fromFilePath() . Это полезно , когда вы используете ACTION_GET_CONTENT намерение предложить пользователю выбрать изображение из галереи их приложения.

      Ява

      FirebaseVisionImage image;
      try {
          image = FirebaseVisionImage.fromFilePath(context, uri);
      } catch (IOException e) {
          e.printStackTrace();
      }

      Котлин + KTX

      val image: FirebaseVisionImage
      try {
          image = FirebaseVisionImage.fromFilePath(context, uri)
      } catch (e: IOException) {
          e.printStackTrace()
      }
    • Чтобы создать FirebaseVisionImage объект из ByteBuffer или массива байтов, сначала вычислить поворот изображения , как описано выше для media.Image ввода.

      Затем создать FirebaseVisionImageMetadata объект , который содержит изображение в высоту, ширину, формат кодирования цвета, и вращение:

      Ява

      FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
              .setWidth(480)   // 480x360 is typically sufficient for
              .setHeight(360)  // image recognition
              .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
              .setRotation(rotation)
              .build();

      Котлин + KTX

      val metadata = FirebaseVisionImageMetadata.Builder()
              .setWidth(480) // 480x360 is typically sufficient for
              .setHeight(360) // image recognition
              .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
              .setRotation(rotation)
              .build()

      Используйте буфер или массив, и объект метаданных, чтобы создать FirebaseVisionImage объекта:

      Ява

      FirebaseVisionImage image = FirebaseVisionImage.fromByteBuffer(buffer, metadata);
      // Or: FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(byteArray, metadata);

      Котлин + KTX

      val image = FirebaseVisionImage.fromByteBuffer(buffer, metadata)
      // Or: val image = FirebaseVisionImage.fromByteArray(byteArray, metadata)
    • Чтобы создать FirebaseVisionImage объект из Bitmap объекта:

      Ява

      FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);

      Котлин + KTX

      val image = FirebaseVisionImage.fromBitmap(bitmap)
      Изображение , представленное Bitmap объект должен быть в вертикальном положении, без дополнительного вращения требуется.

  2. Получить экземпляр FirebaseVisionDocumentTextRecognizer :

    Ява

    FirebaseVisionDocumentTextRecognizer detector = FirebaseVision.getInstance()
            .getCloudDocumentTextRecognizer();
    // Or, to provide language hints to assist with language detection:
    // See https://cloud.google.com/vision/docs/languages for supported languages
    FirebaseVisionCloudDocumentRecognizerOptions options =
            new FirebaseVisionCloudDocumentRecognizerOptions.Builder()
                    .setLanguageHints(Arrays.asList("en", "hi"))
                    .build();
    FirebaseVisionDocumentTextRecognizer detector = FirebaseVision.getInstance()
            .getCloudDocumentTextRecognizer(options);

    Котлин + KTX

    val detector = FirebaseVision.getInstance()
            .cloudDocumentTextRecognizer
    // Or, to provide language hints to assist with language detection:
    // See https://cloud.google.com/vision/docs/languages for supported languages
    val options = FirebaseVisionCloudDocumentRecognizerOptions.Builder()
            .setLanguageHints(listOf("en", "hi"))
            .build()
    val detector = FirebaseVision.getInstance()
            .getCloudDocumentTextRecognizer(options)

  3. И, наконец, передать изображение на processImage метода:

    Ява

    detector.processImage(myImage)
            .addOnSuccessListener(new OnSuccessListener<FirebaseVisionDocumentText>() {
                @Override
                public void onSuccess(FirebaseVisionDocumentText result) {
                    // Task completed successfully
                    // ...
                }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    // Task failed with an exception
                    // ...
                }
            });

    Котлин + KTX

    detector.processImage(myImage)
            .addOnSuccessListener { firebaseVisionDocumentText ->
                // Task completed successfully
                // ...
            }
            .addOnFailureListener { e ->
                // Task failed with an exception
                // ...
            }

2. Извлечь текст из блоков распознанного текста

Если операция распознавания текста успешно, она возвращает FirebaseVisionDocumentText объект. FirebaseVisionDocumentText объект содержит полный текст , признанный в образе и иерархии объектов, отражающих структуру признанного документа:

Для каждого Block , Paragraph , Word и Symbol объекта, вы можете получить текст , признанный в регионе и ограничивающую координату области.

Например:

Ява

String resultText = result.getText();
for (FirebaseVisionDocumentText.Block block: result.getBlocks()) {
    String blockText = block.getText();
    Float blockConfidence = block.getConfidence();
    List<RecognizedLanguage> blockRecognizedLanguages = block.getRecognizedLanguages();
    Rect blockFrame = block.getBoundingBox();
    for (FirebaseVisionDocumentText.Paragraph paragraph: block.getParagraphs()) {
        String paragraphText = paragraph.getText();
        Float paragraphConfidence = paragraph.getConfidence();
        List<RecognizedLanguage> paragraphRecognizedLanguages = paragraph.getRecognizedLanguages();
        Rect paragraphFrame = paragraph.getBoundingBox();
        for (FirebaseVisionDocumentText.Word word: paragraph.getWords()) {
            String wordText = word.getText();
            Float wordConfidence = word.getConfidence();
            List<RecognizedLanguage> wordRecognizedLanguages = word.getRecognizedLanguages();
            Rect wordFrame = word.getBoundingBox();
            for (FirebaseVisionDocumentText.Symbol symbol: word.getSymbols()) {
                String symbolText = symbol.getText();
                Float symbolConfidence = symbol.getConfidence();
                List<RecognizedLanguage> symbolRecognizedLanguages = symbol.getRecognizedLanguages();
                Rect symbolFrame = symbol.getBoundingBox();
            }
        }
    }
}

Котлин + KTX

val resultText = result.text
for (block in result.blocks) {
    val blockText = block.text
    val blockConfidence = block.confidence
    val blockRecognizedLanguages = block.recognizedLanguages
    val blockFrame = block.boundingBox
    for (paragraph in block.paragraphs) {
        val paragraphText = paragraph.text
        val paragraphConfidence = paragraph.confidence
        val paragraphRecognizedLanguages = paragraph.recognizedLanguages
        val paragraphFrame = paragraph.boundingBox
        for (word in paragraph.words) {
            val wordText = word.text
            val wordConfidence = word.confidence
            val wordRecognizedLanguages = word.recognizedLanguages
            val wordFrame = word.boundingBox
            for (symbol in word.symbols) {
                val symbolText = symbol.text
                val symbolConfidence = symbol.confidence
                val symbolRecognizedLanguages = symbol.recognizedLanguages
                val symbolFrame = symbol.boundingBox
            }
        }
    }
}

Следующие шаги