使用 Apple 平台上的 Firebase 驗證和函式,透過 Cloud Vision 安全地識別地標

如要從應用程式呼叫 Google Cloud API,您必須建立中繼 處理授權並保護密鑰值 (例如 API 金鑰) 的 REST API。接著您需要 在行動應用程式中編寫程式碼,以便驗證這個中繼服務並與其通訊。

建立此 REST API 的其中一種方法是使用 Firebase 驗證和函式。這類閘道會提供一個代管的無伺服器閘道, 處理驗證作業的 Google Cloud API,可透過行動應用程式呼叫。 預先建構的 SDK

本指南示範如何使用這項技術從應用程式呼叫 Cloud Vision API。 這個方法將允許所有通過驗證的使用者透過您的 Cloud 專案存取 Cloud Vision 計費服務。 請先思考這項驗證機制是否足以滿足您的用途需求,再繼續操作。

事前準備

設定專案

如果尚未將 Firebase 加入應用程式,請按照下列步驟操作: 入門指南中的步驟。

使用 Swift Package Manager 安裝及管理 Firebase 依附元件。

  1. 在 Xcode 中保持開啟應用程式專案,然後依序選擇 [檔案] >新增套件
  2. 在系統提示時,新增 Firebase Apple 平台 SDK 存放區:
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. 選擇 Firebase ML 程式庫。
  5. 在目標建構設定的「Other Linker Flags」部分中新增 -ObjC 標記。
  6. 完成後,Xcode 會自動開始解析並下載 複製到背景依附元件

接著,進行一些應用程式內設定:

  1. 在應用程式中匯入 Firebase:

    Swift

    import FirebaseMLModelDownloader

    Objective-C

    @import FirebaseMLModelDownloader;

還差幾個步驟就可以開始使用了:

  1. 如果您尚未為專案啟用雲端式 API,請先啟用 現在:

    1. 開啟 Firebase ML Firebase 控制台的「API」頁面。
    2. 如果您尚未將專案升級至 Blaze 定價方案,請按一下 如要這麼做,請升級。(只有在您的 專案並未採用 Blaze 方案)。

      只有 Blaze 層級的專案可以使用以雲端為基礎的 API。

    3. 如果尚未啟用雲端式 API,請按一下「Enable Cloud-based API」(啟用雲端式 API) API
  2. 設定現有的 Firebase API 金鑰來禁止存取 Cloud Vision API:
    1. 開啟 Cloud 控制台的「Credentials」(憑證) 頁面。
    2. 針對清單中的每個 API 金鑰,開啟編輯檢視畫面,然後 限制專區,請新增所有可用的 API (「Cloud Vision」除外) 新增至清單

部署可呼叫函式

接下來,請部署您將用來連結應用程式和 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 CLI,請安裝
  4. 初始化 vision-annotate-image 中的 Firebase 專案 目錄。系統出現提示時,請在清單中選取您的專案。
    firebase init
  5. 部署函式:
    firebase deploy --only functions:annotateImage

將 Firebase 驗證新增至應用程式

上方部署的可呼叫函式會拒絕所有未經驗證的要求 對於應用程式使用者而言如果尚未新增 Firebase 作業,請先完成這項操作。 向應用程式進行驗證。

為應用程式新增必要的依附元件

使用 Swift Package Manager 安裝 Cloud Functions for 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. 首先,請初始化 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. 取得可辨識的地標相關資訊

如果地標辨識作業成功,系統會傳回 批次註解圖片回應 會在工作的結果中傳回landmarkAnnotations 中的每個物件 陣列代表圖片中可辨識的地標。針對每個地標 您可以在輸入圖像、地標名稱 經緯度、知識圖譜實體 ID (如有),以及 比對的可信度分數例如:

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