Erkennen Sie Text in Bildern mit ML Kit auf Android

Sie können ML Kit verwenden, um Text in Bildern zu erkennen. ML Kit verfügt sowohl über eine Allzweck-API, die sich zum Erkennen von Text in Bildern eignet, z. B. den Text eines Straßenschilds, als auch über eine API, die für die Erkennung von Dokumententext optimiert ist. Die Allzweck-API verfügt sowohl über geräteinterne als auch Cloud-basierte Modelle. Die Dokumenttexterkennung ist nur als Cloud-basiertes Modell verfügbar. Siehe die Übersicht für einen Vergleich der Cloud und On-Device - Modelle.

Bevor Sie beginnen

  1. Wenn Sie nicht bereits haben, fügen Sie Firebase zu dem Android - Projekt .
  2. Fügen Sie die Abhängigkeiten für die ML Kit Android - Bibliotheken zu Ihrem Modul (app-Ebene) Gradle Datei ( in der Regel 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'
    }
    
  3. Optional , aber empfohlen: Wenn Sie die On-Device - API zu verwenden, konfigurieren Sie Ihre App , um automatisch das ML - Modell auf das Gerät herunterzuladen , nachdem die App aus dem Play Store installiert ist.

    Dazu fügen Sie die folgende Erklärung zu Ihrer App AndroidManifest.xml Datei:

    <application ...>
      ...
      <meta-data
          android:name="com.google.firebase.ml.vision.DEPENDENCIES"
          android:value="ocr" />
      <!-- To use multiple models: android:value="ocr,model2,model3" -->
    </application>
    
    Wenn Sie nicht aktivieren installieren Zeitmodell - Downloads, wird das Modell , das Sie das erste Mal auf den Detektor auf dem Gerät laufen heruntergeladen werden. Anfragen, die Sie vor Abschluss des Downloads stellen, führen zu keinen Ergebnissen.
  4. Wenn Sie das Cloud-basierte Modell verwenden möchten und die Cloud-basierten APIs für Ihr Projekt noch nicht aktiviert haben, tun Sie dies jetzt:

    1. Öffnen Sie die ML - Kit APIs Seite der Konsole Firebase.
    2. Wenn Sie nicht bereits Ihr Projekt zu einem Blaze Preisgestaltungsplan aktualisiert haben, klicken Sie auf, dies zu tun Upgrades. (Sie werden nur dann zum Upgrade aufgefordert, wenn Ihr Projekt nicht im Blaze-Plan enthalten ist.)

      Nur Blaze-Level-Projekte können Cloud-basierte APIs verwenden.

    3. Wenn Cloud-basierte APIs nicht bereits aktiviert ist, klicken Sie auf Aktivieren Cloud-basierte APIs.

    Wenn Sie nur das On-Device-Modell verwenden möchten, können Sie diesen Schritt überspringen.

Jetzt können Sie mit der Texterkennung in Bildern beginnen.

Richtlinien für die Eingabe von Bildern

  • Damit ML Kit Text richtig erkennen kann, müssen Eingabebilder Text enthalten, der durch ausreichend Pixeldaten dargestellt wird. Idealerweise sollte für lateinischen Text jedes Zeichen mindestens 16 x 16 Pixel groß sein. Bei chinesischem, japanischem und koreanischem Text (wird nur von den Cloud-basierten APIs unterstützt) sollte jedes Zeichen 24 x 24 Pixel groß sein. Bei allen Sprachen gibt es im Allgemeinen keinen Genauigkeitsvorteil für Zeichen, die größer als 24 x 24 Pixel sind.

    So eignet sich beispielsweise ein 640 x 480-Bild gut zum Scannen einer Visitenkarte, die die gesamte Breite des Bilds einnimmt. Um ein auf Papier im Letter-Format gedrucktes Dokument zu scannen, ist möglicherweise ein Bild mit 720 x 1280 Pixeln erforderlich.

  • Ein schlechter Bildfokus kann die Genauigkeit der Texterkennung beeinträchtigen. Wenn Sie keine akzeptablen Ergebnisse erhalten, bitten Sie den Benutzer, das Bild erneut aufzunehmen.

  • Wenn Sie Text in einer Echtzeitanwendung erkennen, sollten Sie auch die Gesamtabmessungen der Eingabebilder berücksichtigen. Kleinere Bilder können schneller verarbeitet werden. Um die Latenz zu reduzieren, nehmen Sie Bilder mit niedrigeren Auflösungen auf (beachten Sie die oben genannten Genauigkeitsanforderungen) und stellen Sie sicher, dass der Text so viel wie möglich vom Bild einnimmt. Siehe auch Tipps Echtzeit - Performance zu verbessern .


