5.利用灰度质心计算ORB特征点方向,实现旋转不变性

  • ComputeKeyPointOctTree 跳转 computeOrientation
  • computeOrientation 跳转 IC_Angle
  • 补 : 灰度质心法
  • IC_Angle 结束 返回 computeOrientation
  • computeOrientation 结束 返回ComputeKeyPointOctTree
  • ComputeKeyPointOctTree 结束 返回operator()

均匀化之后

  • scaledPatchSize 表示当前金字塔层缩放倍数
  • nkps 表示保留的特征点数目

将保留的特征点统一成当前金字塔层的坐标,即加上minBorderX,Y

        //PATCH_SIZE是对于底层的初始图像来说的,现在要根据当前图层的尺度缩放倍数进行缩放得到缩放后的PATCH大小 和特征点的方向计算有关const int scaledPatchSize = PATCH_SIZE*mvScaleFactor[level];// Add border to coordinates and scale information//获取剔除过程后保留下来的特征点数目const int nkps = keypoints.size();//然后开始遍历这些特征点,恢复其在当前图层图像坐标系下的坐标for(int i=0; i<nkps ; i++){//对每一个保留下来的特征点,恢复到相对于当前图层“边缘扩充图像下”的坐标系的坐标keypoints[i].pt.x+=minBorderX;keypoints[i].pt.y+=minBorderY;//记录特征点来源的图像金字塔图层keypoints[i].octave=level;//记录计算方向的patch,缩放后对应的大小, 又被称作为特征点半径keypoints[i].size = scaledPatchSize;}}

使用computeOrientation计算所有层的特征点的方向

    // compute orientations//然后计算这些特征点的方向信息,注意这里还是分层计算的for (int level = 0; level < nlevels; ++level)computeOrientation(mvImagePyramid[level],   //对应的图层的图像allKeypoints[level],     //这个图层中提取并保留下来的特征点容器umax);                   //以及PATCH的横坐标边界
}

ComputeKeyPointOctTree 跳转 computeOrientation

这个函数实际只起到了遍历所有特征点的作用,在每个特征点都调用IC_Angle函数来计算特征点方向

static void computeOrientation(const Mat& image, vector<KeyPoint>& keypoints, const vector<int>& umax)
{// 遍历所有的特征点for (vector<KeyPoint>::iterator keypoint = keypoints.begin(),keypointEnd = keypoints.end(); keypoint != keypointEnd; ++keypoint){// 调用IC_Angle 函数计算这个特征点的方向keypoint->angle = IC_Angle(image,           //特征点所在的图层的图像keypoint->pt,    //特征点在这张图像中的坐标umax);           //每个特征点所在图像区块的每行的边界 u_max 组成的vector}
}

computeOrientation 跳转 IC_Angle

基本原理就是灰度质心法:每个特征点以几何中心P为圆心,画圆,计算出灰度质心Q,则P -> Q就是该特征点的方向.后面比较特征点时,先把方向统一,然后比较特征点描述子,这样特征点就不会因为旋转而不能匹配了

补 : 灰度质心法

目的:使特征点具有旋转不变性

灰度质心:像素集中点

原理:即使图像旋转,图像几何中心与灰度质心的连线也是随之改变的,可以通过这个方向恢复原始图像

输入参数是:

  • image输入图像
  • pt当前特征点坐标
  • u_max是指定一行后的u轴边界坐标
