تشخیص متن در تصاویر با Firebase ML در اندروید

You can use Firebase ML to recognize text in images. Firebase ML هم یک API همه منظوره مناسب برای تشخیص متن در تصاویر، مانند متن تابلوهای خیابان دارد و هم یک API بهینه شده برای تشخیص متن اسناد.

قبل از شروع

  1. اگر قبلاً این کار را نکرده‌اید، Firebase را به پروژه Android خود اضافه کنید .
  2. در فایل Gradle ماژول (سطح برنامه) خود (معمولا <project>/<app-module>/build.gradle.kts یا <project>/<app-module>/build.gradle )، وابستگی را برای کتابخانه Firebase ML Vision برای Android اضافه کنید. توصیه می‌کنیم از Firebase Android BoM برای کنترل نسخه‌سازی کتابخانه استفاده کنید.
    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:34.3.0"))
    
        // 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'
    }

    با استفاده از Firebase Android BoM ، برنامه شما همیشه از نسخه‌های سازگار کتابخانه‌های Firebase Android استفاده می‌کند.

    (جایگزین) وابستگی های کتابخانه Firebase را بدون استفاده از BoM اضافه کنید

    اگر تصمیم گرفتید از Firebase BoM استفاده نکنید، باید هر نسخه کتابخانه Firebase را در خط وابستگی آن مشخص کنید.

    توجه داشته باشید که اگر از چندین کتابخانه Firebase در برنامه خود استفاده می کنید، ما قویاً توصیه می کنیم از BoM برای مدیریت نسخه های کتابخانه استفاده کنید، که تضمین می کند همه نسخه ها سازگار هستند.

    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. If you haven't already enabled Cloud-based APIs for your project, do so now:

    1. Open the Firebase ML APIs page in the Firebase console.
    2. If you haven't already upgraded your project to the pay-as-you-go Blaze pricing plan , click Upgrade to do so. (You'll be prompted to upgrade only if your project isn't on the Blaze pricing plan.)

      Only projects on the Blaze pricing plan can use Cloud-based APIs.

    3. If Cloud-based APIs aren't already enabled, click Enable Cloud-based APIs .

Now you are ready to start recognizing text in images.

دستورالعمل های تصویر ورودی

  • For Firebase ML to accurately recognize text, input images must contain text that is represented by sufficient pixel data. در حالت ایده آل، برای متن لاتین، هر کاراکتر باید حداقل 16x16 پیکسل باشد. برای متن چینی، ژاپنی و کره ای، هر کاراکتر باید ۲۴×۲۴ پیکسل باشد. برای همه زبان ها، معمولاً هیچ مزیتی برای دقت بزرگتر از 24x24 پیکسل وجود ندارد.

    بنابراین، برای مثال، یک تصویر 640x480 ممکن است برای اسکن کارت ویزیتی که تمام عرض تصویر را اشغال می کند، به خوبی کار کند. برای اسکن یک سند چاپ شده روی کاغذ با اندازه حرف، ممکن است به یک تصویر 720x1280 پیکسل نیاز باشد.

  • Poor image focus can hurt text recognition accuracy. If you aren't getting acceptable results, try asking the user to recapture the image.


تشخیص متن در تصاویر

برای تشخیص متن در یک تصویر، شناسه متن را مطابق زیر اجرا کنید.

1. شناسه متن را اجرا کنید

برای تشخیص متن در یک تصویر، یک شی FirebaseVisionImage از Bitmap ، media.Image ، ByteBuffer ، آرایه بایت یا یک فایل روی دستگاه ایجاد کنید. سپس، شی FirebaseVisionImage را به متد processImage FirebaseVisionTextRecognizer ارسال کنید.

  1. Create a FirebaseVisionImage object from your image.

    • برای ایجاد یک شی FirebaseVisionImage از یک شی media.Image ، مانند هنگام گرفتن تصویر از دوربین دستگاه، شی media.Image .Image و چرخش تصویر را به FirebaseVisionImage.fromMediaImage() منتقل کنید.

      اگر از کتابخانه CameraX استفاده می‌کنید، کلاس‌های OnImageCapturedListener و ImageAnalysis.Analyzer مقدار چرخش را برای شما محاسبه می‌کنند، بنابراین فقط باید قبل از فراخوانی FirebaseVisionImage.fromMediaImage() چرخش را به یکی از ثابت‌های ROTATION_ Firebase ML تبدیل کنید:

      Kotlin

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

      اگر از کتابخانه دوربینی که چرخش تصویر را به شما می دهد استفاده نمی کنید، می توانید آن را از روی چرخش دستگاه و جهت سنسور دوربین در دستگاه محاسبه کنید:

      Kotlin

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

      سپس، شی media.Image و مقدار چرخش را به FirebaseVisionImage.fromMediaImage() ارسال کنید:

      Kotlin

      val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)

      Java

      FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
    • برای ایجاد یک شی FirebaseVisionImage از URI فایل، زمینه برنامه و فایل URI را به FirebaseVisionImage.fromFilePath() ارسال کنید. This is useful when you use an ACTION_GET_CONTENT intent to prompt the user to select an image from their gallery app.

      Kotlin

      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();
      }
    • برای ایجاد یک شی FirebaseVisionImage از یک ByteBuffer یا یک آرایه بایت، ابتدا چرخش تصویر را همانطور که در بالا برای ورودی media.Image توضیح داده شد محاسبه کنید.

      سپس، یک شی FirebaseVisionImageMetadata ایجاد کنید که شامل ارتفاع، عرض، فرمت کدگذاری رنگ و چرخش تصویر باشد:

      Kotlin

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

      برای ایجاد یک شی FirebaseVisionImage از بافر یا آرایه و شیء فراداده استفاده کنید:

      Kotlin

      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);
    • To create a FirebaseVisionImage object from a Bitmap object:

      Kotlin

      val image = FirebaseVisionImage.fromBitmap(bitmap)

      Java

      FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
      The image represented by the Bitmap object must be upright, with no additional rotation required.

  2. Get an instance of FirebaseVisionTextRecognizer .

    Kotlin

    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. در نهایت تصویر را به متد processImage منتقل کنید:

    Kotlin

    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. متن را از بلوک های متن شناخته شده استخراج کنید

