Google is committed to advancing racial equity for Black communities. See how.
ترجمت واجهة Cloud Translation API‏ هذه الصفحة.
Switch to English

التعرف على النص في الصور باستخدام Firebase ML على Android

يمكنك استخدام Firebase ML للتعرف على النص في الصور. يحتوي Firebase ML على واجهة برمجة تطبيقات ذات أغراض عامة مناسبة للتعرف على النص في الصور ، مثل نص لافتة الشارع وواجهة برمجة تطبيقات مُحسَّنة للتعرف على نص المستندات.

قبل ان تبدأ

  1. أضف Firebase إلى مشروع Android ، إذا لم تكن قد قمت بذلك بالفعل.
  2. في ملف build.gradle مستوى المشروع ، تأكد من تضمين مستودع Google Maven في كل من buildscript الخاص بك allprojects أقسام allprojects .
  3. أضف مكتبات Firebase ML Android إلى ملف Gradle (على مستوى التطبيق) للوحدة النمطية (عادةً app/build.gradle ):
    apply plugin: 'com.android.application'
    apply plugin: 'com.google.gms.google-services'
    
    dependencies {
      // ...
    
      implementation 'com.google.firebase:firebase-ml-vision:24.1.0'
    }
    
  4. إذا لم تقم بالفعل بتمكين واجهات برمجة التطبيقات المستندة إلى السحابة لمشروعك ، فقم بذلك الآن:

    1. افتح صفحة Firebase ML APIs بوحدة تحكم Firebase.
    2. إذا لم تكن قد قمت بالفعل بترقية مشروعك إلى خطة Blaze ، فانقر فوق ترقية للقيام بذلك. (ستتم مطالبتك بالترقية فقط إذا لم يكن مشروعك مدرجًا في خطة Blaze.)

      يمكن فقط للمشاريع على مستوى Blaze استخدام واجهات برمجة التطبيقات المستندة إلى السحابة.

    3. إذا لم تكن واجهات برمجة التطبيقات المستندة إلى السحابة ممكّنة بالفعل ، فانقر فوق تمكين واجهات برمجة التطبيقات المستندة إلى السحابة .

أنت الآن جاهز لبدء التعرف على النص في الصور.

إرشادات الصورة المدخلة

  • لكي يتعرف Firebase ML على النص بدقة ، يجب أن تحتوي الصور المدخلة على نص يتم تمثيله ببيانات بكسل كافية. من الناحية المثالية ، بالنسبة للنص اللاتيني ، يجب ألا يقل حجم كل حرف عن 16 × 16 بكسل. بالنسبة للنصوص الصينية واليابانية والكورية ، يجب أن يكون حجم كل حرف 24 × 24 بكسل. بالنسبة لجميع اللغات ، لا توجد ميزة دقة بشكل عام عندما تكون الأحرف أكبر من 24 × 24 بكسل.

    لذلك ، على سبيل المثال ، قد تعمل صورة بحجم 640 × 480 جيدًا لمسح بطاقة عمل ضوئيًا تشغل العرض الكامل للصورة. لمسح مستند مطبوع على ورق بحجم letter ، قد تكون هناك حاجة إلى صورة 720 × 1280 بكسل.

  • يمكن أن يؤدي التركيز الضعيف للصورة إلى الإضرار بدقة التعرف على النص. إذا لم تحصل على نتائج مقبولة ، فحاول مطالبة المستخدم بإعادة التقاط الصورة.


التعرف على النص في الصور

للتعرف على نص في صورة ، قم بتشغيل أداة التعرف على النص كما هو موضح أدناه.

1. قم بتشغيل أداة التعرف على النص

