Join us in person and online for Firebase Summit on October 18, 2022. Learn how Firebase can help you accelerate app development, release your app with confidence, and scale with ease. Register now

التعرف على النص في الصور بأمان باستخدام Cloud Vision باستخدام مصادقة Firebase والوظائف على أنظمة Apple الأساسية

تنظيم صفحاتك في مجموعات يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.

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

تتمثل إحدى طرق إنشاء واجهة برمجة تطبيقات REST هذه في استخدام مصادقة ووظائف Firebase ، والتي تمنحك بوابة مُدارة بدون خادم إلى Google Cloud APIs التي تتعامل مع المصادقة ويمكن استدعاؤها من تطبيق الجوال الخاص بك باستخدام حزم SDK سابقة الإنشاء.

يوضح هذا الدليل كيفية استخدام هذه التقنية لاستدعاء Cloud Vision API من تطبيقك. ستسمح هذه الطريقة لجميع المستخدمين المعتمدين بالوصول إلى خدمات Cloud Vision التي تتم فوترتها من خلال مشروع Cloud الخاص بك ، لذا ضع في اعتبارك ما إذا كانت آلية المصادقة هذه كافية لحالة الاستخدام الخاصة بك قبل المتابعة.

قبل ان تبدأ

تكوين مشروعك

إذا لم تكن قد أضفت Firebase بالفعل إلى تطبيقك ، فقم بذلك باتباع الخطوات الواردة في دليل البدء .

استخدم Swift Package Manager لتثبيت وإدارة تبعيات Firebase.

  1. في Xcode ، مع فتح مشروع التطبيق الخاص بك ، انتقل إلى ملف> إضافة حزم .
  2. عند المطالبة ، أضف مستودع SDK لأنظمة Apple الأساسية لـ Firebase:
  3.   https://github.com/firebase/firebase-ios-sdk
  4. اختر مكتبة Firebase ML.
  5. عند الانتهاء ، سيبدأ Xcode تلقائيًا في حل وتنزيل التبعيات الخاصة بك في الخلفية.

بعد ذلك ، قم بإجراء بعض الإعداد داخل التطبيق:

  1. في تطبيقك ، استورد Firebase:

    سويفت

    import FirebaseMLModelDownloader

    ج موضوعية

    @import FirebaseMLModelDownloader;

بضع خطوات تكوين أخرى ، ونحن على استعداد للذهاب:

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

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

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

    3. إذا لم تكن واجهات برمجة التطبيقات المستندة إلى السحابة ممكّنة بالفعل ، فانقر فوق تمكين واجهات برمجة التطبيقات المستندة إلى السحابة .
  2. هيئ مفاتيح Firebase API الحالية لعدم السماح بالوصول إلى Cloud Vision API:
    1. افتح صفحة بيانات الاعتماد الخاصة بوحدة التحكم السحابية.
    2. لكل مفتاح API في القائمة ، افتح عرض التحرير ، وفي قسم Key Restrictions ، أضف جميع واجهات برمجة التطبيقات المتاحة باستثناء Cloud Vision API إلى القائمة.

انشر الوظيفة القابلة للاستدعاء

بعد ذلك ، انشر وظيفة السحابة التي ستستخدمها لربط تطبيقك بواجهة Cloud Vision API. يحتوي مستودع functions-samples على مثال يمكنك استخدامه.

بشكل افتراضي ، سيسمح الوصول إلى Cloud Vision API من خلال هذه الوظيفة للمستخدمين المعتمدين فقط من تطبيقك بالوصول إلى Cloud Vision API. يمكنك تعديل الوظيفة لمتطلبات مختلفة.

لنشر الوظيفة:

  1. استنساخ أو تنزيل الريبو الخاص بعينات الوظائف والتغيير إلى دليل Vision vision-annotate-image :
    git clone https://github.com/firebase/functions-samples
    cd vision-annotate-image
    
  2. تثبيت التبعيات:
    cd functions
    npm install
    cd ..
    
  3. إذا لم يكن لديك Firebase CLI ، فثبته .
  4. ابدأ مشروع Firebase في دليل Vision vision-annotate-image . عند المطالبة ، حدد مشروعك من القائمة.
    firebase init
  5. انشر الوظيفة:
    firebase deploy --only functions:annotateImage

أضف Firebase Auth إلى تطبيقك

سترفض الوظيفة القابلة للاستدعاء التي تم نشرها أعلاه أي طلب من المستخدمين غير المصادق عليهم لتطبيقك. إذا لم تكن قد قمت بذلك بالفعل ، فستحتاج إلى إضافة Firebase Auth إلى تطبيقك.

أضف التبعيات الضرورية إلى تطبيقك

استخدم Swift Package Manager لتثبيت وظائف السحابة لمكتبة Firebase.

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

1. تحضير صورة الإدخال

من أجل استدعاء Cloud Vision ، يجب تنسيق الصورة كسلسلة مشفرة base64. لمعالجة صورة UIImage :

سويفت

guard let imageData = uiImage.jpegData(compressionQuality: 1.0f) else { return }
let base64encodedImage = imageData.base64EncodedString()

ج موضوعية

NSData *imageData = UIImageJPEGRepresentation(uiImage, 1.0f);
NSString *base64encodedImage =
  [imageData base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];

2. استدعاء الدالة القابلة للاستدعاء للتعرف على النص

