Catch up on everthing we announced at this year's Firebase Summit. Learn more

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

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

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

    سويفت

    import Firebase

    ج موضوعية

    @import Firebase;

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

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

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

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

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

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

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

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

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

  1. استنساخ أو تنزيل ظائف عينات الريبو وتغيير في 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-annotate-image الدليل. عند المطالبة ، حدد مشروعك من القائمة.
    firebase init
  5. نشر وظيفة:
    firebase deploy --only functions:annotateImage

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

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

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

استخدم 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 سحابة الرؤية .

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

    سويفت

    lazy var functions = Functions.functions()
    

    ج موضوعية

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. قم بإنشاء الطلب. وAPI سحابة الرؤية يدعم اثنان أنواع من كشف النص: TEXT_DETECTION و DOCUMENT_TEXT_DETECTION . رؤية سحابة الرؤية 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];
  }
}