Rozpoznawanie tekstu w obrazach za pomocą Firebase ML na Androida

Możesz używać systemów uczących się Firebase do rozpoznawania tekstu na obrazach. Firebase ML ma Są to interfejsy API ogólnego przeznaczenia, odpowiednie do rozpoznawania tekstu na obrazach, tekstu znaku drogowego oraz interfejs API zoptymalizowany pod kątem rozpoznawania tekstu dokumenty.

.

Zanim zaczniesz

  1. Jeśli jeszcze nie masz tego za sobą, dodaj Firebase do swojego projektu na Androida.
  2. w pliku Gradle (na poziomie aplikacji) modułu, (zwykle <project>/<app-module>/build.gradle.kts lub <project>/<app-module>/build.gradle), dodaj zależność z biblioteką Firebase ML Vision na Androida. Zalecamy użycie metody Funkcja BoM Firebase na Androida aby kontrolować obsługę wersji biblioteki.
    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:33.1.2"))
    
        // Add the dependency for the Firebase ML Vision library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-ml-vision'
    }
    

    Korzystając z BM Firebase Android BoM, Twoja aplikacja zawsze używa zgodnych wersji bibliotek Firebase na Androida.

    (Wersja alternatywna) Dodawanie zależności biblioteki Firebase bez korzystania z BM

    Jeśli nie chcesz używać Firebase BoM, musisz określić każdą wersję biblioteki Firebase w wierszu zależności.

    Pamiętaj, że jeśli używasz wielu bibliotek Firebase w aplikacji, zalecamy korzystanie z BoM do zarządzania wersjami biblioteki, dzięki czemu wszystkie wersje

    dependencies {
        // Add the dependency for the Firebase ML Vision library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-ml-vision:24.1.0'
    }
    
    Szukasz modułu biblioteki korzystającego z usługi Kotlin? Zaczyna się za Październik 2023 r. (Firebase BoM 32.5.0), programiści, zarówno w języku Kotlin, jak i w języku Java, zależą od modułu biblioteki głównej (więcej informacji znajdziesz w Najczęstsze pytania na temat tej inicjatywy).
  3. Jeśli w swoim projekcie nie włączono jeszcze interfejsów API działających w chmurze, zrób to. teraz:

    1. Otwórz Firebase ML API w konsoli Firebase.
    2. Jeśli Twój projekt nie został jeszcze przeniesiony na abonament Blaze, kliknij Aby to zrobić, przejdź na wyższą wersję. (Prośba o uaktualnienie wyświetli się tylko wtedy, gdy projekt nie jest objęty abonamentem Blaze).

      Tylko projekty na poziomie Blaze mogą korzystać z interfejsów API działających w chmurze.

    3. Jeśli interfejsy API działające w chmurze nie są włączone, kliknij Włącz działające w chmurze interfejsów API.
    .

Teraz możesz zacząć rozpoznawać tekst na obrazach.

Wytyczne dotyczące obrazu wejściowego

  • Aby systemy uczące się w Firebase mogły dokładnie rozpoznawać tekst, obrazy wejściowe muszą zawierać który jest reprezentowany przez wystarczającą ilość danych pikseli. najlepiej dla alfabetu łacińskiego tekstu, każdy znak powinien mieć co najmniej 16 x 16 pikseli. W przypadku języka chińskiego, tekstu japońskiego i koreańskiego, każdy powinien mieć rozmiar 24 x 24 piksele. Dla wszystkich języków zwykle nie ma funkcji w przypadku znaków większych niż 24 x 24 piksele.

    Na przykład obraz o wymiarach 640 x 480 może się sprawdzić do zeskanowania wizytówki zajmuje całą szerokość obrazu. Aby zeskanować dokument wydrukowany na na papierze w formacie letter, może być wymagany obraz o wymiarach 720 x 1280 pikseli.

  • Słaba ostrość obrazu może obniżyć dokładność rozpoznawania tekstu. Jeśli nim nie jesteś uzyskać akceptowalne wyniki, poproś użytkownika o ponowne przechwycenie obrazu.


Rozpoznawanie tekstu w obrazach

Aby rozpoznać tekst na obrazie, uruchom moduł rozpoznawania tekstu zgodnie z opisem poniżej.

1. Uruchom moduł rozpoznawania tekstu

