זיהוי של ציוני דרך באופן מאובטח באמצעות Cloud Vision באמצעות אימות ופונקציות של Firebase בפלטפורמות של Apple

כדי לשלוח קריאה ל-Google Cloud API מהאפליקציה, צריך ליצור אמצעי ביניים API ל-REST שמטפל בהרשאות ומגן על ערכים סודיים, כמו מפתחות API. לאחר מכן צריך לכתוב קוד באפליקציה לנייד כדי לבצע אימות של השירות המתווך הזה ולתקשר איתו.

אחת מהדרכים ליצור את ה-API ל-REST הוא באמצעות אימות ופונקציות ב-Firebase, שמאפשרים גישה מנוהלת ללא שרת (serverless) אל ממשקי Google Cloud API שמטפלים באימות ואפשר לקרוא להם מהאפליקציה לנייד באמצעות וערכות SDK מוכנות מראש.

במדריך הזה נסביר איך להשתמש בשיטה הזו כדי לבצע קריאה ל-Cloud Vision API מהאפליקציה. השיטה הזו תאפשר לכל המשתמשים המאומתים לגשת לשירותים של Cloud Vision שמוגדרים לחיוב דרך הפרויקט שלכם ב-Cloud. לכן, לפני שממשיכים, כדאי לבדוק אם מנגנון האימות הזה מספיק לתרחיש לדוגמה שלכם.

לפני שמתחילים

הגדרת הפרויקט

אם עדיין לא הוספתם את Firebase לאפליקציה, צריך לבצע את הפעולות הבאות במדריך לתחילת העבודה.

שימוש ב-Swift Package Manager כדי להתקין ולנהל יחסי תלות של Firebase.

  1. ב-Xcode, כשפרויקט האפליקציה פתוח, עוברים אל File > (קובץ >) הוספת חבילות.
  2. כשמופיעה בקשה, מוסיפים את מאגר ה-SDK של מוצרי הפלטפורמה של Firebase של Apple:
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. בוחרים את הספרייה Firebase ML.
  5. מוסיפים את הדגל -ObjC לקטע Other Linker Flags (דגלים אחרים של קישור) בהגדרות ה-build של היעד.
  6. בסיום, Xcode יתחיל לפתור את הבעיה ותוריד את של יחסי התלות ברקע.

עכשיו מבצעים הגדרה בתוך האפליקציה:

  1. באפליקציה, מייבאים את Firebase:

    Swift

    import FirebaseMLModelDownloader

    Objective-C

    @import FirebaseMLModelDownloader;

עוד כמה שלבי הגדרה, ואנחנו מוכנים:

  1. אם עדיין לא הפעלתם ממשקי API מבוססי-Cloud בפרויקט, עליכם לעשות זאת עכשיו:

    1. פותחים את Firebase ML דף ממשקי ה-API במסוף Firebase.
    2. אם עדיין לא שדרגתם את הפרויקט לתוכנית התמחור Blaze, לוחצים על שדרוג כדי לעשות זאת. (הבקשה לשדרוג תוצג רק אם הפרויקט לא נמצא בתוכנית Blaze).

      רק בפרויקטים ברמת Blaze אפשר להשתמש בממשקי API מבוססי-ענן.

    3. אם ממשקי ה-API מבוססי-הענן עדיין לא מופעלים, לוחצים על Enable Cloud-based APIs.
  2. להגדיר את מפתחות ה-API הקיימים של Firebase כדי למנוע גישה לענן Vision API:
    1. פותחים את הדף Credentials במסוף Cloud.
    2. עבור כל מפתח API ברשימה, פותחים את תצוגת העריכה ובקטע 'מפתח' בקטע 'הגבלות', מוסיפים את כל ממשקי ה-API הזמינים מלבד Cloud Vision API אל הרשימה.

פריסת הפונקציה שניתנת לקריאה

בשלב הבא, פורסים את הפונקציה של Cloud Functions שתשמש לגשר בין האפליקציה לבין 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. אם ה-CLI של Firebase לא מותקן, מתקינים אותו.
  4. מפעילים פרויקט Firebase ב-vision-annotate-image כשמופיעה בקשה, בוחרים את הפרויקט מהרשימה.
    firebase init
  5. פורסים את הפונקציה:
    firebase deploy --only functions:annotateImage

הוספת אימות מ-Firebase לאפליקציה

הפונקציה הניתנת לקריאה שפרוסה למעלה תדחה כל בקשה ממשתמשים לא מאומתים באפליקציה. אם עדיין לא עשיתם זאת, תצטרכו להוסיף את Firebase Auth לאפליקציה.

צריך להוסיף את יחסי התלות הנדרשים לאפליקציה

כדי להתקין את הספרייה Cloud Functions for Firebase, משתמשים ב-Swift Package Manager.

1. הכנת תמונת הקלט

כדי לקרוא ל-Cloud Vision, התמונה צריכה להיות בפורמט של קידוד base64 String. כדי לעבד 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. קודם כול, מאתחלים מכונה של Cloud Functions:

    Swift

    lazy var functions = Functions.functions()
    

    Objective-C

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. יוצרים בקשה כשהשדה Type מוגדר ל-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 מייצג ציון דרך שזוהה בתמונה. לכל ציון דרך, תוכלו לקבל את קואורדינטות המסגרת שלו בתמונה הקלט, את השם שלו, את קווי הרוחב והאורך שלו, את מזהה הישות שלו ב-Knowledge Graph (אם הוא זמין) ואת דירוג האמון של ההתאמה. לדוגמה:

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