转到控制台

在 Android 上使用机器学习套件识别地标

您可以使用机器学习套件识别图片中的知名地标。

准备工作

  1. 设置一个 Firebase 项目:
    1. 如果您还没有 Firebase 项目,请在 Firebase 控制台中创建一个。如果您已经有与自己的移动应用相关联的现有 Google 项目,请点击导入 Google 项目。如果没有,请点击添加项目
    2. 点击将 Firebase 添加到您的 Android 应用,然后按设置步骤操作。如果您是导入现有 Google 项目,系统可能会自动执行这些操作,您只需下载配置文件即可。
    3. 出现提示时,输入应用的软件包名称。请务必输入应用在使用的软件包名称;只有在将应用添加到 Firebase 项目时您才能进行此设置。
    4. 最后,您要下载一个 google-services.json 文件。您可以随时重新下载配置文件
    5. 如果尚未将此文件复制到项目的模块文件夹(通常是 app/),请执行此操作。
  2. 将您从自己的 EAP 联系人那里接收到的 SDK 解压缩:
    unzip -d $SDK_DIR 3p_sdk.m2repo.zip
    
  3. 将 SDK 和 Google 服务插件解压缩到的目录添加到您的项目级 build.gradle
    buildscript {
      // ...
      dependencies {
          // ...
          classpath 'com.google.gms:google-services:3.2.0' // google-services plugin
      }
    }
    
    allprojects {
      repositories {
        // Add this
        maven {
          url "$SDK_DIR"
        }
        // This should already be here
        jcenter()
    
        ...
      }
    }
    
  4. 然后,添加机器学习套件的依赖项,并将 apply plugin 行添加到您的应用级 build.gradle 文件:

    dependencies {
      // ...
      compile 'com.google.firebase:firebase-core:12.8.0-SNAPSHOT'
      compile 'com.google.firebase:firebase-ml-vision:12.8.0-SNAPSHOT'
    }
    
    // ADD THIS AT THE BOTTOM OF THE FILE
    apply plugin: 'com.google.gms.google-services'
    

配置地标检测器

默认情况下,Cloud 检测器使用模型的 STABLE 版本并最多返回 10 个结果。如果您想更改这两个设置中的任何一个,请使用 FirebaseVisionCloudDetectorOptions 对象进行指定。

例如,要将两项默认设置全部更改,请按照以下示例构建一个 FirebaseVisionCloudDetectorOptions 对象:

FirebaseVisionCloudDetectorOptions options =
    new FirebaseVisionCloudDetectorOptions.Builder()
        .setModelType(FirebaseVisionCloudDetectorOptions.LATEST_MODEL)
        .setMaxResults(15)
        .build();

要使用默认设置,可以在下一步中使用 FirebaseVisionCloudDetectorOptions.DEFAULT

运行地标检测器

要识别图片中的地标,请将图片作为 ByteBuffer 对象传递给 FirebaseVisionCloudLandmarkDetectordetectInBuffer 方法,或将图片作为 android.graphics.Bitmap 对象传递给 detectInImage 方法。

  1. 获取 FirebaseVisionCloudLandmarkDetector 的一个实例:

    FirebaseVisionCloudLandmarkDetector detector = FirebaseVision.getInstance()
        .getVisionCloudLandmarkDetector(options);
    
  2. 创建一个包含图片元数据的 FirebaseVisionImageMetadata 对象。

    如果要将图片作为 ByteBuffer 传递,则必须指定图片的高度、宽度、颜色编码格式和显示方向:

    FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
        .setWidth(1280)
        .setHeight(720)
        .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
        .setRotation(FirebaseVisionImageMetadata.ROTATION_0)
        .build();
    

    如果要将图片作为 Bitmap 传递,则只需指定图片的显示方向:

    FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
        .setRotation(FirebaseVisionImageMetadata.ROTATION_0)
        .build();
    
  3. 最后,将图片传递给 detectInBufferdetectInImage 方法:

    Task<SparseArray<FirebaseVisionCloudLandmark>> result =
        detector.detectInImage(image, metadata)  // or detectInBuffer(buffer, metadata)
        .addOnSuccessListener(
            this,
            new OnSuccessListener<SparseArray<FirebaseVisionCloudLandmark>>() {
              @Override
              public void onSuccess(SparseArray<FirebaseVisionCloudLandmark> landmarks) {
                // Task completed successfully
                // ...
              }
            })
        .addOnFailureListener(
            this,
            new OnFailureListener() {
              @Override
              public void onFailure(@NonNull Exception e) {
                // Task failed with an exception
                // ...
              }
            });
    

获取识别出的地标的相关信息

如果地标识别操作成功,则系统会向成功侦听器传递一组 FirebaseVisionCloudLandmark 对象。每个 FirebaseVisionCloudLandmark 对象代表一个在图片中识别出的地标。对于每个地标,您可以获取它在输入图片中的边界坐标、地标名称、地标的纬度和经度、地标的知识图谱实体 ID(如果有)以及匹配的置信度分数。例如:

for(int i = 0; i < landmarks.size(); i++) {
  FirebaseVisionCloudLandmark landmark = landmarks.valueAt(i);

  Rect bounds = landmark.getBoundingBox();
  String landmarkName = landmark.getlandmark();
  String entityId = landmark.getEntityId();
  float confidence = landmark.getScore();

  // Multiple locations are possible, e.g., the location of the depicted
  // landmark and the location the picture was taken.
  for (FirebaseVisionLatLng loc: landmark.getLocations()) {
    double latitude = loc.getLatitude();
    double longitude = loc.getLongitude();
  }
}