إلى التعرف على النص في إحدى الصور، إنشاء FirebaseVisionImage الكائن إما من Bitmap ، media.Image ، ByteBuffer ، صفيف بايت، أو ملف على الجهاز. ثم، لتمرير FirebaseVisionImage الكائن إلى FirebaseVisionTextRecognizer الصورة processImage الأسلوب.

  1. قم بإنشاء كائن FirebaseVisionImage من صورتك.

    • لإنشاء FirebaseVisionImage كائن من media.Image الكائن، مثل عند التقاط صورة من كاميرا جهاز لتمرير media.Image الكائن ودوران الصورة ل FirebaseVisionImage.fromMediaImage() .

      إذا كنت تستخدم CameraX المكتبة، و OnImageCapturedListener و ImageAnalysis.Analyzer الطبقات حساب قيمة التناوب بالنسبة لك، لذلك أنت بحاجة فقط الى تحويل تناوب واحد من Firebase ML في ROTATION_ الثوابت قبل استدعاء FirebaseVisionImage.fromMediaImage() :

      جافا

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

      Kotlin + KTX

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

      إذا كنت لا تستخدم مكتبة الكاميرا التي تمنحك تدوير الصورة ، يمكنك حسابها من دوران الجهاز واتجاه مستشعر الكاميرا في الجهاز:

      جافا

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

      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
      }

      ثم قم بتمرير كائن media.Image وقيمة التدوير إلى FirebaseVisionImage.fromMediaImage() :

      جافا

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

      Kotlin + KTX

      سي 73e506842
    • لإنشاء كائن FirebaseVisionImage من ملف URI ، مرر سياق التطبيق وملف URI إلى FirebaseVisionImage.fromFilePath() . يكون هذا مفيدًا عند استخدام نية ACTION_GET_CONTENT المستخدم بتحديد صورة من تطبيق المعرض الخاص به.

      جافا

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

      Kotlin + KTX

      val image: FirebaseVisionImage
      try {
          image = FirebaseVisionImage.fromFilePath(context, uri)
      } catch (e: IOException) {
          e.printStackTrace()
      }
    • لإنشاء FirebaseVisionImage كائن من ByteBuffer أو مجموعة بايت، أولا حساب دوران الصورة كما هو موضح أعلاه ل media.Image الإدخال.

      بعد ذلك ، قم بإنشاء كائن FirebaseVisionImageMetadata يحتوي على ارتفاع الصورة وعرضها وتنسيق ترميز اللون والدوران:

      جافا

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

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

      استخدم المخزن المؤقت أو المصفوفة وكائن البيانات الوصفية لإنشاء كائن FirebaseVisionImage :

      جافا

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

      Kotlin + KTX

      val image = FirebaseVisionImage.fromByteBuffer(buffer, metadata)
      // Or: val image = FirebaseVisionImage.fromByteArray(byteArray, metadata)
    • لإنشاء كائن FirebaseVisionImage من كائن Bitmap :

      جافا

      FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);

      Kotlin + KTX

      val image = FirebaseVisionImage.fromBitmap(bitmap)
      يجب أن تكون الصورة التي يمثلها كائن Bitmap وضع مستقيم ، دون الحاجة إلى تدوير إضافي.

  2. احصل على مثيل من FirebaseVisionTextRecognizer .

    جافا

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

    Kotlin + KTX

    val detector = FirebaseVision.getInstance().cloudTextRecognizer
    // Or, to change the default settings:
    // val detector = FirebaseVision.getInstance().getCloudTextRecognizer(options)
    // Or, to provide language hints to assist with language detection:
    // See https://cloud.google.com/vision/docs/languages for supported languages
    val options = FirebaseVisionCloudTextRecognizerOptions.Builder()
            .setLanguageHints(listOf("en", "hi"))
            .build()
    
  3. أخيرًا ، مرر الصورة إلى التابع processImage :

    جافا

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

    Kotlin + KTX

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

2. استخراج نص من كتل النص المعترف به

إذا نجحت عملية التعرف على النص ، فسيتم تمرير كائن FirebaseVisionText إلى مستمع النجاح. يحتوي كائن FirebaseVisionText على النص الكامل الذي تم التعرف عليه في الصورة وصفر أو أكثر من كائنات TextBlock .

يمثل كل TextBlock كتلة نص مستطيلة تحتوي على صفر أو أكثر من عناصر Line . يحتوي كل كائن Line على صفر أو أكثر من كائنات Element ، والتي تمثل الكلمات والكيانات الشبيهة بالكلمات (التواريخ والأرقام وما إلى ذلك).

لكل كائن TextBlock و Line و Element ، يمكنك التعرف على النص في المنطقة والإحداثيات المحيطة بالمنطقة.

فمثلا:

جافا

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

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

الخطوات التالية


التعرف على النص في صور المستندات

للتعرف على نص مستند ، قم بتكوين أداة التعرف على نص المستند وتشغيلها كما هو موضح أدناه.

توفر واجهة برمجة تطبيقات التعرف على نص المستند ، الموصوفة أدناه ، واجهة مصممة لتكون أكثر ملاءمة للعمل مع صور المستندات. ومع ذلك ، إذا كنت تفضل الواجهة التي توفرها واجهة برمجة تطبيقات FirebaseVisionTextRecognizer API ، فيمكنك استخدامها بدلاً من ذلك لمسح المستندات ضوئيًا عن طريق تكوين أداة التعرف على النص السحابي لاستخدام نموذج النص الكثيف .