Text in Bildern erkennen

Führen Sie die Texterkennung wie unten beschrieben aus, um Text in einem Bild mit einem geräteinternen oder cloudbasierten Modell zu erkennen.

1. Führen Sie die Texterkennung aus

Um Text in einem Bild zu erkennen, erstellen Sie ein FirebaseVisionImage Objekt entweder aus einer Bitmap , media.Image , ByteBuffer , Byte - Array oder eine Datei auf dem Gerät. Dann passiert das FirebaseVisionImage Objekt des FirebaseVisionTextRecognizer ‚s processImage Methode.

  1. Erstellen Sie ein FirebaseVisionImage Objekt aus dem Bild.

    • Um ein erstellen FirebaseVisionImage Objekt aus einem media.Image Objekt, beispielsweise , wenn von einem Gerät der Kamera ein Bild aufzeichnen, vorbei an das media.Image Objekt und die Bildrotation zu FirebaseVisionImage.fromMediaImage() .

      Wenn Sie die Verwendung CameraX Bibliothek, die OnImageCapturedListener und ImageAnalysis.Analyzer berechnen Klassen den Rotationswert für Sie, so dass Sie nur die Drehung zu einem der ML Kits müssen konvertieren ROTATION_ Konstanten vor dem Aufruf FirebaseVisionImage.fromMediaImage() :

      Java

      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
              // ...
          }
      }
      

      Kotlin+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
                  // ...
              }
          }
      }
      

      Wenn Sie keine Kamerabibliothek verwenden, die Ihnen die Drehung des Bildes liefert, können Sie sie aus der Drehung des Geräts und der Ausrichtung des Kamerasensors im Gerät berechnen:

      Java

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

      Kotlin+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
      }

      Dann passiert das media.Image Objekt und den Drehwert FirebaseVisionImage.fromMediaImage() :

      Java

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

      Kotlin+KTX

      val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)
    • So erstellen Sie ein FirebaseVisionImage Objekt aus einer Datei URI, übergeben Sie die App Kontext und Datei - URI zu FirebaseVisionImage.fromFilePath() . Dies ist nützlich , wenn Sie eine verwenden ACTION_GET_CONTENT Absicht , den Benutzer aufzufordern , ein Bild aus ihrer Galerie App auswählen.

      Java

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

      Kotlin+KTX

      val image: FirebaseVisionImage
      try {
          image = FirebaseVisionImage.fromFilePath(context, uri)
      } catch (e: IOException) {
          e.printStackTrace()
      }
    • Um ein zu erstellen FirebaseVisionImage Objekt aus einem ByteBuffer oder einem Byte - Array, berechnet zuerst die Bilddrehung , wie oben beschrieben für media.Image Eingabe.

      Dann erstellen FirebaseVisionImageMetadata Objekt, das die Bildhöhe, Breite enthält, Farbcodierungsformat, und die Rotation:

      Java

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

      Kotlin+KTX

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

      Verwenden Sie den Puffer oder Array und das Metadatenobjekt, eine erstellen FirebaseVisionImage Objekt:

      Java

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

      Kotlin+KTX

      val image = FirebaseVisionImage.fromByteBuffer(buffer, metadata)
      // Or: val image = FirebaseVisionImage.fromByteArray(byteArray, metadata)
    • Um ein zu erstellen FirebaseVisionImage Objekt aus einem Bitmap - Objekt:

      Java

      FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);

      Kotlin+KTX

      val image = FirebaseVisionImage.fromBitmap(bitmap)
      Das Bild , das durch das dargestellte Bitmap - Objekt muss aufrecht sein, ohne zusätzliche Drehung erforderlich.

  2. Erhalten Sie eine Instanz von FirebaseVisionTextRecognizer .

    So verwenden Sie das On-Device-Modell:

    Java

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

    Kotlin+KTX

    val detector = FirebaseVision.getInstance()
            .onDeviceTextRecognizer

    So verwenden Sie das Cloud-basierte Modell:

    Java

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

    Kotlin+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. Schließlich passiert das Bild auf die processImage Methode:

    Java

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

    Kotlin+KTX

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

