惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tor Project blog
B
Blog RSS Feed
M
MIT News - Artificial intelligence
WordPress大学
WordPress大学
H
Hackread – Cybersecurity News, Data Breaches, AI and More
罗磊的独立博客
GbyAI
GbyAI
N
Netflix TechBlog - Medium
博客园 - 司徒正美
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
宝玉的分享
宝玉的分享
W
WeLiveSecurity
Stack Overflow Blog
Stack Overflow Blog
Y
Y Combinator Blog
SecWiki News
SecWiki News
V
Vulnerabilities – Threatpost
Google DeepMind News
Google DeepMind News
C
CERT Recently Published Vulnerability Notes
T
Tailwind CSS Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Register - Security
The Register - Security
Cisco Talos Blog
Cisco Talos Blog
Martin Fowler
Martin Fowler
A
About on SuperTechFans
S
Security @ Cisco Blogs
T
Tenable Blog
C
Check Point Blog
N
News and Events Feed by Topic
S
SegmentFault 最新的问题
The GitHub Blog
The GitHub Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Attack and Defense Labs
Attack and Defense Labs
美团技术团队
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
Cisco Blogs
P
Palo Alto Networks Blog
V
V2EX
博客园 - 聂微东
Project Zero
Project Zero
酷 壳 – CoolShell
酷 壳 – CoolShell
D
Docker
N
News | PayPal Newsroom
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
小众软件
小众软件
Application and Cybersecurity Blog
Application and Cybersecurity Blog
人人都是产品经理
人人都是产品经理
V2EX - 技术
V2EX - 技术
I
Intezer
L
LINUX DO - 最新话题

元视角

