当前位置: 首页 > 文档资料 > ML Kit 中文文档 >

在 iOS 上使用 ML Kit 识别地标

优质
小牛编辑
122浏览
2023-12-01

您可以使用ML kit来识别图片中的著名地标。

有关此API使用的示例,请参阅GitHub上的ML Kit快速入门示例。

在您开始之前

  1. 如果您还没有将Firebase添加到您的程序当中,那您可以从开始指南来开始您的工作。

  2. 将ML kit库放进您的Podfile中:

    pod 'Firebase/Core'
    pod 'Firebase/MLVision'
    

​ 而后每次您要安装或者升级您的Pods的时候,请确保使用您的Xcode项目的.xcworkspace来打开它。

  1. 在您的程序中,引入Firebase:

    Swift:

    import Firebase
    

    Objective-C:

    @import Firebase;
    
  2. 如果您想使用基于云的模型,并且尚未将项目升级到Blaze计划,请在Firebase控制台中执行此操作。只有Blaze计划的项目才能使用Cloud Vision API。

  3. 如果您想使用基于云的模型,您也需要开启Cloud Vision API:

    • 在云API列表管理平台中打开Cloud Vision API
    • 确保您的Firebase项目已经在当前菜单页面中被置于顶端。
    • 如果API依旧还是显示为enabled,请点击Enable。

配置地标识别器

默认情况下,云识别器使用STABLE版本的模型并返回多达10个结果。如果您想要更改这些设置中的任何一个,请使用下例中的VisionCloudDetectorOptions对象指定它们:

Swift:

let options = VisionCloudDetectorOptions()
options.modelType = .latest
options.maxResults = 20

Objective-C:

  FIRVisionCloudDetectorOptions *options =
      [[FIRVisionCloudDetectorOptions alloc] init];
  options.modelType = FIRVisionCloudModelTypeLatest;
  options.maxResults = 20;

在下一步中,创建Cloud识别器对象时传递该VisionCloudDetectorOptions对象。

运行地标识别器

为了能够识别图像中的地标,将图像传递为UIImage或者CMSampleBufferRefVisionCloudLandmarkDetectordetect(in:)方法:

  1. 得到一个VisionCloudLandmarkDetector实例:

    Swift:

    lazy var vision = Vision.vision()
    let landmarkDetector = vision.cloudLandmarkDetector(options: options)
    // 或者使用默认设定:
    // let landmarkDetector = vision?.cloudLandmarkDetector()
    

    Objective-C:

    FIRVision *vision = [FIRVision vision];
    FIRVisionCloudLandmarkDetector *landmarkDetector = [vision cloudLandmarkDetector];
    // 或者使用默认设定:
    // FIRVisionCloudLandmarkDetector *landmarkDetector =
    //     [vision cloudLandmarkDetectorWithOptions:options];
    
  2. 使用UIImage或者CMSampleBufferRef创建一个VisionImage对象:

    使用UIImage

    1. 如有必要,旋转图像以使其imageOrientation 属性为.up

    2. VisionImage使用正确旋转的对象创建一个对象 UIImage。不要指定任何旋转元数据 - 默认值.topLeft,必须使用。

      Swift:

      let image = VisionImage(image: uiImage)
      

      Objective-C:

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
      

    使用CMSampleBufferRef

    1. 创建一个VisionImageMetadata对象,该对象指定包含在CMSampleBufferRef缓冲区中的图像数据的方向 。

      例如,如果图像数据必须顺时针旋转90度才能保持直立:

      Swift:

      let metadata = VisionImageMetadata()
      metadata.orientation = .rightTop  // Row为0在右边,column为0则是在顶端
      

      Objective-C:

      // Row为0在右边,column为0则是在顶端
      FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
      metadata.orientation = FIRVisionDetectorImageOrientationRightTop;
      
    2. VisionImage使用CMSampleBufferRef对象和旋转元数据创建一个对象 :

      Swift:

      let image = VisionImage(buffer: bufferRef)
      image.metadata = metadata
      

      Objective-C:

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:buffer];
      image.metadata = metadata;
      
  3. 然后,将图像传递给该detect(in:)方法:

    Swift:

    landmarkDetector.detect(in: visionImage) { (landmarks, error) in
      guard error == nil, let landmarks = landmarks, !landmarks.isEmpty else {
        // ...
        return
      }
    
      // 识别地标
      // ...
    }
    

    Objective-C:

    [landmarkDetector detectInImage:image
                         completion:^(NSArray<FIRVisionCloudLandmark *> *landmarks,
                                      NSError *error) {
      if (error != nil) {
        return;
      } else if (landmarks != nil) {
        // 得到地标
      }
    }];
    

获取著名地标的有关信息

如果地标识别成功,则会将一个VisionCloudLandmark 对象数组传递给完成处理程序。从每个对象中,您可以获取在图像中识别的地标的信息。

例如:

Swift:

for landmark in landmarks {
  let landmarkDesc = landmark.landmark
  let boundingPoly = landmark.frame
  let entityId = landmark.entityId

  // 一个地标可以有多个定位,例如图片中的地址还有就是所描绘地标的位置。
  for location in landmark.locations {
    let latitude = location.latitude
    let longitude = location.longitude
  }

  let confidence = landmark.confidence
}

Objective-C:

for (FIRVisionCloudLandmark *landmark in landmarks) {
   NSString *landmarkDesc = landmark.landmark;
   CGRect frame = landmark.frame;
   NSString *entityId = landmark.entityId;

  // 一个地标可以有多个定位,例如图片中的地址还有就是所描绘地标的位置。
   for (FIRVisionLatitudeLongitude *location in landmark.locations) {
     double latitude = [location.latitude doubleValue];
     double longitude = [location.longitude doubleValue];
   }

   float confidence = [landmark.confidence floatValue];
}