Rozpoznawaj tekst w obrazach za pomocą Firebase ML na Androidzie

Możesz użyć Firebase ML do rozpoznawania tekstu na obrazach. Firebase ML ma zarówno interfejs API ogólnego przeznaczenia, odpowiedni do rozpoznawania tekstu na obrazach, na przykład tekstu znaku ulicznego, jak i interfejs API zoptymalizowany pod kątem rozpoznawania tekstu dokumentów.

Zanim zaczniesz

  1. Jeśli jeszcze tego nie zrobiłeś, dodaj Firebase do swojego projektu na Androida .
  2. W pliku Gradle modułu (na poziomie aplikacji) (zwykle <project>/<app-module>/build.gradle.kts lub <project>/<app-module>/build.gradle ) dodaj zależność dla Firebase ML Biblioteka Vision na Androida. Zalecamy używanie Firebase Android BoM do kontrolowania wersji bibliotek.
    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
    
        // 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 Firebase Android BoM , Twoja aplikacja będzie zawsze korzystać ze zgodnych wersji bibliotek Firebase Android.

    (Alternatywnie) Dodaj zależności biblioteki Firebase bez korzystania z BoM

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

    Pamiętaj, że jeśli używasz w swojej aplikacji wielu bibliotek Firebase, zdecydowanie zalecamy korzystanie z BoM do zarządzania wersjami bibliotek, co zapewnia zgodność wszystkich wersji.

    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'
    }
    
  3. Jeśli jeszcze nie włączyłeś interfejsów API opartych na chmurze dla swojego projektu, zrób to teraz:

    1. Otwórz stronę Firebase ML APIs w konsoli Firebase.
    2. Jeśli jeszcze nie zaktualizowałeś swojego projektu do planu cenowego Blaze, kliknij Uaktualnij , aby to zrobić. (Zostaniesz poproszony o uaktualnienie tylko wtedy, gdy Twój projekt nie jest objęty planem Blaze).

      Tylko projekty na poziomie Blaze mogą korzystać z interfejsów API opartych na chmurze.

    3. Jeśli interfejsy API oparte na chmurze nie są jeszcze włączone, kliknij opcję Włącz interfejsy API oparte na chmurze .

Teraz możesz rozpocząć rozpoznawanie tekstu na obrazach.

Wprowadź wskazówki dotyczące obrazu

  • Aby Firebase ML dokładnie rozpoznawał tekst, obrazy wejściowe muszą zawierać tekst reprezentowany przez wystarczającą ilość danych w pikselach. Idealnie, dla tekstu łacińskiego, każdy znak powinien mieć co najmniej 16x16 pikseli. W przypadku tekstu chińskiego, japońskiego i koreańskiego każdy znak powinien mieć rozmiar 24 x 24 piksele. W przypadku wszystkich języków generalnie nie ma żadnych korzyści w zakresie dokładności, jeśli znaki są większe niż 24 x 24 piksele.

    Na przykład obraz o rozdzielczości 640 x 480 może dobrze nadawać się do zeskanowania wizytówki, która zajmuje całą szerokość obrazu. Aby zeskanować dokument wydrukowany na papierze formatu Letter, może być wymagany obraz o rozdzielczości 720 x 1280 pikseli.

  • Słaba ostrość obrazu może zaszkodzić dokładności rozpoznawania tekstu. Jeśli nie otrzymujesz akceptowalnych wyników, spróbuj poprosić użytkownika o ponowne przechwycenie obrazu.


Rozpoznawanie tekstu na obrazach

Aby rozpoznać tekst na obrazie, uruchom narzędzie do rozpoznawania tekstu w sposób opisany poniżej.

1. Uruchom rozpoznawanie tekstu

Aby rozpoznać tekst na obrazie, utwórz obiekt FirebaseVisionImage na podstawie Bitmap , media.Image , ByteBuffer , tablicy bajtów lub pliku na urządzeniu. Następnie przekaż obiekt FirebaseVisionImage do metody processImage obiektu FirebaseVisionTextRecognizer .

  1. Utwórz obiekt FirebaseVisionImage ze swojego obrazu.

    • Aby utworzyć obiekt FirebaseVisionImage z obiektu media.Image , na przykład podczas przechwytywania obrazu z kamery urządzenia, należy przekazać obiekt media.Image i obrót obrazu do FirebaseVisionImage.fromMediaImage() .

      Jeśli korzystasz z biblioteki CameraX , klasy OnImageCapturedListener i ImageAnalysis.Analyzer obliczają wartość obrotu, więc wystarczy przekonwertować obrót na jedną ze stałych ROTATION_ Firebase ML przed wywołaniem 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 kamer, która zapewnia obrót obrazu, możesz obliczyć go na podstawie obrotu urządzenia i orientacji czujnika kamery 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 i wartość obrotu 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 do FirebaseVisionImage.fromFilePath() . Jest to przydatne, gdy używasz intencji ACTION_GET_CONTENT , aby poprosić użytkownika o wybranie obrazu z jego aplikacji galerii.

      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 z ByteBuffer lub tablicy bajtów, najpierw oblicz obrót obrazu, jak opisano powyżej dla danych wejściowych media.Image .

      Następnie utwórz obiekt FirebaseVisionImageMetadata , który zawiera wysokość, szerokość, format kodowania kolorów i obrót obrazu:

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

      Użyj bufora lub tablicy oraz obiektu metadanych, aby utworzyć obiekt FirebaseVisionImage :

      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 z obiektu Bitmap :

      Kotlin+KTX

      val image = FirebaseVisionImage.fromBitmap(bitmap)

      Java

      FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
      Obraz reprezentowany przez obiekt Bitmap musi być ustawiony 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ębnij tekst z bloków rozpoznanego tekstu