.NET 生态下的 Agent 框架选型:从 ReAct 到原生推理 - 元视角 从「能用」到「好用」:LLM 流式响应实现方式的探索之路 - 元视角 当我用 2000 条聊天记录,让 AI 为我画一幅自画像 - 元视角 基于 Supabase 的 AI 应用开发探索 - 元视角 微博 × MCP:社交媒体新玩法解锁 - 元视角 四点钟海棠花未眠 - 元视角 Semantic Kernel × MCP:智能体的上下文增强探索 - 元视角 基于 K-Means 聚类分析实现人脸照片的快速分类 - 元视角 容器技术驱动下的代码沙箱实践与思考 - 元视角 温故而知新:后端通用查询方案的再思考 - 元视角 浅议 CancellationToken 在前后端协同取消场景中的应用 - 元视角 Semantic Kernel 视角下的 Text2SQL 实践与思考 - 元视角 关于 ChatGPT 的流式传输,你需要知道的一切 - 元视角 RAG 的是与非、Rewrite 和 Rerank - 元视角 使用 EFCore 和 PostgreSQL 实现向量存储及检索 - 元视角 基于 LLaMA 和 LangChain 实践本地 AI 知识库 - 元视角 使用 llama.cpp 在本地部署 AI 大模型的一次尝试 - 元视角 如何为 Git 配置多个 SSH Key - 元视角 C# 使用 LibUsbDotNet 实现 USB 设备检测 - 元视角 基于 C# 实现样式与数据分离的打印方案 - 元视角 基于 SVG 的图形交互方案实践 - 元视角 前端视频播放技术概览 - 元视角 温故而知新,再话 Python 动态导入 - 元视角 后 GPT 时代,NLP 不存在了? - 元视角 视频是不能 P 的系列:使用 Milvus 实现海量人脸快速检索 - 元视角 GDI+下字体大小自适应方案初探 - 元视角 小爱音箱集成 ChatGPT 的不完全教程 - 元视角 程序员视角下的三体世界随想 - 元视角 关于 Docker 容器配置信息的渐进式思考 - 元视角 在 Docker 容器内集成 Crontab 定时任务 - 元视角 为你的服务器集成 LDAP 认证 - 元视角 似花还似非花 - 元视角 视频是不能 P 的系列:使用 Dlib 实现人脸识别 - 元视角 浅议分布式链路追踪与日志的整合 - 元视角 关于 Git 大文件上传这件小事 - 元视角 .NET 进程内队列 Channel 的入门与应用 - 元视角 使用 Fody 实现 .NET 的静态编织 - 元视角 .NET Core + ELK 搭建可视化日志分析平台(下) - 元视角 聊一聊前端图片懒加载背后的故事 - 元视角 支持外部链接跳转的 Vue Router 扩展实现 - 元视角 视频是不能 P 的系列:OpenCV 和 Dlib 实现表情包 - 元视角 不得不说的 ASP.NET Core 集成测试 - 元视角 再议 DDD 视角下的 EFCore 与 领域事件 - 元视角 Vue.js 前端项目容器化部署实践极简教程 - 元视角 再见,人间四月天 - 元视角 Python 图像风格化迁移助力画家梦想 - 元视角 利用 ASP.NET Core 中的标头传播实现分布式链路追踪 - 元视角 利用 gRPC 实现文件的上传与下载 - 元视角 七种武器:延迟队列的原理和实现总结 - 元视角 gRPC 流式传输极简入门指南 - 元视角 Envoy 集成 Jaeger 实现分布式链路追踪 - 元视角 浅议非典型 Web 应用场景下的身份认证 - 元视角 gRPC 借助 Any 类型实现接口的泛化调用 - 元视角 分布式丛林探险系列之 Redis 集群模式 - 元视角 分布式丛林探险系列之 Redis 主从复制模式 - 元视角 通过 Python 预测 2021 年双十一交易额 - 元视角 gRPC 搭配 Swagger 实现微服务文档化 - 元视角 SSL/TLS 加密传输与数字证书的前世今生 - 元视角 使用 Python 自动识别防疫健康码 - 元视角 你不可不知的容器编排进阶技巧 - 元视角 ASP.NET Core 搭载 Envoy 实现 gRPC 服务代理 - 元视角 再话 AOP,从简化缓存操作说起 - 元视角 ASP.NET Core 搭载 Envoy 实现微服务身份认证(JWT) - 元视角 ASP.NET Core 搭载 Envoy 实现微服务的监控预警 - 元视角 ASP.NET Core 搭载 Envoy 实现微服务的反向代理 - 元视角 ASP.NET Core gRPC 打通前端世界的尝试 - 元视角 EFCore 实体命名约定库:EFCore.NamingConventions - 元视角 ASP.NET Core gRPC 集成 Polly 实现优雅重试 - 元视角 ASP.NET Core gRPC 健康检查的探索与实现 - 元视角 ASP.NET Core gRPC 拦截器的使用技巧分享 - 元视角 SnowNLP 使用自定义语料进行模型训练 - 元视角 使用 HttpMessageHandler 实现 HttpClient 请求管道自定义 - 元视角 ABP vNext 的实体与服务扩展技巧分享 - 元视角 ABP vNext 对接 Ant Design Vue 实现分页查询 - 元视角 源代码探案系列之 .NET Core 跨域中间件 CORS - 元视角 源代码探案系列之 .NET Core 限流中间件 AspNetCoreRateLimit - 元视角 源代码探案系列之 .NET Core 并发限制中间件 ConcurrencyLimiter - 元视角 通过 EmbededFileProvider 实现 Blazor 的静态文件访问 - 元视角 低代码,想说爱你不容易 - 元视角 记一次失败的 ThoughtWorks 面试经历 - 元视角 从 C# 1.0 到 C# 9.0,历代 C# 语言特性一览 - 元视角 通过 Python 分析 2020 年全年微博热搜数据 - 元视角 基于 Python 和 Selenium 实现 CSDN 一键三连自动化 - 元视角 使用多线程为你的 Python 爬虫提速的 N 种姿势,你会几种? - 元视角 实现网页长截图的常见思路总结 - 元视角 温故而知新,由 ADO.NET 与 Dapper 所联想到的 - 元视角 视频是不能 P 的系列:OpenCV 人脸检测 - 元视角 作为技术宅的我,是这样追鬼滅の刃的 - 元视角 使用 Python 抽取《半泽直树》原著小说人物关系 - 元视角 厉害了!打工人用 Python 分析西安市职位信息 - 元视角 使用 dotTrace 对 .NET 应用进行性能分析与优化 - 元视角 一道 HashSet 面试题引发的蝴蝶效应 - 元视角 基于选项模式实现.NET Core 的配置热更新 - 元视角 Dapper.Contrib 在 Oracle 环境下引发 ORA-00928 异常问题的解决 - 元视角 .NET Core 中对象池(Object Pool)的使用 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(下):EventBus 篇 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(中):RabbitMQ 篇 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(上):基础篇 - 元视角 记一次从已损坏的 Git 仓库中找回代码的经历 - 元视角 .NET Core 原生 DI 扩展之属性注入实现 - 元视角
EasyAR 尝鲜系列教程之 ImageTarget 千呼万唤始出来 - 元视角
飞鸿踏雪 · 2015-12-09 · via 元视角