If the text recognition operation succeeds, a FirebaseVisionText object will be passed to the success listener. یک شی FirebaseVisionText حاوی متن کامل شناسایی شده در تصویر و صفر یا چند شی TextBlock است.

هر TextBlock یک بلوک مستطیل شکل از متن را نشان می دهد که شامل صفر یا چند شی Line است. Each Line object contains zero or more Element objects, which represent words and word-like entities (dates, numbers, and so on).

برای هر شیء TextBlock ، Line و Element ، می توانید متن را در ناحیه و مختصات مرزی منطقه تشخیص دهید.

به عنوان مثال:

Kotlin

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

مراحل بعدی


تشخیص متن در تصاویر اسناد

برای تشخیص متن یک سند، شناساگر متن سند را پیکربندی و اجرا کنید که در زیر توضیح داده شده است.

API تشخیص متن سند، که در زیر توضیح داده شده است، رابطی را ارائه می دهد که برای کار با تصاویر اسناد راحت تر است. با این حال، اگر رابط ارائه شده توسط FirebaseVisionTextRecognizer API را ترجیح می دهید، می توانید به جای آن از آن برای اسکن اسناد با پیکربندی تشخیص دهنده متن ابری برای استفاده از مدل متن متراکم استفاده کنید.

برای استفاده از API تشخیص متن سند:

1. شناسه متن را اجرا کنید

برای تشخیص متن در یک تصویر، یک شی FirebaseVisionImage از Bitmap ، media.Image ، ByteBuffer ، آرایه بایت یا یک فایل روی دستگاه ایجاد کنید. Then, pass the FirebaseVisionImage object to the FirebaseVisionDocumentTextRecognizer 's processImage method.

  1. یک شی FirebaseVisionImage از تصویر خود ایجاد کنید.

    • برای ایجاد یک شی FirebaseVisionImage از یک شی media.Image ، مانند هنگام گرفتن تصویر از دوربین دستگاه، شی media.Image .Image و چرخش تصویر را به FirebaseVisionImage.fromMediaImage() منتقل کنید.

      اگر از کتابخانه CameraX استفاده می‌کنید، کلاس‌های OnImageCapturedListener و ImageAnalysis.Analyzer مقدار چرخش را برای شما محاسبه می‌کنند، بنابراین فقط باید قبل از فراخوانی FirebaseVisionImage.fromMediaImage() چرخش را به یکی از ثابت‌های ROTATION_ Firebase ML تبدیل کنید:

      Kotlin

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

      اگر از کتابخانه دوربینی که چرخش تصویر را به شما می دهد استفاده نمی کنید، می توانید آن را از روی چرخش دستگاه و جهت سنسور دوربین در دستگاه محاسبه کنید:

      Kotlin

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

      Then, pass the media.Image object and the rotation value to FirebaseVisionImage.fromMediaImage() :

      Kotlin

      val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)

      Java

      FirebaseVisionImage image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation);
    • برای ایجاد یک شی FirebaseVisionImage از URI فایل، زمینه برنامه و فایل URI را به FirebaseVisionImage.fromFilePath() ارسال کنید. This is useful when you use an ACTION_GET_CONTENT intent to prompt the user to select an image from their gallery app.

      Kotlin

      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();
      }
    • برای ایجاد یک شی FirebaseVisionImage از یک ByteBuffer یا یک آرایه بایت، ابتدا چرخش تصویر را همانطور که در بالا برای ورودی media.Image توضیح داده شد محاسبه کنید.

      سپس، یک شی FirebaseVisionImageMetadata ایجاد کنید که شامل ارتفاع، عرض، فرمت کدگذاری رنگ و چرخش تصویر باشد:

      Kotlin

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

      برای ایجاد یک شی FirebaseVisionImage از بافر یا آرایه و شیء فراداده استفاده کنید:

      Kotlin

      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);
    • To create a FirebaseVisionImage object from a Bitmap object:

      Kotlin

      val image = FirebaseVisionImage.fromBitmap(bitmap)

      Java

      FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);
      تصویر نمایش داده شده توسط شی Bitmap باید عمودی باشد، بدون نیاز به چرخش اضافی.

  2. Get an instance of FirebaseVisionDocumentTextRecognizer :

    Kotlin

    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. Finally, pass the image to the processImage method:

    Kotlin

    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. متن را از بلوک های متن شناخته شده استخراج کنید

اگر عملیات تشخیص متن موفقیت آمیز باشد، یک شی FirebaseVisionDocumentText را برمی گرداند. یک شی FirebaseVisionDocumentText حاوی متن کامل شناسایی شده در تصویر و سلسله مراتبی از اشیاء است که ساختار سند شناسایی شده را منعکس می کند:

برای هر شئ Block ، Paragraph ، Word و Symbol ، می توانید متن را در منطقه و مختصات مرزی منطقه تشخیص دهید.

به عنوان مثال:

Kotlin

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

مراحل بعدی