Jeśli operacja rozpoznawania tekstu powiedzie się, obiekt FirebaseVisionText zostanie przekazany do detektora sukcesu. Obiekt FirebaseVisionText zawiera pełny tekst rozpoznany na obrazie i zero lub więcej obiektów TextBlock .

Każdy TextBlock reprezentuje prostokątny blok tekstu, który zawiera zero lub więcej obiektów Line . Każdy obiekt Line zawiera zero lub więcej obiektów Element , które reprezentują słowa i obiekty słowopodobne (daty, liczby itd.).

Dla każdego obiektu TextBlock , Line i Element można rozpoznać tekst w regionie i współrzędne ograniczające region.

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

Następne kroki


Rozpoznawanie tekstu na obrazach dokumentów

Aby rozpoznać tekst dokumentu, skonfiguruj i uruchom narzędzie do rozpoznawania tekstu dokumentu zgodnie z poniższym opisem.

Opisany poniżej interfejs API rozpoznawania tekstu dokumentu zapewnia interfejs, który ma być wygodniejszy w pracy z obrazami dokumentów. Jeśli jednak wolisz interfejs udostępniany przez interfejs API FirebaseVisionTextRecognizer , możesz go użyć do skanowania dokumentów, konfigurując aparat rozpoznawania tekstu w chmurze do korzystania z modelu gęstego tekstu .

Aby użyć interfejsu API rozpoznawania tekstu dokumentu:

1. Uruchom rozpoznawanie tekstu

Aby rozpoznać tekst na obrazie, utwórz obiekt FirebaseVisionImage na podstawie Bitmap , media.Image , ByteBuffer , tablicy bajtów lub pliku na urządzeniu. Następnie przekaż obiekt FirebaseVisionImage do metody processImage FirebaseVisionDocumentTextRecognizer .

  1. Utwórz obiekt FirebaseVisionImage ze swojego obrazu.

    • Aby utworzyć obiekt FirebaseVisionImage z obiektu media.Image , na przykład podczas przechwytywania obrazu z kamery urządzenia, należy przekazać obiekt media.Image i obrót obrazu do FirebaseVisionImage.fromMediaImage() .

      Jeśli korzystasz z biblioteki CameraX , klasy OnImageCapturedListener i ImageAnalysis.Analyzer obliczają wartość obrotu, więc wystarczy przekonwertować obrót na jedną ze stałych ROTATION_ Firebase ML przed wywołaniem 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 kamer, która zapewnia obrót obrazu, możesz obliczyć go na podstawie obrotu urządzenia i orientacji czujnika kamery 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 i wartość obrotu 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 do FirebaseVisionImage.fromFilePath() . Jest to przydatne, gdy używasz intencji ACTION_GET_CONTENT , aby poprosić użytkownika o wybranie obrazu z jego aplikacji galerii.

      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 z ByteBuffer lub tablicy bajtów, najpierw oblicz obrót obrazu, jak opisano powyżej dla danych wejściowych media.Image .

      Następnie utwórz obiekt FirebaseVisionImageMetadata , który zawiera wysokość, szerokość, format kodowania kolorów i obrót obrazu:

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

      Użyj bufora lub tablicy oraz obiektu metadanych, aby utworzyć obiekt FirebaseVisionImage :

      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 z obiektu Bitmap :

      Kotlin+KTX

      val image = FirebaseVisionImage.fromBitmap(bitmap)

      Java

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

  2. Uzyskaj 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ębnij tekst z bloków rozpoznanego tekstu

Jeśli operacja rozpoznawania tekstu powiedzie się, zwróci obiekt FirebaseVisionDocumentText . Obiekt FirebaseVisionDocumentText zawiera pełny tekst rozpoznany na obrazie oraz hierarchię obiektów odzwierciedlającą strukturę rozpoznanego dokumentu:

Dla każdego obiektu Block , Paragraph , Word i Symbol można rozpoznać tekst w regionie i współrzędne ograniczające region.

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

Następne kroki