ORB_SLAM2算法中是如何计算特征点的描述子的?
文章目录
- descriptors = Mat::zeros((int)keypoints.size(), 32, CV_8UC1);
- 该函数用于基于角点检测的方法提取并返回特征向量。
static void computeDescriptors(const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors,
const vector<Point>& pattern)
{
descriptors = Mat::zeros((int)keypoints.size(), 32, CV_8UC1);
for (size_t i = 0; i < keypoints.size(); i++)
computeOrbDescriptor(keypoints[i], image, &pattern[0], descriptors.ptr((int)i));
}
AI助手
descriptors = Mat::zeros((int)keypoints.size(), 32, CV_8UC1);
该段代码生成了命名为 descriptors 的一个 cv::Mat 对象,并旨在保存特征描述符相关信息。请让我们逐行解析这段代码的功能:
Mat::zeros((int)keypoints.size(), 32, CV_8UC1);
AI助手
此函数是静态定义的,并专门用于生成一个全零的OpenCV矩阵实例。该实例具有与指定输入向量相同的行维度数值。具体来说:
(int)keypoints.size()这一运算符调用将被用于计算该矩阵的高度维度数值,并将结果转换为整型以便后续应用。- 该参数值等于向量keypoints中所包含特征点的数量。
- 32则被指定为该矩阵宽度维度的具体数值。
- CV_8UC1这种数据类型编码方式表明每个像素元素都被赋以无符号8位整数值(取值范围从0到255),这通常用于表示灰度图像数据。
因此,此代码行生成一个cv::Mat对象,并将其所有元素置零。该矩阵将被用来存储特征描述符,这些特征描述符将由32个无符号8位整数组成的向量表示。
请注意查看以下代码段:其中声明了一个名为keypoints的标准C++向量容器(std::vector),其元素类型为OpenCV的关键点(cv::KeyPoint),该容器中存储了特征点信息。其中存储了检测到的特征点。\n\n此外,在该代码段中使用了变量keypoints.size()来获取该向量中的元素数量(即特征点数目),并将这个数值赋值给后续处理使用的矩阵变量作为其行数参数。
computeOrbDescriptor函数如何计算描述子?
逐函数讲解ORB_SLAM2源码
const float factorPI = (float)(CV_PI/180.f);
static void computeOrbDescriptor(const KeyPoint& kpt,
const Mat& img, const Point* pattern,
uchar* desc)
{
float angle = (float)kpt.angle*factorPI;
float a = (float)cos(angle), b = (float)sin(angle);
const uchar* center = &img.at<uchar>(cvRound(kpt.pt.y), cvRound(kpt.pt.x));
const int step = (int)img.step;
#define GET_VALUE(idx) \
center[cvRound(pattern[idx].x*b + pattern[idx].y*a)*step + \
cvRound(pattern[idx].x*a - pattern[idx].y*b)]
for (int i = 0; i < 32; ++i, pattern += 16)
{
int t0, t1, val;
t0 = GET_VALUE(0); t1 = GET_VALUE(1);
val = t0 < t1;
t0 = GET_VALUE(2); t1 = GET_VALUE(3);
val |= (t0 < t1) << 1;
t0 = GET_VALUE(4); t1 = GET_VALUE(5);
val |= (t0 < t1) << 2;
t0 = GET_VALUE(6); t1 = GET_VALUE(7);
val |= (t0 < t1) << 3;
t0 = GET_VALUE(8); t1 = GET_VALUE(9);
val |= (t0 < t1) << 4;
t0 = GET_VALUE(10); t1 = GET_VALUE(11);
val |= (t0 < t1) << 5;
t0 = GET_VALUE(12); t1 = GET_VALUE(13);
val |= (t0 < t1) << 6;
t0 = GET_VALUE(14); t1 = GET_VALUE(15);
val |= (t0 < t1) << 7;
desc[i] = (uchar)val;
}
#undef GET_VALUE
}
AI助手
这段代码位于ORB_SLAM2算法框架内作为核心功能。它主要负责生成ORB特征描述子这一关键操作。以下将对代码的各个部分进行详细解析:
声明一个浮点型常量 factorPI,并将其赋值为 CV_PI 除以 180.f 的结果;该常量用于完成角度到弧度的转换。
该程序定义了一个名为computeOrbDescriptor的静态函数
计算特征关键点的角度值,并将其通过角度转弧度操作转化为弧度值。
其中,
-
kpt.angle表示输入的关键点角度 -
factorPI代表π的数值常数
通过公式计算给定角度的余弦函数值和正弦函数值,并将其分别赋值为变量 a 和 b。
通过访问图像 img 在坐标 cvRound(kpt.pt.y) 和 cvRound(kpt.pt.x) 处的像素值,并将该地址指向的像素值赋值给指针变量 center ,从而获得特征点的像素信息。
const int step = (int)img.step;:获取图像的行步长。
实现了一个名为GET_VALUE的宏函数...该函数用于从图像中获取特定特征点周围的像素值...其工作原理基于给定的特征点坐标及其方向信息...并结合预先设定好的图像采样模式来进行推导...具体而言...该函数通过对余弦和正弦函数作用于相应的坐标分量来推导出对应的采样点在图像空间的具体坐标...进而利用中心指针center来获取该位置处的像素数据
for (int i = 0; i < 32; ++i, pattern += 16):循环遍历32个特征点的采样模式。
在循环过程中,在每次迭代中使用 GET_VALUE 宏获取特征点周围的像素值,并将其进行对比分析以生成一个8位的二进制描述子 val。对于每一对像素值,在比较时将较小的那个像素值对应的位置设置为1位(即二进制中的1),而较大的那个则设置为0位。
将二进制描述子 val 转换为 uchar 类型并赋值给 desc 数组元素 i。该步骤实现了特征向量的二进制化处理。
#undef GET_VALUE:取消宏定义。
这段代码的作用是基于输入提供的特征点信息及其图像数据,在预设的空间采样模式下对目标区域进行像素值采集,并生成相应的二进制特征码。这些二进制编码则被用来构建...
注
表示图像特征,并用于后续的特征匹配和姿态估计等任务。
