第三章 无标记式增强现实

3.1 基于标记的AR与无标记的AR

算法 基于标记的AR 基于无标记的AR
优点
  • 检测算法简单
  • 对光线变化鲁棒性好
  • 检测算法复杂
  • 对光线变化鲁棒性较差
缺点
  • 标记部分重叠时无法工作
  • 标记的图像必须是黑色和白色
  • 大多情况下,标记的图像要有方形
  • 与真实世界的对象没有共同点
  • 可用于检测现实世界的对象
  • 即使目标对象部分重叠也可工作
  • 可以有任意的形状和纹理

无标记AR利用真实图像和对象来定位摄像机,并在真实图像上进行渲染。其核心是图像识别和目标检测算法。

3.2 用特征描述符来检测视频中的任意图像

使用特征点和特征描述符可以很好地解决模式图像受到透视变换而不能直接与测试图像进行比较的问题。特征提取是指从输入图像中寻找感兴趣区域,例如寻找edges(边缘)corners(角点)或blobs(斑点)。书中第三章关注的是角点。

  • The corner detection is based on an analysis of the edges in the image. A corner-based edge detection algorithm searches for rapid changes in the image gradient. Usually it's done by looking for extremums of the first derivative of the image gradients in the X and Y directions.

  • 特征点的主方向通过计算图像某区域内的图像主方向梯度得到。is usually computed as a direction of dominant image gradient in a particular area. When the image is rotated or scaled, the orientation of dominant gradient is recomputed by the feature-detection algorithm. This means that regardless of image rotation, the orientation of feature points will not change. Such features are called rotation invariant(旋转不变性).

  • 一些特征检测算法使用固定大小的特征,然而其他算法分别计算每一个关键点的最优化大小。知道了特征点的大小,我们可以在被缩放图像中找到同样的特征点。使得特征尺度不变。 I have to mention a few points about the size feature point. Some of the feature-detection algorithms use fixed-size features, while others calculate the optimal size for each keypoint separately. Knowing the feature size allows us to find the same feature points on scaled images. This makes features scale invariant.

  • opencv特征检测算法

  1. 通过特征检测所在类的构造函数显式调用  Via an explicit call of the concrete feature detector class constructor:。

cv::Ptr<cv::FeatureDetector> detector =

cv::Ptr<cv::FeatureDetector>(new cv::SurfFeatureDetector());

2.通过算法名创建一个特征检测器  Or by creating a feature detector by algorithm name:

cv::Ptr<cv::FeatureDetector> detector =

cv::FeatureDetector::create("SURF");

  • 检测特征点,调用detect

std::vector<cv::KeyPoint> keypoints;

detector->detect(image, keypoints);

检测到的特征点存储在 keypoints 容器中。每一个关键点包含它的中心,半径,角度和分数,以及一些与特征点相关的”质量”或者”强度”。每一个特征检测算法拥有自己的评分计算算法,因此通过特定的检测算法比较关键点的分数是很有效的。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