Aby rozpoznać tekst na obrazie, utwórz obiekt FirebaseVisionImage z obiektu Bitmap, media.Image, ByteBuffer, tablicy bajtów lub pliku w urządzenia. Następnie przekaż obiekt FirebaseVisionImage do funkcji Metoda processImage użytkownika FirebaseVisionTextRecognizer.

  1. Utwórz obiekt FirebaseVisionImage na podstawie swojego obrazu.

    • Aby utworzyć obiekt FirebaseVisionImage na podstawie media.Image, np. podczas przechwytywania obrazu z z aparatu urządzenia, przekazać obiekt media.Image oraz w kierunku FirebaseVisionImage.fromMediaImage().

      Jeśli używasz tagu CameraX, OnImageCapturedListener oraz ImageAnalysis.Analyzer klasy obliczają wartość rotacji więc trzeba tylko przekonwertować rotację na jeden z mechanizmów ML Firebase Stały ROTATION_ przed nawiązaniem połączenia FirebaseVisionImage.fromMediaImage():

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

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

      Jeśli nie korzystasz z biblioteki aparatu zapewniającej obrót obrazu, może go obliczyć na podstawie obrotu urządzenia i orientacji aparatu czujnik w urządzeniu:

      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
      }

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

      Następnie przekaż obiekt media.Image oraz wartość rotacji do FirebaseVisionImage.fromMediaImage():

      Kotlin+KTX

      val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)

      Java

      FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
    • Aby utworzyć obiekt FirebaseVisionImage na podstawie identyfikatora URI pliku, przekaż kontekst aplikacji i identyfikator URI pliku FirebaseVisionImage.fromFilePath() Jest to przydatne, gdy użyj intencji ACTION_GET_CONTENT, aby zachęcić użytkownika do wyboru obraz z aplikacji Galeria.

      Kotlin+KTX

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

      Java

      FirebaseVisionImage image;
      try {
          image = FirebaseVisionImage.fromFilePath(context, uri);
      } catch (IOException e) {
          e.printStackTrace();
      }
    • Aby utworzyć obiekt FirebaseVisionImage na podstawie ByteBuffer lub tablicy bajtów, najpierw oblicz wartość obrazu w sposób opisany powyżej dla danych wejściowych media.Image.

      Następnie utwórz obiekt FirebaseVisionImageMetadata określającą wysokość, szerokość i format kodowania kolorów obrazu i rotacja:

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

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

      Za pomocą bufora lub tablicy oraz obiektu metadanych utwórz FirebaseVisionImage obiekt:

      Kotlin+KTX

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

      Java

      FirebaseVisionImage image = FirebaseVisionImage.fromByteBuffer(buffer, metadata);
      // Or: FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(byteArray, metadata);
    • Aby utworzyć obiekt FirebaseVisionImage na podstawie Obiekt Bitmap:

      Kotlin+KTX

      val image = FirebaseVisionImage.fromBitmap(bitmap)

      Java

      FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
      Obraz reprezentowany przez obiekt Bitmap musi być pionowo bez konieczności dodatkowego obracania.

  2. Pobierz instancję FirebaseVisionTextRecognizer.

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

    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();
    
  3. Na koniec przekaż obraz do metody processImage:

    Kotlin+KTX

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

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

2. Wyodrębnianie tekstu z bloków rozpoznanego tekstu

Jeśli rozpoznawanie tekstu się powiedzie, Do powodzenia zostanie przekazany obiekt FirebaseVisionText słuchacz. Obiekt FirebaseVisionText zawiera pełny tekst rozpoznany w i zero lub więcej obiektów TextBlock.

Każdy element TextBlock to prostokątny blok tekstu, zawierający zero lub więcej obiektów Line. Każdy obiekt Line zawiera 0 lub więcej obiekty Element, które reprezentują słowa i słowa elementów (dat, liczb itp.).

Dla każdego obiektu TextBlock, Line i Element można wyświetlić tekst rozpoznawane w regionie i współrzędne graniczne regionu.

Przykład:

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

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

Dalsze kroki


Rozpoznawanie tekstu na obrazach dokumentów

Aby rozpoznać tekst dokumentu, skonfiguruj i uruchom rozpoznawania tekstu dokumentu, zgodnie z opisem poniżej.

