获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

在 Apple 平台上使用 Firebase Auth 和 Functions 通过 Cloud Vision 安全地识别地标

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

为了从您的应用程序调用 Google Cloud API,您需要创建一个中间 REST API 来处理授权并保护 API 密钥等秘密值。然后,您需要在您的移动应用程序中编写代码来验证此中间服务并与之通信。

创建此 REST API 的一种方法是使用 Firebase 身份验证和函数,它为您提供了一个托管的、无服务器的 Google Cloud API 网关,该网关处理身份验证,并且可以使用预构建的 SDK 从您的移动应用程序中调用。

本指南演示如何使用此技术从您的应用调用 Cloud Vision API。此方法将允许所有经过身份验证的用户通过您的 Cloud 项目访问 Cloud Vision 计费服务,因此请在继续之前考虑此身份验证机制是否足以满足您的用例。

在你开始之前

配置您的项目

如果您尚未将 Firebase 添加到您的应用,请按照入门指南中的步骤进行操作。

使用 Swift Package Manager 安装和管理 Firebase 依赖项。

  1. 在 Xcode 中,打开您的应用项目,导航到File > Add Packages
  2. 出现提示时,添加 Firebase Apple 平台 SDK 存储库:
  3.   https://github.com/firebase/firebase-ios-sdk
  4. 选择 Firebase ML 库。
  5. 完成后,Xcode 将在后台自动开始解析和下载您的依赖项。

接下来,执行一些应用内设置:

  1. 在您的应用中,导入 Firebase:

    迅速

    import FirebaseMLModelDownloader

    Objective-C

    @import FirebaseMLModelDownloader;

再进行一些配置步骤,我们就可以开始了:

  1. 如果您尚未为您的项目启用基于云的 API,请立即执行此操作:

    1. 打开 Firebase 控制台的Firebase ML API 页面
    2. 如果您尚未将项目升级到 Blaze 定价计划,请单击升级以执行此操作。 (仅当您的项目不在 Blaze 计划中时,系统才会提示您升级。)

      只有 Blaze 级项目可以使用基于云的 API。

    3. 如果尚未启用基于云的 API,请单击启用基于云的 API
  2. 配置您现有的 Firebase API 密钥以禁止访问 Cloud Vision API:
    1. 打开云控制台的凭据页面。
    2. 对于列表中的每个 API 密钥,打开编辑视图,然后在密钥限制部分中,将Cloud Vision API 之外的所有可用 API 添加到列表中。

部署可调用函数

接下来,部署您将用于桥接您的应用程序和 Cloud Vision API 的 Cloud Functions 函数。 functions-samples存储库包含一个您可以使用的示例。

默认情况下,通过此函数访问 Cloud Vision API 将只允许您应用的经过身份验证的用户访问 Cloud Vision API。您可以根据不同的要求修改功能。

部署功能:

  1. 克隆或下载functions-samples repo并更改到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. vision-annotate-image目录中初始化一个 Firebase 项目。出现提示时,在列表中选择您的项目。
    firebase init
  5. 部署函数:
    firebase deploy --only functions:annotateImage

将 Firebase 身份验证添加到您的应用

上面部署的可调用函数将拒绝来自您应用程序的未经身份验证的用户的任何请求。如果您尚未这样做,则需要将 Firebase Auth 添加到您的应用中。

为您的应用添加必要的依赖项

使用 Swift Package Manager 安装 Cloud Functions for Firebase 库。

1.准备输入图像

为了调用 Cloud Vision,图像必须格式化为 base64 编码的字符串。处理UIImage

迅速

guard let imageData = uiImage.jpegData(compressionQuality: 1.0f) 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 实例:

    迅速

    lazy var functions = Functions.functions()
    

    Objective-C

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. 创建一个类型设置为LANDMARK_DETECTION的请求:

    迅速

    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. 最后,调用函数:

    迅速

    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
    }
    

    Objective-C

    [[_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. 获取有关已识别地标的信息

如果地标识别操作成功,任务结果中会返回一个BatchAnnotateImagesResponse的 JSON 响应。 landmarkAnnotations数组中的每个对象都表示在图像中识别的一个地标。对于每个地标,您可以获得其在输入图像中的边界坐标、地标的名称、其纬度和经度、其知识图实体 ID(如果可用)以及匹配的置信度分数。例如:

迅速

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