计算关键点的方向和大小,可以使得关键点具有尺度和旋转的不变性,像SIFT/SURF  ORB/FREAK。(#the ORB algorithm does estimate keypoint orientation, but the feature size is still fixed.)

两帧之间逐像素地去比较图像计算花费很大,我们选择相信特征可以描述图像的一个部分,包含了下许多信息。所以为了宣召两帧之间的匹配关系,我们只需要匹配关键点。如何匹配关键点呢?我们在由关键点定义的patch上提取一个向量称之为描述子,作为对特征点的表达。再利用两个特征描述符的相似度距离来衡量。

特征描述子提取算法源于

 cv::DescrptorExtrator 

基类。同样的,作为特征检测算法他们可以通过指定算法名或者使用显式构造函数的调用来创建。


3.2.2 模式对象定义

为了描述一个模式对象,这里定义一个类叫做pattern。pattern里面包含一张训练图像/特征和描述子列表以及对应的2D和3D的初始pattern位置确定。

/**
* Store the image data and computed descriptors of target pattern*/
struct Pattern
{cv::Size  size;cv::Mat    data;std::vector<cv::KeyPoint>   keypoints;cv::Mat                     descriptors;    std::vector<cv::Point2f>    points2d;std::vector<cv::Point3f>    points3d;
};

3.2.3 特征点匹配

寻找帧与帧之间对应关系的过程可以看作是寻找一个描述子集中每一个元素在另一个描述子集中的最近邻。

OpenCV中提供了bruteForce 暴力搜索和FLANN两种匹配方法的使用 (FLANN fast library for approximate nearest neighbors )

BF https://baike.baidu.com/item/BF%E7%AE%97%E6%B3%95/4326761

FLANN 算法 in OpenCV

https://blog.csdn.net/cshilin/article/details/52107580& https://blog.csdn.net/App_12062011/article/details/51987352

描述符匹配的结果是一个列表,列表上有两个描述符集合之间的对应关系。描述子的第一个集通常称为训练集,对应pattern图像。第二个集称为查询集,属于我们将要搜索的图像。找到越多的正确匹配(pattern与图像的对应越多),该图像上更有可能存在这个pattern。

为了提高匹配速度,在调用匹配函数之前,你可以训练一个匹配器。训练可以优化cv::FlannBaseMatcher 。为了完成训练,train 类为训练描述子建立索引树,这将提高大数据集的匹配速率(例如,如果你想从数百张图像中什么找到一个匹配的图像)
。对于 cv::BFmatcher,train 函数不做处理,只在内部字段(internal field)简单地存储训练描述子。

下面代码使用模式图像来训练描述符匹配器

void PatternDetector::train(const Pattern& pattern)
{// Store the pattern objectm_pattern = pattern;// API of cv::DescriptorMatcher is somewhat tricky// First we clear old train data:m_matcher->clear();// That we add vector of descriptors// (each descriptors matrix describe one image).// This allows us to perform search across multiple images:std::vector<cv::Mat> descriptors(1);descriptors[0] = pattern.descriptors.clone();m_matcher->add(descriptors);// After adding train data perform actual train:m_matcher->train();
}

为了匹配在查找的描述子,可使用 cv::DescriptorMatcher类中的一个方法的:

1)找到最佳匹配的简单列表。

void match(const Mat& queryDescriptors,
vector<DMatch>& matches,
=vector<Mat>());

2、对于每一个描述子寻找 k 最近的匹配

void knnMatch(const Mat& queryDescriptors,
vector<vector<DMatch>&mathcer,int k,
const vector<Mat> &masks=vector<Mat>(),
bool compactResult=false);

3、找到不大于指定的距离的对应距离:

void radiusMatch(const Mat& queryDescrptors,
vecotor<vector<DMatch>>& matches,maxDistance,
const vector<Mat>& masks=vector<Mat>(),
bool compactResult=false);

