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

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

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

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

قبل البدء

ضبط مشروعك

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

يمكنك استخدام "مدير حزم Swift" لتثبيت اعتماديات Firebase وإدارتها.

  1. في Xcode، بعد فتح مشروع تطبيقك، انتقِل إلى File > Add Packages (ملف > إضافة حِزم).
  2. أضِف مستودع حزمة تطوير البرامج (SDK) لمنصّات Firebase Apple عندما يُطلب منك ذلك:
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. اختَر مكتبة تعلُّم الآلة في Firebase.
  5. أضِف العلامة -ObjC إلى القسم علامات الروابط الأخرى في إعدادات إصدار هدفك.
  6. عند الانتهاء، ستبدأ خدمة Xcode تلقائيًا في حلّ المشاكل المتعلّقة بالعناصر التي تعتمد عليها وتنزيلها في الخلفية.

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

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

    Swift

    import FirebaseMLModelDownloader

    Objective-C

    @import FirebaseMLModelDownloader;

في ما يلي بعض خطوات الضبط الإضافية، ونحن جاهزون لبدء الاستخدام:

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

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

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

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

نشر الدالة القابلة للاستدعاء

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

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

لنشر الدالة:

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

إضافة مصادقة Firebase إلى تطبيقك

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

أضف التبعيات اللازمة إلى تطبيقك

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

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

لطلب البيانات من Cloud Vision، يجب تنسيق الصورة كسلسلة بترميز base64. لمعالجة UIImage:

Swift

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

Objective-C

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

2- استدعاء الدالة القابلة للاستدعاء للتعرّف على المعالم

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

  1. أولاً، عليك إعداد مثيل من دوال السحابة:

    Swift

    lazy var functions = Functions.functions()
    

    Objective-C

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. إنشاء طلب مع ضبط النوع على LANDMARK_DETECTION:

    Swift

    let requestData = [
      "image": ["content": base64encodedImage],
      "features": ["maxResults": 5, "type": "LANDMARK_DETECTION"]
    ]
    

    Objective-C

    NSDictionary *requestData = @{
      @"image": @{@"content": base64encodedImage},
      @"features": @{@"maxResults": @5, @"type": @"LANDMARK_DETECTION"}
    };
    
  3. أخيرًا، استدعِ الدالة:

    Swift

    do {
      let result = try await functions.httpsCallable("annotateImage").call(requestData)
      print(result)
    } catch {
      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]
        }
        // ...
      }
    }
    

    Objective-C

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

3- الحصول على معلومات عن المعالم المعروفة

إذا نجحت عملية التعرّف على المعالم، سيتم عرض استجابة JSON للرمز BatchAnnotateImagesResponse في نتيجة المهمة. يمثل كل كائن في مصفوفة landmarkAnnotations مَعلمًا تم التعرّف عليه في الصورة. يمكنك الحصول على إحداثيات المحيط لكل معلَم في الصورة المدخلة واسم المَعلم وخط العرض وخط الطول ورقم تعريف جهة الرسم البياني المعرفي (إن توفّر) ونتيجة الثقة للمطابقة. على سبيل المثال:

Swift

if let labelArray = (result?.data as? [String: Any])?["landmarkAnnotations"] as? [[String:Any]] {
  for labelObj in labelArray {
    let landmarkName = labelObj["description"]
    let entityId = labelObj["mid"]
    let score = labelObj["score"]
    let bounds = labelObj["boundingPoly"]
    // Multiple locations are possible, e.g., the location of the depicted
    // landmark and the location the picture was taken.
    guard let locations = labelObj["locations"] as? [[String: [String: Any]]] else { continue }
    for location in locations {
      let latitude = location["latLng"]?["latitude"]
      let longitude = location["latLng"]?["longitude"]
    }
  }
}

Objective-C

NSArray *labelArray = result.data[@"landmarkAnnotations"];
for (NSDictionary *labelObj in labelArray) {
  NSString *landmarkName = labelObj[@"description"];
  NSString *entityId = labelObj[@"mid"];
  NSNumber *score = labelObj[@"score"];
  NSArray *bounds = labelObj[@"boundingPoly"];
  // Multiple locations are possible, e.g., the location of the depicted
  // landmark and the location the picture was taken.
  NSArray *locations = labelObj[@"locations"];
  for (NSDictionary *location in locations) {
    NSNumber *latitude = location[@"latLng"][@"latitude"];
    NSNumber *longitude = location[@"latLng"][@"longitude"];
  }
}