各位朋友大家好,欢迎大家关注我的博客,我是秦元培,我的博客地址是http://qinyuanpei.com。最近 EasyAR 终于迎来了一次重大的版本更新:v1.10,真可谓是“千呼万唤始出来”啊,所以在官方文档和示例项目基本完善的情况下,博主决定将 EasyAR 尝鲜系列教程继续下去。本次教程主要以官方新发布的 Unity 示例项目为基础来进行讲解,关注 Androis/iOS 原生应用开发的朋友请自行针对官方示例项目进行研究。好了,今天主要的内容是通过 EasyAR SDK 来自行构建一个 ImageTarget 的实例,采用 Unity3D 4.6.4 版本进行开发。

EasyAR SDK 的结构

将 EasyAR SDK 导入 Unity3D 后会在项目的 Assets 根目录下生成 EasyAR 和 Plugins 两个文件夹。其中 EasyAR 文件夹中提供了开发 AR 应用相关的标准接口、材质、Shader 和 Prefab,Plugins 文件夹中提供了针对各个平台的插件。好了,下面我们来介绍 EasyAR SDK 中提供的标准接口:

  • ARBuilder: 该类提供了 EasyAR 初始化的相关方法,我们在编写 EasyAR 配置类的时候会用到这个类,这是一个可以直接使用的类。
  • ImageTargetBehaviour: 该类是一个抽象类,我们需要对其进行 override,可以将这个类理解为 ImageTarget 生命周期相关的一个类,在实际使用中需要配合 ITargetEventHandle 这个接口来使用。
  • VideoPlayerBaseBehaviour: 该类是一个组件,我们可以使用这个组件来播放视频。其原理和 ImageTarget 类似,所不同的地方是 ImageTarget 在识别成功后会显示一个模型,而这里则是使用一个隐藏的物体来播放视频,VideoPlayerBaseBehaviour 负责控制视频的播放、暂停等工作。
  • ITargetEventHandle: 这是一个接口,通过该接口可以捕捉到识别过程中的 OnTargetFound、OnTargetLost、OnTargetLoad 和 OnTargetUnload 四个事件,对于一个基本的 AR 应用来说,我们通常需要关注的是 OnTargetFound、OnTargetLost 这两个方法。

构建第一个 ImageTarget 项目

好了,在了解了 EasyAR 中常用的标准接口以后,我们下面来着手构建第一个 ImageTarget 项目,和我们第一次接触 EasyAR 不同,这次我们会编写些简单地代码,打开场景填入应用程序密钥(Key)然后运行它,这种方式在这里会显得略 LOW。

EasyAR 的初始化

首先我们在 Assets/EasyAR/Prefabs 目录下找到 EasyAR 这个预制体,然后将其拖放到场景中,这样我们就创建了基本的 EasyAR 应用场景,接下来我们要做的事情就是在这个场景中填入各种各样的识别物。为了让 EasyAR 正常工作,我们首先要编写一个初始化 EasyAR 的脚本:

using UnityEngine;
using System.Collections;
using EasyAR;

public class EasyARConfig : MonoBehaviour 
{
    /// <summary>
    /// 应用程序密钥
    /// </summary>
    [TextArea(1,10)]
    public string Key;

    public void Awake()
    {
        //检查KEY是否存在
        if(string.IsNullOrEmpty(Key))
            Debug.Log("请先输入应用程序密钥");

        //初始化EasyAR
        ARBuilder.Instance.InitializeEasyAR(Key);
        ARBuilder.Instance.EasyBuild();
    }
    
}

我确信这个类简单到彻底,它需要开发者在编辑器中填入 KEY 然后再 Awake 方法中完成对 EasyAR 的初始化,就是这样简单,我们这里将这个脚本附加到 EasyAR 这个物体上去,这样我们就完成了引擎的初始化工作,下面我们就可以专注于 AR 内容的产生了。

制作一个 ImageTarget

接下来我们在 Assets/EasyAR/Prefabs 目录中找到 ImageTarget 这个预制体,将其拖放到场景中,确保它在摄像机的视野范围内。我们注意到默认情况下它附加了一个 ImageTargetBehaviour 脚本,我们在前面已经说过,这个类是一个抽象类,抽象类通常是不做任何事情的,因此我们需要继承这个类来编写一个具体类,我们将这个具体类命名为 CustomImageTargetBehaviour。下面给出它的代码实现:

using UnityEngine;
using System.Collections;
using EasyAR;

public class CustomImageTargetBehaviour :ImageTargetBehaviour,ITargetEventHandler
{

    protected override void Start()
    {
        //在Start方法中隐藏模型
        base.Start();
        HideObjects(transform);
    }

