ImageTracking_CloudRecognition

演示如何使用云识别功能。

  • 演示如何创建和使用本地缓存

  • 演示如何在跟踪时停止网络请求

运行前配置

使用云识别需配置服务器访问信息,这些信息可以在EasyAR官网的开发中心中 云识别管理页面 中获得。在Unity中输入这些信息有两种方法:

一种是全局配置, EasyAR 配置 Image Tracking > Cloud Recognition (CRS) > Service Access [Global]

另一种是在场景中配置,它只对当前场景有效。

用法

../../_images/image_21.png
标记1:显示系统状态和操作提示。
标记2:结束/开始云识别。
标记3:清空当前云识别的Targets和缓存。

详解

触发云识别

从EasyAR Sense 4.1开始,所有 CloudRecognizer 的请求都由用户代码触发,SDK内部将不再触发从服务器发送和接收数据的调用。也就是说你可以自由控制请求的频次。

cloudRecognizer.Resolve(requestTimeout, (result) => {});

最低请求间隔限制为300ms。

周期性地触发云识别

private void Update()
{
    AutoResolve();
}

在这个sample中,如果target在被跟踪或是前一次的resolve未完成或时间间隔未到达预设值(1s)的时候,resolve不会被调用。

private void AutoResolve(OutputFrame oframe, Matrix4x4 displayCompensation)
{
    var time = Time.realtimeSinceStartup;
    if (!resolveOn || isTracking || resolveInfo.Running || time - resolveInfo.ResolveTime < resolveInterval) { return; }

    resolveInfo.Running = true;
    resolveInfo.ResolveTime = time;
    ...
}

云识别结果

云识别是EasyAR的独立功能,可以在不与图像跟踪一起使用。如果在识别之后不需要跟踪,直接使用resolve结果即可。

cloudRecognizer.Resolve(requestTimeout, (result) =>
{
    ...
    resolveInfo.CloudStatus = result.Status;
    ...
    var target = result.Target;
    ...
});

跟踪云返回的target

如果需要跟踪服务器识别到的图像,就需要用到result中的target信息。

在这个sample中target被clone了一份,因为它会在ImageTargetController中被引用,因此需要保留一份内部object的引用。

cloudRecognizer.Resolve(requestTimeout, (result) =>
{
    ...
    var target = result.Target;
    if (target.OnSome)
    {
        var targetValue = target.Value;

        if (!loadedCloudTargetUids.Contains(targetValue.uid()))
        {
            LoadCloudTarget(targetValue.Clone());
        }
    }
});

创建一个有 ImageTargetControllerGameObject ,并将resolve回调中的 ImageTarget 赋给 ImageTargetController.Source ,这样controller可以使用 ImageTargetController.DataSource.Target 来初始化。

private void LoadCloudTarget(ImageTarget target)
{
    ...
    var go = new GameObject(uid);
    targetObjs.Add(go);
    var targetController = go.AddComponent<ImageTargetController>();
    targetController.TargetDataLoad += (_) => target.Dispose();
    targetController.Source = new ImageTargetController.TargetSourceData
    {
        Target = target
    };
    LoadTargetIntoTracker(targetController);
}

没有必要多次加载同一个target,并且这样做也会失败。

if (!loadedCloudTargetUids.Contains(targetValue.uid()))
{
    LoadCloudTarget(targetValue.Clone());
}

使用离线缓存

一个好的实践是,将识别到的target保持在文件存储中,以便在下次启动时加载。这会对下次应用启动时的识别有好处,可以减少响应时间,而且可以在离线状态下使用识别过的target。

可以使用 ImageTarget.save 将target保存为 .etd 文件。

target.save(OfflineCachePath + "/" + target.uid() + ".etd")

然后可以在下次运行时通过 ImageTargetController.DataSource.TargetDataFile 类型的数据使用 .etd 文件创建target。

private void LoadOfflineTarget(string file)
{
    var go = new GameObject(Path.GetFileNameWithoutExtension(file) + "-offline");
    targetObjs.Add(go);
    var targetController = go.AddComponent<ImageTargetController>();
    targetController.Source = new ImageTargetController.TargetDataFileSourceData
    {
        PathType = PathType.Absolute,
        Path = file,
    };
    LoadTargetIntoTracker(targetController);
}