static float IC_Angle(const Mat& image, Point2f pt,  const vector<int> & u_max)
{

定义的变量center 表示特征点坐标的指针

    //图像的矩,前者是按照图像块的y坐标加权,后者是按照图像块的x坐标加权int m_01 = 0, m_10 = 0;//获得这个特征点所在的图像块的中心点坐标灰度值的指针centerconst uchar* center = &image.at<uchar> (cvRound(pt.y), cvRound(pt.x));

遍历中心线(-R到R),求m10m01,要乘加权center表示该点灰度值

不需要求m01,因为当前遍历的是u轴,v坐标为0

step 是一行的字节总数,后面遍历的时候增量乘step表示像素增量

   // Treat the center line differently, v=0//这条v=0中心线的计算需要特殊对待//由于是中心行+若干行对,所以PATCH_SIZE应该是个奇数for (int u = -HALF_PATCH_SIZE; u <= HALF_PATCH_SIZE; ++u)//注意这里的center下标u可以是负的!中心水平线上的像素按x坐标(也就是u坐标)加权m_10 += u * center[u];// Go line by line in the circular patch  //这里的step1表示这个图像一行包含的字节总数。参考[https://blog.csdn.net/qianqing13579/article/details/45318279]int step = (int)image.step1();

遍历非中心线

v从1开始,到半径的长度

    //注意这里是以v=0中心线为对称轴,然后对称地每成对的两行之间进行遍历,这样处理加快了计算速度for (int v = 1; v <= HALF_PATCH_SIZE; ++v){// Proceed over the two lines//本来m_01应该是一列一列地计算的,但是由于对称以及坐标x,y正负的原因,可以一次计算两行int v_sum = 0;// 获取某行像素横坐标的最大范围,注意这里的图像块是圆形的!int d = u_max[v];

在每个v下,遍历u,前面定义过u_max[v],表示给定一个v坐标,求出最大u坐标,这里赋值给了d

遍历d相当于遍历了给定v之后的当前行

由两个公式m_10 m_01 需要当前u或v值乘以当前像素灰度值

val_plus相当于I(x,y),val_minus相当于I(x,-y)

有了这两个变量,下面的程序就很好懂了

fastAtan2为计算特征点方向的函数

        //在坐标范围内挨个像素遍历,实际是一次遍历2个// 假设每次处理的两个点坐标,中心线下方为(x,y),中心线上方为(x,-y) // 对于某次待处理的两个点:m_10 = Σ x*I(x,y) =  x*I(x,y) + x*I(x,-y) = x*(I(x,y) + I(x,-y))// 对于某次待处理的两个点:m_01 = Σ y*I(x,y) =  y*I(x,y) - y*I(x,-y) = y*(I(x,y) - I(x,-y))for (int u = -d; u <= d; ++u){//得到需要进行加运算和减运算的像素灰度值//val_plus:在中心线下方x=u时的的像素灰度值//val_minus:在中心线上方x=u时的像素灰度值int val_plus = center[u + v*step], val_minus = center[u - v*step];//在v(y轴)上,2行所有像素灰度值之差v_sum += (val_plus - val_minus);//u轴(也就是x轴)方向上用u坐标加权和(u坐标也有正负符号),相当于同时计算两行m_10 += u * (val_plus + val_minus);}//将这一行上的和按照y坐标加权m_01 += v * v_sum;}//为了加快速度还使用了fastAtan2()函数,输出为[0,360)角度,精度为0.3°return fastAtan2((float)m_01, (float)m_10);
}

IC_Angle 结束 返回 computeOrientation

computeOrientation 结束 返回ComputeKeyPointOctTree

ComputeKeyPointOctTree 结束 返回operator()