لاستخدام واجهة برمجة تطبيقات التعرف على نص المستند:

1. قم بتشغيل أداة التعرف على النص

إلى التعرف على النص في إحدى الصور، إنشاء FirebaseVisionImage الكائن إما من Bitmap ، media.Image ، ByteBuffer ، صفيف بايت، أو ملف على الجهاز. ثم، لتمرير FirebaseVisionImage الكائن إلى FirebaseVisionDocumentTextRecognizer الصورة processImage الأسلوب.

  1. قم بإنشاء كائن FirebaseVisionImage من صورتك.

    • لإنشاء FirebaseVisionImage كائن من media.Image الكائن، مثل عند التقاط صورة من كاميرا جهاز لتمرير media.Image الكائن ودوران الصورة ل FirebaseVisionImage.fromMediaImage() .

      إذا كنت تستخدم CameraX المكتبة، و OnImageCapturedListener و ImageAnalysis.Analyzer الطبقات حساب قيمة التناوب بالنسبة لك، لذلك أنت بحاجة فقط الى تحويل تناوب واحد من Firebase ML في ROTATION_ الثوابت قبل استدعاء FirebaseVisionImage.fromMediaImage() :

      جافا

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

      Kotlin + KTX

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

      إذا كنت لا تستخدم مكتبة الكاميرا التي تمنحك تدوير الصورة ، يمكنك حسابها من دوران الجهاز واتجاه مستشعر الكاميرا في الجهاز:

      جافا

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

      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
      }

      ثم قم بتمرير كائن media.Image وقيمة التدوير إلى FirebaseVisionImage.fromMediaImage() :

      جافا

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

      Kotlin + KTX

      val image = FirebaseVisionImage.fromMediaImage(mediaImage, rotation)
    • لإنشاء كائن FirebaseVisionImage من ملف URI ، مرر سياق التطبيق وملف URI إلى FirebaseVisionImage.fromFilePath() . يكون هذا مفيدًا عند استخدام نية ACTION_GET_CONTENT المستخدم بتحديد صورة من تطبيق المعرض الخاص به.

      جافا

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

      Kotlin + KTX

      val image: FirebaseVisionImage
      try {
          image = FirebaseVisionImage.fromFilePath(context, uri)
      } catch (e: IOException) {
          e.printStackTrace()
      }
    • لإنشاء FirebaseVisionImage كائن من ByteBuffer أو مجموعة بايت، أولا حساب دوران الصورة كما هو موضح أعلاه ل media.Image الإدخال.

      بعد ذلك ، قم بإنشاء كائن FirebaseVisionImageMetadata يحتوي على ارتفاع الصورة وعرضها وتنسيق ترميز اللون والدوران:

      جافا

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

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

      استخدم المخزن المؤقت أو المصفوفة وكائن البيانات الوصفية لإنشاء كائن FirebaseVisionImage :

      جافا

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

      Kotlin + KTX

      val image = FirebaseVisionImage.fromByteBuffer(buffer, metadata)
      // Or: val image = FirebaseVisionImage.fromByteArray(byteArray, metadata)
    • لإنشاء كائن FirebaseVisionImage من كائن Bitmap :

      جافا

      FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);

      Kotlin + KTX

      val image = FirebaseVisionImage.fromBitmap(bitmap)
      يجب أن تكون الصورة التي يمثلها كائن Bitmap وضع مستقيم ، دون الحاجة إلى تدوير إضافي.

  2. احصل على نسخة من FirebaseVisionDocumentTextRecognizer :

    جافا

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

    Kotlin + KTX

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

  3. أخيرًا ، مرر الصورة إلى التابع processImage :

    جافا

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

    Kotlin + KTX

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

2. استخراج نص من كتل النص الذي تم التعرف عليه

إذا نجحت عملية التعرف على النص ، FirebaseVisionDocumentText كائن FirebaseVisionDocumentText . يحتوي كائن FirebaseVisionDocumentText على النص الكامل الذي تم التعرف عليه في الصورة وتسلسل هرمي للكائنات التي تعكس بنية المستند الذي تم التعرف عليه:

لكل كائن Block و Paragraph و Word و Symbol ، يمكنك التعرف على النص في المنطقة والإحداثيات المحيطة بالمنطقة.

فمثلا:

جافا

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

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

الخطوات التالية