Opisany poniżej interfejs API rozpoznawania tekstu dokumentów zapewnia interfejs, ma ułatwić pracę z obrazami dokumentów. Pamiętaj jednak: jeśli wolisz interfejs dostarczony przez FirebaseVisionTextRecognizer API, możesz go używać do skanowania dokumentów, konfigurując tekst w chmurze modułu rozpoznawania, aby używać modelu gęstego tekstu.

Aby użyć interfejsu API rozpoznawania tekstu dokumentów:

1. Uruchom moduł rozpoznawania tekstu

Aby rozpoznać tekst na obrazie, utwórz obiekt FirebaseVisionImage na podstawie Bitmap, media.Image, ByteBuffer, tablica bajtów lub plik na urządzeniu. Następnie przekaż obiekt FirebaseVisionImage do funkcji Metoda processImage użytkownika FirebaseVisionDocumentTextRecognizer.

  1. Utwórz obiekt FirebaseVisionImage na podstawie swojego obrazu.

    • Aby utworzyć obiekt FirebaseVisionImage na podstawie media.Image, np. podczas przechwytywania obrazu z z aparatu urządzenia, przekazać obiekt media.Image oraz w kierunku FirebaseVisionImage.fromMediaImage().

      Jeśli używasz tagu CameraX, OnImageCapturedListener oraz ImageAnalysis.Analyzer klasy obliczają wartość rotacji więc trzeba tylko przekonwertować rotację na jeden z mechanizmów ML Firebase Stały ROTATION_ przed nawiązaniem połączenia FirebaseVisionImage.fromMediaImage():

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

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

      Jeśli nie korzystasz z biblioteki aparatu zapewniającej obrót obrazu, może go obliczyć na podstawie obrotu urządzenia i orientacji aparatu czujnik w urządzeniu:

      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
      }

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

      Następnie przekaż obiekt media.Image oraz wartość rotacji do FirebaseVisionImage.fromMediaImage():

      Kotlin+KTX

      val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)

      Java

      FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
    • Aby utworzyć obiekt FirebaseVisionImage na podstawie identyfikatora URI pliku, przekaż kontekst aplikacji i identyfikator URI pliku FirebaseVisionImage.fromFilePath() Jest to przydatne, gdy użyj intencji ACTION_GET_CONTENT, aby zachęcić użytkownika do wyboru obraz z aplikacji Galeria.

      Kotlin+KTX

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

      Java

      FirebaseVisionImage image;
      try {
          image = FirebaseVisionImage.fromFilePath(context, uri);
      } catch (IOException e) {
          e.printStackTrace();
      }
    • Aby utworzyć obiekt FirebaseVisionImage na podstawie ByteBuffer lub tablicy bajtów, najpierw oblicz wartość obrazu w sposób opisany powyżej dla danych wejściowych media.Image.

      Następnie utwórz obiekt FirebaseVisionImageMetadata określającą wysokość, szerokość i format kodowania kolorów obrazu i rotacja:

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

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

      Za pomocą bufora lub tablicy oraz obiektu metadanych utwórz FirebaseVisionImage obiekt:

      Kotlin+KTX

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

      Java

      FirebaseVisionImage image = FirebaseVisionImage.fromByteBuffer(buffer, metadata);
      // Or: FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(byteArray, metadata);
    • Aby utworzyć obiekt FirebaseVisionImage na podstawie Obiekt Bitmap:

      Kotlin+KTX

      val image = FirebaseVisionImage.fromBitmap(bitmap)

      Java

      FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
      Obraz reprezentowany przez obiekt Bitmap musi być pionowo bez konieczności dodatkowego obracania.

  2. Pobierz instancję FirebaseVisionDocumentTextRecognizer:

    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)

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

  3. Na koniec przekaż obraz do metody processImage:

    Kotlin+KTX

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

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

2. Wyodrębnianie tekstu z bloków rozpoznanego tekstu

Jeśli rozpoznawanie tekstu się powiedzie, zwróci błąd FirebaseVisionDocumentText. O Obiekt FirebaseVisionDocumentText zawiera pełny tekst rozpoznany w i hierarchię obiektów, które odzwierciedlają strukturę rozpoznawanych dokument:

Dla każdego obiektu Block, Paragraph, Word i Symbol można uzyskać tekstu rozpoznawanego w regionie oraz jego współrzędnych geograficznych.

Przykład:

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

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

Dalsze kroki