تشخیص امن نقاط دیدنی با Cloud Vision بااستفاده از «احراز هویت Firebase» و «توابع» در پلاتفرم‌های Apple

برای فراخوانی Google Cloud API از برنامه‌تان، باید یک میانای برنامه‌سازی کاربردی میانجی REST ایجاد کنید که مجوزدهی را مدیریت کند و از مقادیر محرمانه مثل کلیدهای API محافظت کند. سپس باید در برنامه تلفن همراهتان کد بنویسید تا با این سرویس واسطه ارتباط برقرار کنید و هویتتان را در آن به‌تأیید برسانید.

یکی از روش‌های ایجاد این REST API استفاده از «احراز هویت Firebase» و «توابع» است که درگاهی بدون سرور و مدیریت‌شده به Google Cloud APIs ارائه می‌دهد که احراز هویت را مدیریت می‌کند و می‌تواند از برنامه تلفن همراه شما با کیت‌های توسعه نرم‌افزار ازپیش ساخته‌شده فراخوانی شود.

این راهنما نشان می‌دهد که چگونه از این تکنیک برای فراخوانی Cloud Vision API از برنامه‌تان استفاده کنید. این روش به همه کاربران اصالت‌سنجی‌شده اجازه می‌دهد ازطریق پروژه Cloud شما به سرویس‌های صورت‌حساب‌دار Cloud Vision دسترسی داشته باشند، بنابراین قبل‌از ادامه دادن، درنظر بگیرید که آیا این سازوکار اصالت‌سنجی برای مورد استفاده شما کافی است یا نه.

قبل از شروع

پیکربندی پروژه

اگر هنوز Firebase را به برنامه‌تان اضافه نکرده‌اید، با دنبال کردن مراحل راهنمای شروع به کار این کار را انجام دهید.

از «مدیر بسته Swift» برای نصب و مدیریت وابستگی‌های Firebase استفاده کنید.

  1. در Xcode، با باز بودن پروژه برنامه، به File > Add Packages (فایل > افزودن بسته‌ها) پیمایش کنید.
  2. وقتی درخواست شد، مخزن کیت توسعه نرم‌افزار پلاتفرم‌های Firebase Apple را اضافه کنید:
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. کتابخانه Firebase ML را انتخاب کنید.
  5. پرچم -ObjC را به بخش پرچم‌های پیونددهنده دیگر در تنظیمات ساخت هدف اضافه کنید.
  6. پس‌از اتمام، Xcode به‌طور خودکار شروع به حل و بارگیری وابستگی‌های شما در پس‌زمینه می‌کند.

سپس، برخی‌از راه‌اندازی‌های درون‌برنامه‌ای را انجام دهید:

  1. در برنامه‌تان، Firebase را وارد کنید:

    Swift

    import FirebaseMLModelDownloader

    Objective-C

    @import FirebaseMLModelDownloader;

چند مرحله دیگر برای پیکربندی باقی مانده است و آماده‌ایم:

  1. اگر قبلاً «میاناهای برنامه‌سازی کاربردی ابری» را برای پروژه‌تان فعال نکرده‌اید، اکنون این کار را انجام دهید:

    1. صفحه Firebase ML APIs را در کنسول Firebase باز کنید.
    2. اگر هنوز پروژه‌تان را به طرح قیمت‌گذاری Blaze با پرداخت براساس مصرف ارتقا نداده‌اید، روی ارتقا کلیک کنید تا این کار را انجام دهید. (فقط درصورتی از شما خواسته می‌شود پروژه‌تان را ارتقا دهید که در طرح قیمت‌گذاری Blaze نباشد.)

      فقط پروژه‌های طرح قیمت‌گذاری Blaze می‌توانند از میاناهای برنامه‌سازی کاربردی مبتنی بر ابر استفاده کنند.

    3. اگر «میاناهای برنامه‌سازی کاربردی مبتنی بر Cloud» ازقبل فعال نشده است، روی فعال کردن میاناهای برنامه‌سازی کاربردی مبتنی بر Cloud کلیک کنید.
  2. کلیدهای Firebase API موجود را پیکربندی کنید تا دسترسی به Cloud Vision API را غیرمجاز کنید:
    1. صفحه اطلاعات اعتباری کنسول Cloud را باز کنید.
    2. برای هر کلید API در فهرست، نمای ویرایش را باز کنید و در بخش «محدودیت‌های کلید»، همه APIهای دردسترس به‌جز Cloud Vision API را به فهرست اضافه کنید.

استقرار تابع فراخوان‌شدنی

سپس، Cloud Function را که برای ایجاد پل بین برنامه و Cloud Vision API استفاده می‌کنید مستقر کنید. مخزن functions-samples حاوی نمونه‌ای است که می‌توانید از آن استفاده کنید.

به‌طور پیش‌فرض، دسترسی به Cloud Vision API ازطریق این تابع فقط به کاربران اصیل‌سازی‌شده برنامه شما اجازه می‌دهد به Cloud Vision API دسترسی داشته باشند. می‌توانید عملکرد را برای الزامات مختلف تغییر دهید.

برای استقرار تابع:

  1. مخزن functions-samples را شبیه‌سازی یا بارگیری کنید و به دایرکتوری 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» برای نصب کتابخانه «توابع ابری ویژه Firebase» استفاده کنید.

۱. آماده کردن تصویر ورودی

برای فراخوانی 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];

۲. برای تشخیص نشانگرهای مکانی، تابع فراخوان‌شدنی را فراخوانی کنید

برای تشخیص نشان‌های جغرافیایی در تصویر، تابع فراخوان‌شدنی را با ارسال درخواست JSON Cloud Vision فراخوانی کنید.

  1. ابتدا نمونه‌ای از Cloud Functions را مقداردهی اولیه کنید:

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

۳. درباره نشانگرهای مکانی تشخیص‌داده‌شده اطلاعات دریافت کنید

اگر عملیات تشخیص مکان دیدنی موفقیت‌آمیز باشد، پاسخ 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"];
  }
}