للتعرف على المعالم في صورة ما ، قم باستدعاء الوظيفة القابلة للاستدعاء لتمرير طلب JSON Cloud Vision .

  1. أولاً ، قم بتهيئة مثيل من وظائف السحابة:

    سويفت

    lazy var functions = Functions.functions()
    

    ج موضوعية

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. قم بإنشاء الطلب. تدعم Cloud Vision API نوعين من اكتشاف TEXT_DETECTION و DOCUMENT_TEXT_DETECTION . راجع مستندات Cloud Vision OCR لمعرفة الفرق بين حالتي الاستخدام.

    سويفت

    let requestData = [
      "image": ["content": base64encodedImage],
      "features": ["type": "TEXT_DETECTION"],
      "imageContext": ["languageHints": ["en"]]
    ]
    

    ج موضوعية

    NSDictionary *requestData = @{
      @"image": @{@"content": base64encodedImage},
      @"features": @{@"type": @"TEXT_DETECTION"},
      @"imageContext": @{@"languageHints": @[@"en"]}
    };
    
  3. أخيرًا ، قم باستدعاء الوظيفة:

    سويفت

    functions.httpsCallable("annotateImage").call(requestData) { (result, error) in
      if let error = error as NSError? {
        if error.domain == FunctionsErrorDomain {
          let code = FunctionsErrorCode(rawValue: error.code)
          let message = error.localizedDescription
          let details = error.userInfo[FunctionsErrorDetailsKey]
        }
        // ...
      }
      // Function completed succesfully
    }
    

    ج موضوعية

    [[_functions HTTPSCallableWithName:@"annotateImage"]
                              callWithObject:requestData
                                  completion:^(FIRHTTPSCallableResult * _Nullable result, NSError * _Nullable error) {
            if (error) {
              if (error.domain == FIRFunctionsErrorDomain) {
                FIRFunctionsErrorCode code = error.code;
                NSString *message = error.localizedDescription;
                NSObject *details = error.userInfo[FIRFunctionsErrorDetailsKey];
              }
              // ...
            }
            // Function completed succesfully
            // Get information about labeled objects
    
          }];
    

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

إذا نجحت عملية التعرف على النص ، فسيتم إرجاع استجابة JSON لـ BatchAnnotateImagesResponse في نتيجة المهمة. يمكن العثور على التعليقات التوضيحية النصية في كائن fullTextAnnotation .

يمكنك الحصول على النص الذي تم التعرف عليه كسلسلة في حقل text . فمثلا:

سويفت

guard let annotation = (result?.data as? [String: Any])?["fullTextAnnotation"] as? [String: Any] else { return }
print("%nComplete annotation:")
let text = annotation["text"] as? String ?? ""
print("%n\(text)")

ج موضوعية

NSDictionary *annotation = result.data[@"fullTextAnnotation"];
if (!annotation) { return; }
NSLog(@"\nComplete annotation:");
NSLog(@"\n%@", annotation[@"text"]);

يمكنك أيضًا الحصول على معلومات خاصة بمناطق الصورة. لكل block ، paragraph ، word ، symbol ، يمكنك التعرف على النص في المنطقة والإحداثيات المحيطة بالمنطقة. فمثلا:

سويفت

guard let pages = annotation["pages"] as? [[String: Any]] else { return }
for page in pages {
var pageText = ""
guard let blocks = page["blocks"] as? [[String: Any]] else { continue }
for block in blocks {
    var blockText = ""
    guard let paragraphs = block["paragraphs"] as? [[String: Any]] else { continue }
    for paragraph in paragraphs {
    var paragraphText = ""
    guard let words = paragraph["words"] as? [[String: Any]] else { continue }
    for word in words {
        var wordText = ""
        guard let symbols = word["symbols"] as? [[String: Any]] else { continue }
        for symbol in symbols {
        let text = symbol["text"] as? String ?? ""
        let confidence = symbol["confidence"] as? Float ?? 0.0
        wordText += text
        print("Symbol text: \(text) (confidence: \(confidence)%n")
        }
        let confidence = word["confidence"] as? Float ?? 0.0
        print("Word text: \(wordText) (confidence: \(confidence)%n%n")
        let boundingBox = word["boundingBox"] as? [Float] ?? [0.0, 0.0, 0.0, 0.0]
        print("Word bounding box: \(boundingBox.description)%n")
        paragraphText += wordText
    }
    print("%nParagraph: %n\(paragraphText)%n")
    let boundingBox = paragraph["boundingBox"] as? [Float] ?? [0.0, 0.0, 0.0, 0.0]
    print("Paragraph bounding box: \(boundingBox)%n")
    let confidence = paragraph["confidence"] as? Float ?? 0.0
    print("Paragraph Confidence: \(confidence)%n")
    blockText += paragraphText
    }
    pageText += blockText
}

ج موضوعية

for (NSDictionary *page in annotation[@"pages"]) {
  NSMutableString *pageText = [NSMutableString new];
  for (NSDictionary *block in page[@"blocks"]) {
    NSMutableString *blockText = [NSMutableString new];
    for (NSDictionary *paragraph in block[@"paragraphs"]) {
      NSMutableString *paragraphText = [NSMutableString new];
      for (NSDictionary *word in paragraph[@"words"]) {
        NSMutableString *wordText = [NSMutableString new];
        for (NSDictionary *symbol in word[@"symbols"]) {
          NSString *text = symbol[@"text"];
          [wordText appendString:text];
          NSLog(@"Symbol text: %@ (confidence: %@\n", text, symbol[@"confidence"]);
        }
        NSLog(@"Word text: %@ (confidence: %@\n\n", wordText, word[@"confidence"]);
        NSLog(@"Word bounding box: %@\n", word[@"boundingBox"]);
        [paragraphText appendString:wordText];
      }
      NSLog(@"\nParagraph: \n%@\n", paragraphText);
      NSLog(@"Paragraph bounding box: %@\n", paragraph[@"boundingBox"]);
      NSLog(@"Paragraph Confidence: %@\n", paragraph[@"confidence"]);
      [blockText appendString:paragraphText];
    }
    [pageText appendString:blockText];
  }
}