在iOS上使用ML Kit识别地标

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

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

在您开始之前

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

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

    1. pod 'Firebase/Core'
    2. pod 'Firebase/MLVision'

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

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

    Swift:

    1. import Firebase

    Objective-C:

    1. @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:

  1. let options = VisionCloudDetectorOptions()
  2. options.modelType = .latest
  3. options.maxResults = 20

Objective-C:

  1. FIRVisionCloudDetectorOptions *options =
  2. [[FIRVisionCloudDetectorOptions alloc] init];
  3. options.modelType = FIRVisionCloudModelTypeLatest;
  4. options.maxResults = 20;

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

运行地标识别器

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

  1. 得到一个VisionCloudLandmarkDetector实例:

    Swift:

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

    Objective-C:

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

    使用UIImage

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

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

      Swift:

      1. let image = VisionImage(image: uiImage)

      Objective-C:

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

    使用CMSampleBufferRef

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

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

      Swift:

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

      Objective-C:

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

      Swift:

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

      Objective-C:

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

    Swift:

    1. landmarkDetector.detect(in: visionImage) { (landmarks, error) in
    2. guard error == nil, let landmarks = landmarks, !landmarks.isEmpty else {
    3. // ...
    4. return
    5. }
    6. // 识别地标
    7. // ...
    8. }

    Objective-C:

    1. [landmarkDetector detectInImage:image
    2. completion:^(NSArray<FIRVisionCloudLandmark *> *landmarks,
    3. NSError *error) {
    4. if (error != nil) {
    5. return;
    6. } else if (landmarks != nil) {
    7. // 得到地标
    8. }
    9. }];

获取著名地标的有关信息

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

例如:

Swift:

  1. for landmark in landmarks {
  2. let landmarkDesc = landmark.landmark
  3. let boundingPoly = landmark.frame
  4. let entityId = landmark.entityId
  5. // 一个地标可以有多个定位,例如图片中的地址还有就是所描绘地标的位置。
  6. for location in landmark.locations {
  7. let latitude = location.latitude
  8. let longitude = location.longitude
  9. }
  10. let confidence = landmark.confidence
  11. }

Objective-C:

  1. for (FIRVisionCloudLandmark *landmark in landmarks) {
  2. NSString *landmarkDesc = landmark.landmark;
  3. CGRect frame = landmark.frame;
  4. NSString *entityId = landmark.entityId;
  5. // 一个地标可以有多个定位,例如图片中的地址还有就是所描绘地标的位置。
  6. for (FIRVisionLatitudeLongitude *location in landmark.locations) {
  7. double latitude = [location.latitude doubleValue];
  8. double longitude = [location.longitude doubleValue];
  9. }
  10. float confidence = [landmark.confidence floatValue];
  11. }