2. Text aus Blöcken erkannten Texts extrahieren

Wenn der Texterkennungsvorgang erfolgreich ist , ein FirebaseVisionText wird Objekt für den Erfolg Zuhörer weitergegeben werden. Ein FirebaseVisionText Objekt enthält den vollständigen Text im Bild erkannt und null oder mehr TextBlock - Objekten.

Jeder TextBlock darstellt , einen rechteckigen Block von Text, der enthält null oder mehr Line Jede Line Objekt enthält null oder mehr Element - Objekte, die repräsentieren Worte und Wort wie Entitäten (Daten, Zahlen, und so weiter).

Für jeden TextBlock , Line und Element - Objekt, können Sie den Text in der Region und die begrenzenden Koordinaten der Region anerkannt bekommen.

Zum Beispiel:

Java

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

Kotlin+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
        }
    }
}

Tipps zur Verbesserung der Echtzeitleistung

Wenn Sie das On-Device-Modell verwenden möchten, um Text in einer Echtzeitanwendung zu erkennen, befolgen Sie diese Richtlinien, um die besten Frameraten zu erzielen:

  • Drosseln Sie Anrufe an die Texterkennung. Wenn ein neuer Videoframe verfügbar wird, während die Texterkennung ausgeführt wird, lassen Sie den Frame fallen.
  • Wenn Sie die Ausgabe des Texterkenners verwenden, um Grafiken auf dem Eingabebild zu überlagern, rufen Sie zuerst das Ergebnis von ML Kit ab und rendern Sie dann das Bild und die Überlagerung in einem einzigen Schritt. Auf diese Weise rendern Sie für jeden Eingabeframe nur einmal auf der Anzeigeoberfläche.
  • Wenn Sie die Camera2 API, die Aufnahmen in verwenden ImageFormat.YUV_420_888 Format.

    Wenn Sie den älteren Kamera - API, die Aufnahmen in verwenden ImageFormat.NV21 Format.

  • Ziehen Sie in Erwägung, Bilder mit einer niedrigeren Auflösung aufzunehmen. Beachten Sie jedoch auch die Anforderungen an die Bildabmessungen dieser API.

Nächste Schritte


Text in Bildern von Dokumenten erkennen

Um den Text eines Dokuments zu erkennen, konfigurieren und führen Sie die cloudbasierte Dokumenttexterkennung wie unten beschrieben aus.

Die unten beschriebene Dokumenttexterkennungs-API stellt eine Schnittstelle bereit, die für die Arbeit mit Dokumentenbildern bequemer sein soll. Wenn Sie jedoch die Schnittstelle von der mitgelieferten bevorzugen FirebaseVisionTextRecognizer API, können Sie es verwenden , anstatt auf Dokumente scannen durch die Wolke Texterkennungs Konfiguration auf das dichte Textmodell zu verwenden .

So verwenden Sie die Dokumenttexterkennungs-API:

1. Führen Sie die Texterkennung aus