    /// <summary>
    /// 隐藏模型的方法
    /// </summary>
    /// <param name="trans">要隐藏的Transform</param>
    void HideObjects(Transform trans)
    {
        for (int i = 0; i < trans.childCount; ++i)
            HideObjects(trans.GetChild(i));
        if (transform != trans)
            gameObject.SetActive(false);
    }

    /// <summary>
    /// 显示模型的方法
    /// </summary>
    /// <param name="trans">要显示的Transform</param>
    void ShowObjects(Transform trans)
    {
        for (int i = 0; i < trans.childCount; ++i)
            ShowObjects(trans.GetChild(i));
        if (transform != trans)
            gameObject.SetActive(true);
    }

    /// <summary>
    /// 实现ITargetEventHandler接口中的OnTargetFound方法
    /// </summary>
    /// <param name="target">识别目标</param>
    void ITargetEventHandler.OnTargetFound(Target target)
    {
        ShowObjects(transform);
    }

    /// <summary>
    /// 实现ITargetEventHandler接口中的OnTargetLost方法
    /// </summary>
    /// <param name="target">识别目标</param>
    void ITargetEventHandler.OnTargetLost(Target target)
    {
        HideObjects(transform);
    }

    /// <summary>
    /// 实现ITargetEventHandler接口中的OnTargetLoad方法
    /// </summary>
    /// <param name="target">识别目标</param>
    void ITargetEventHandler.OnTargetLoad(Target target, bool status)
    {
        
    }

    /// <summary>
    /// 实现ITargetEventHandler接口中的OnTargetUnload方法
    /// </summary>
    /// <param name="target">识别目标</param>
    void ITargetEventHandler.OnTargetUnload(Target target, bool status)
    {
       
    }
}

可以注意到在这个类中我们主要做了两件事情:第一,定义了隐藏和显示识别模型的方法 HideObjects 和 ShowObjects,其作用是在没有识别到 Target 的时候隐藏物体,在识别到 Target 的时候显示物体;第二,实现了 ITargetEventHandler 接口并在 OnTargetFound 和 OnTargetLost 两个方法中实现我们第一步希望达到的目的。至此,我们完成了一个基本的 AR 识别组件,我们下面所有的 AR 识别物体都是通过这个组件来工作的,所以我们从场景中的 ImageTarget 物体上移除默认的 ImageTargetBehaviour 脚本然后为其添加我们定义的 CustomImageTargetBehaviour 脚本。

编写完脚本以后我们就可以着手制作识别图和 Marker 了,EasyAR 最让人喜欢的一点就是你可以按照自己的意愿来制作识别图和 Marker。虽然 Vuforia 在识别效果上比 EasyAR 更好点,可是对程序员来说选择一个透明的产品方案比面对着黑箱子进行调试要明智得多。EasyAR 中的识别图相对来说比较简单,因为我们只需要选择一张图片然后为其创建一个材质,再将这个材质附加到 ImageTarget 物体上就可以了。此外还会涉及到某些参数的设置,我们下面会提到。好了,我们继续选择官方示例中的 idback 这张图片来作为我们的识别图,因为身份证每个人都有可以随时用来进行测试,而一般的图片则需要打印出来制成硬质卡片来使用。我们在 Assets 目录中创建一个 StreamingAssets 目录,将官方示例中 targets.json 和 idbcak.jpg 两个文件拷贝过来。创建材质就不再说了,这是 Unity3D 中非常非常基础的内容。我们将创建好的材质附加到 ImageTarget 物体上以后,可能在场景中并不会看到对应的识别图,这是因为我们没有为其配置参数。具体的参数配置如下图:

ImageTarget参数配置 ImageTarget参数配置

具体这些参数的定义请大家自己去看文档,因为我这里说得再明白如果大家不看等于我没有说。好了,下面我们来创建 Marker,这个就比较简单了,我们直接找一个模型缩放到合适的大小然后拖拽到 ImageTarget 这个物体下面就可以了。如图是博主参照官方示例制作的两个识别图及其 Marker:

两个ImageTarget及其对应Maker 两个ImageTarget及其对应Maker

走向成功的关键步骤

1、在 EasyAR 物体的 EasyARConfig 组件中填入从官网申请的 KEY。 2、在 BuildSetting 中填写 KEY 对应的 AppID。 3、安装 SDK 中附带的 VC++2015 运行库。 4、如要编译 Android 版本,请确保安装 Java 环境和 Android SDK 更多的问题请自行到官方文档中对照寻找解决办法。

截图展示

截图展示 截图展示