ORB2单目读代码笔记5--利用灰度质心计算ORB特征点方向,实现旋转不变性相关推荐

  1. 单目相机标定 分辨率1920X1080 利用libuvc

    单目相机标定 分辨率1920X1080 利用libuvc libuvc 安装 开始标定 之前一直使用 usb_cam 但是默认分辨率是 640X480,调节到1920X1080后运行出错,干脆用lib ...

  2. 《第7讲 视觉里程计1 》上 7.1~7.6单目模型 读书笔记

    本文是<视觉SLAM十四讲>第7讲的个人读书笔记,为防止后期记忆遗忘写的. 本讲关注基于特征点 方式的视觉里程计算法.我们将介绍什么是特征点,如何提取和匹配特征点,以及如何根 据配对的特征 ...

  3. 变焦单目论文阅读笔记

    文章目录 双焦距光学成像模型 双焦成像原理 视场转像 本篇小结 基于双焦成像的单目立体视觉算法 算法分析 图像获取 运动模型 深度恢复 本篇小结 基于双焦的单目立体成像系统分析 深度误差与焦距 双焦系 ...

  4. Unity UGS官方例子BossRoom,NetCode部分的读代码笔记

    适配 项目引用了navMesh库,2022版本已经内置到引擎,因此升级后要删掉库引用 auth库的2.4.0有bug,编辑器环境下profile检查会抛异常,导致编辑器环境不能使用lobby,仿照官方 ...

  5. 单目三维重建学习笔记2023

    目录 速度提升24倍,30分钟室内大场景逆渲染,如视研究入选CVPR 2023 物体三维重建 MVSTER: 2d卷积3维重建

  6. 单目深度估计 | Real-Time Monocular Depth Estimation using Synthetic Data 学习笔记

    文章目录 1. 摘要 2. 创新点和局限性 3 研究 3.1 阶段1-单目深度估计模型. 3.1.1 损失函数 3.1.2 训练细节 3.2 阶段2-通过风格迁移的域自适应 3.2.1 损失函数 3. ...

  7. 2017CVPR NID-SLAM:基于归一化信息距离的鲁棒单目SLAM系统

    原作:Geoffrey Pascoe 翻译:Frank 转载请注明出处 水平有限,错误请指出 NID-SLAM:基于归一化信息距离的鲁棒单目SLAM系统 摘要 本文提出了一种基于归一化信息距离(NID ...

  8. 3D单目(mono 3D)目标检测算法综述

    layout: post title: 3D单目(mono 3D)目标检测算法综述 date: 2021-01-22 22:08:39.000000000 +09:00 categories: [算法 ...

  9. 论文翻译 | Mask-SLAM:基于语义分割掩模的鲁棒特征单目SLAM

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 1 摘要 本文提出了一种将单目视觉SLAM与基于深度学习的语义分割相结合的新方法.为了稳定运行,vSL ...

最新文章

  1. Postmortem报告
  2. bzoj2746: [HEOI2012]旅行问题
  3. 如何与室友相处?2017-12-08
  4. android 如何拖动控件的实现
  5. 基于easyui开发Web版Activiti流程定制器详解(六)——Draw2d的扩展(一)
  6. oracle 查询时间点数据_oracle统计时间段内每一天的数据(推荐)
  7. apache+webdav的安装配置
  8. 2005年最具钱途的人才:软件研发炙手可热
  9. Android Logcat 报错:Could not create the view: For input string:
  10. php文件目录教程,php文件目录操作的开发过程与示例分享
  11. docker修改镜像的存储位置_win10家庭版Docker环境搭建步骤
  12. 华北黄淮江淮等地有大雾 江南华南等地有小到中雨
  13. 在线数字转大写金额工具
  14. linux原生运行微信客户端,巧用 Docker 在 Linux 下 运行微信 PC 客户端
  15. 51nod 3199 操作栈
  16. Android 11.0 PackageManagerService(一)工作原理和启动流程
  17. 艾司博讯:拼多多新手如何正确使用多多进宝?
  18. js二分法的简单计算
  19. 【慕课网】Web学习笔记———CSS3 (一)
  20. 游戏开发者眼中的Unity 3D网页游戏测评报告

热门文章

  1. 第7章第11节:完成银行卡片视图的创建 [SwiftUI快速入门到实战]
  2. 非专业老师上怎么计算机课,非计算机专业计算机基础教学研究
  3. bzoj1599[Usaco2008 Oct]笨重的石子*
  4. 程序员:怎样才能学好英语?
  5. delphi中的public和published
  6. 去掉QTableView、QTreeView内item被选中时的虚线框
  7. 谁在痛打“诺顿”落水狗
  8. sentinel监控界面无显示
  9. 解决报错 WARNING: IPv4 forwarding is disabled. Networking will not work.
  10. No module named ensurepip