3.2.4 删除外点(离群值

匹配阶段错误的匹配分为两种类型。
1、假阳性:当特征点的对应是错误的。
2、假阴性:当特征点在两个图像上可视时,没有匹配。
假阴性在阈值确定下已经无法解决,删除外点只能是使得假阳性错误最小化。

  • 交叉匹配技术。

这种思想是用查询集匹配训练描述子,再用训练的描述子匹配查询集。只有都存在在这两个匹配中的共同匹配才被返回。当有足够的匹配仅带有少量的异常值时,这种方法通常得到最好的结果。

交叉匹配过滤

交叉匹配可以在 cv::BFMatcher 类中访问的到。为了使用交叉检验测试,创建一个cv::BFMatcher 匹配器并且第二个参数设置为 true.

cv::Ptr<cv::DescriptorMatcher> matcher(new cv::BFMathcher(cv::NORM_HAMMING,true));
  • 比率检定。

我们首先执行 KNN-matching,参数K=2,即对于每一个匹配返回2个最临近的描述子。仅当第一个和第二个匹配的距离ratio足够大,才返回这个match。(ratio 阈值通常接近与 2)。

比率检定可以移除几乎所用的异常值。但是在一些情况下,假阳性匹配可以通过这个检定。接下来将展示怎样移除剩下的异常值并且只留下正确的匹配。

  • 单应性估计

为了进一步改善我们的匹配,我们使用随机采样一致性来过滤异常值。

当我们对图像进行处理时(一个平面物体)并且假设是刚体的。可以在pattern特征点和查询图像特征点之间找到单应性转换。单应性转换将点集从模式图像转换到查询图像坐标系统。 cv::findHomography 函数可用来寻找单应变换,它使用RANSAC来探测输入点的子集以找到最佳单应性矩阵。缺点是:函数通过计算单应矩阵的重投影误差,把每一个对应标记成内点或外点。

单应性搜索步骤很重要,因为得到的单应性变幻是找到查询图像中pattern位置的关键

  • 单应细化

当我们查找单应性转换时,已经有了查找它们3D位置的所有数据。然而,我们可以通过找到更精确的模式角点来进一步改善其位置。具体的,利用估计的单应将输入图像warp来获得已经找到的一个pattern,warp后的pattern应当非常接近于源训练图像。

单应性提纯可以帮助我们找到更精确的单应性转换。

然后,会得到另外一个单应性和另外一组内层围特征。更精确的结果单一性将是 H1 和H2 单应性的矩阵乘积。

如果所有的异常值去除阶段后,匹配的数目仍合理(至少模式图像25%的特征和输入图像对应),可以确保pattern定位准确。


特征检测--综合步骤

为了得到特征检测、描述子提取,匹配算法的实例,需要创建 PatternMatcher 类,该类封装所有的这些数据,包含了特征检测器,描述子提取算法,特征匹配算法和控制检测过程的设置。

总而言之,我们简短的列一下我们将要执行的步骤:
1、转换输出图到灰度图像
2、使用我们的特征检测算法在查询图像上检测特征
3、从输入的图像中检测到的特征点中抽取描述子
4、与模式描述子进行匹配
5、使用交叉验证或者比率检定移除异常值
6、使用内围层匹配找到单应性变换
7、通过使用上一步骤得到的单应性变换查询图像来提纯单应性。
8、找到精确的单应性作为粗略的增值和提纯的单应性
9、转换模式角点到一副图像的坐标系统,来获得模式在这个图像上的位置。

《Mastering OpenCV》--3.Markless AR.无标识式AR (1)相关推荐

  1. 《Mastering opencv....读书笔记》基于标记的虚拟现实

       虚拟现实技术一直比较火,应用领域也非常广.本次为大家讲解虚拟现实的一个入门级例子,如果对以下内容感兴趣: 初音: http://jandan.net/2012/07/09/augmented-r ...

  2. Mastering OpenCV with Practical Computer Vision Projects

    1.书名:<Mastering OpenCV with Practical Computer Vision Projects> 2.书下载地址:https://download.csdn. ...

  3. Spring Boot 无侵入式 实现 API 接口统一 JSON 格式返回

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 无侵入式 统一返回JSON格式 其实本没有没打算写这篇博客 ...

  4. 从易到难,针对复杂问题的无监督式问题分解方法

    论文标题: Unsupervised Question Decomposition for Question Answering 论文作者: Ethan Perez (FAIR,NYU), Patri ...

  5. 基于WASM的无侵入式全链路A/B Test实践

    简介:我们都知道,服务网格(ServiceMesh)可以为运行其上的微服务提供无侵入式的流量治理能力.通过配置VirtualService和DestinationRule,即可实现流量管理.超时重试. ...

  6. 【FHQ treap】维护书架(金牌导航 无旋式treap-1)

    维护书架 金牌导航 无旋式treap-1 题目大意 给出一个序列a,编号为1~n,让你做若干操作,操作有五种: 1.把第x个数放在最前面 2.把第x个数放在最后面 3.把第x个数和第x±1x\pm 1 ...

  7. 联想服务器AR系列,联想沉浸式AR游戏设备Mirage AR现场实拍图赏

    IT之家12月20日消息 今天,联想在于冰城哈尔滨举办的联想创新科技大会暨联想智能生态新品发布会上发布了全球首款沉浸式AR游戏设备Mirage AR. 联想Mirage增强现实头显主机的机身尺寸为20 ...

  8. 如何低成本快速积累用户,分享4种无脑式操作

    马云曾说过这样一句话,把梳子卖给和尚,这根本不算什么营销技巧,而是骗术,原因很简单,因为和尚根本就不需要梳子,你卖给人家不就是骗人家吗? 其实,马云说这句话的重点是:找对目标用户,不是人人都是你的客户 ...

  9. Spring Boot 无侵入式 实现API接口统一JSON格式返回

    作者 | 小魏小魏我们去那里呀 来源 | blog.csdn.net/qq_34347620/article/details/102239179 无侵入式 统一返回JSON格式 其实本没有没打算写这篇 ...

  10. 基于Arduino的无接触式智能门锁(RFID和蓝牙开锁)

    一.简单介绍 本项目基于Arduino开发,支持刷卡(复旦卡)和蓝牙串口密码发送两种方式,支持舵机和继电器(可接电磁锁等)两种开锁方式.详情见代码,代码注释很全的. 文章末尾附源程序.库文件.3D打印 ...

最新文章

  1. python 微信模块_Python使用itchat模块实现简单的微信控制电脑功能示例
  2. git pull 报错:The following untracked working tree files would be overwritten by merge
  3. JavaScript MSN 弹出消息框
  4. 单价数量和总价的公式_人教版四年级数学上册单价、数量和总价之间的关系微课...
  5. 嘉年华回顾丨李海翔带你解密腾讯TDSQL数据库的技术与未来
  6. NAND FLASH读写原理
  7. 文章马伊琍离婚,华为却成“最大赢家”?
  8. 数据库系统工程师5天修炼_程序员逆袭之路,5年IT人生从电脑装机到技术大神,人生不认输...
  9. 5行代码秀碾压,比Keras还好用的fastai来了,尝鲜PyTorch 1.0必备伴侣
  10. skywalking mysql配置_skywalking 配置和使用(windows)
  11. 《那些年啊,那些事——一个程序员的奋斗史》——53
  12. 一款保险系统架构设计图
  13. lzg_ad:EWF启用常见问题及解决方案
  14. 如何撰写软件详细设计内容?
  15. tkmybatis更新无效
  16. 如何升级iOS 16正式版?iOS 16正式版一键刷机教程
  17. 什么是数字孪生?已有哪些应用?终于有人讲明白了
  18. 【编程语言】Scala下载及安装教程 CentOS 7
  19. 手机的开发者选项怎么找(真机调试)
  20. SMT操作员是做什么的?工作职责?

热门文章

  1. 纠删码(Erasure Code)及其演进LRC(Locally Repairable Codes)原理讲解
  2. win7 升级到 win10 补丁
  3. Linux Ubuntu16挂载新硬盘并格式化硬盘方法教程笔记
  4. MCU低功耗设计(一)理论
  5. 实变函数自制笔记1:前言
  6. 如何做到在子线程更新 UI?
  7. 快递物流行业总结(一)中国快递行业生命周期理论
  8. windows 技巧篇-解除共享文件夹占用方法,解决共享文件被占用导致不可修改问题,查看共享文件被谁占用方法
  9. Linux文件系统有哪些
  10. GROW GM65 条码二维码扫描识别模块 兼容大部分条码和二维码