Um Text in einem Bild zu erkennen, erstellen Sie ein FirebaseVisionImage Objekt entweder aus einer Bitmap , media.Image , ByteBuffer , Byte - Array oder eine Datei auf dem Gerät. Dann passiert das FirebaseVisionImage Objekt des FirebaseVisionDocumentTextRecognizer ‚s processImage Methode.

  1. Erstellen Sie ein FirebaseVisionImage Objekt aus dem Bild.

    • Um ein erstellen FirebaseVisionImage Objekt aus einem media.Image Objekt, beispielsweise , wenn von einem Gerät der Kamera ein Bild aufzeichnen, vorbei an das media.Image Objekt und die Bildrotation zu FirebaseVisionImage.fromMediaImage() .

      Wenn Sie die Verwendung CameraX Bibliothek, die OnImageCapturedListener und ImageAnalysis.Analyzer berechnen Klassen den Rotationswert für Sie, so dass Sie nur die Drehung zu einem der ML Kits müssen konvertieren ROTATION_ Konstanten vor dem Aufruf FirebaseVisionImage.fromMediaImage() :

      Java

      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
              // ...
          }
      }
      

      Kotlin+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
                  // ...
              }
          }
      }
      

      Wenn Sie keine Kamerabibliothek verwenden, die Ihnen die Drehung des Bildes liefert, können Sie sie aus der Drehung des Geräts und der Ausrichtung des Kamerasensors im Gerät berechnen:

      Java

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

      Kotlin+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
      }

      Dann passiert das media.Image Objekt und den Drehwert FirebaseVisionImage.fromMediaImage() :

      Java

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

      Kotlin+KTX

      val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)
    • So erstellen Sie ein FirebaseVisionImage Objekt aus einer Datei URI, übergeben Sie die App Kontext und Datei - URI zu FirebaseVisionImage.fromFilePath() . Dies ist nützlich , wenn Sie eine verwenden ACTION_GET_CONTENT Absicht , den Benutzer aufzufordern , ein Bild aus ihrer Galerie App auswählen.

      Java

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

      Kotlin+KTX

      val image: FirebaseVisionImage
      try {
          image = FirebaseVisionImage.fromFilePath(context, uri)
      } catch (e: IOException) {
          e.printStackTrace()
      }
    • Um ein zu erstellen FirebaseVisionImage Objekt aus einem ByteBuffer oder einem Byte - Array, berechnet zuerst die Bilddrehung , wie oben beschrieben für media.Image Eingabe.

      Dann erstellen FirebaseVisionImageMetadata Objekt, das die Bildhöhe, Breite enthält, Farbcodierungsformat, und die Rotation:

      Java

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

      Kotlin+KTX

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

      Verwenden Sie den Puffer oder Array und das Metadatenobjekt, eine erstellen FirebaseVisionImage Objekt:

      Java

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

      Kotlin+KTX

      val image = FirebaseVisionImage.fromByteBuffer(buffer, metadata)
      // Or: val image = FirebaseVisionImage.fromByteArray(byteArray, metadata)
    • Um ein zu erstellen FirebaseVisionImage Objekt aus einem Bitmap - Objekt:

      Java

      FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);

      Kotlin+KTX

      val image = FirebaseVisionImage.fromBitmap(bitmap)
      Das Bild , das durch das dargestellte Bitmap - Objekt muss aufrecht sein, ohne zusätzliche Drehung erforderlich.

  2. Erhalten Sie eine Instanz von FirebaseVisionDocumentTextRecognizer :

    Java

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

    Kotlin+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. Schließlich passiert das Bild auf die processImage Methode:

    Java

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

    Kotlin+KTX

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

2. Text aus Blöcken erkannten Texts extrahieren

Wenn die Texterkennung Operation erfolgreich ist , wird es eine Rückkehr FirebaseVisionDocumentText Objekt. Ein FirebaseVisionDocumentText Objekt enthält den vollständigen Text in dem Bild erkannt und eine Hierarchie von Objekten, die die Struktur des erkannten Dokuments beziehen:

Für jeden Block - , Paragraph , Word und Symbol Objekt, können Sie den Text in der Region und die begrenzenden Koordinaten der Region anerkannt bekommen.

Zum Beispiel:

Java

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

Kotlin+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
            }
        }
    }
}

Nächste Schritte