一、IC_Angle函数解析
static float IC_Angle(const Mat& image, Point2f pt, const vector<int> & u_max)
{
int m_01 = 0, m_10 = 0;
const uchar* center = &image.at<uchar> (cvRound(pt.y), cvRound(pt.x));
// Treat the center line differently, v=0
for (int u = -HALF_PATCH_SIZE; u <= HALF_PATCH_SIZE; ++u)
m_10 += u * center[u];
// Go line by line in the circuI853lar patch
int step = (int)image.step1();
for (int v = 1; v <= HALF_PATCH_SIZE; ++v)
{
// Proceed over the two lines
int v_sum = 0;
int d = u_max[v];
for (int u = -d; u <= d; ++u)
{
int val_plus = center[u + v*step], val_minus = center[u - v*step];
v_sum += (val_plus - val_minus);
m_10 += u * (val_plus + val_minus);
}
m_01 += v * v_sum;
}
return fastAtan2((float)m_01, (float)m_10);
}
以下是IC_Angle
函数的逐行解析及其原理说明:
功能概述
该函数用于计算图像特征点的方向角(ORB特征中的灰度质心方向),通过分析局部图像块的灰度分布,实现特征点的旋转不变性。核心思想是通过计算图像块的质心方向,确定特征点的主方向。
输入参数
image
:输入的灰度图像(OpenCVMat
类型)。pt
:特征点坐标(Point2f
类型,可能为浮点数,但会转换为整数像素位置)。u_max
:预计算的每行最大水平偏移量,用于控制圆形区域的采样范围。
代码解析
1. 初始化变量
int m_01 = 0, m_10 = 0;
const uchar* center = &image.at<uchar>(cvRound(pt.y), cvRound(pt.x));
m_01
和m_10
:分别表示图像块的垂直和水平方向的一阶矩(用于计算质心)。center
:指向特征点中心像素的指针(通过cvRound
取整确保整数坐标)。
2. 处理中心行(v=0)
for (int u = -HALF_PATCH_SIZE; u <= HALF_PATCH_SIZE; ++u)
m_10 += u * center[u];
- 目的:计算中心行(
v=0
)的水平方向矩。 - 原理:对中心行的每个像素,用水平偏移
u
加权灰度值,累加到m_10
。 - 优化:直接遍历水平方向,无需处理垂直对称性。
3. 处理非中心行(v≥1)
int step = (int)image.step1();
for (int v = 1; v <= HALF_PATCH_SIZE; ++v) {
int v_sum = 0;
int d = u_max[v];
for (int u = -d; u <= d; ++u) {
int val_plus = center[u + v*step], val_minus = center[u - v*step];
v_sum += (val_plus - val_minus);
m_10 += u * (val_plus + val_minus);
}
m_01 += v * v_sum;
}
step
:图像每行的步长(字节数除以Mat
元素大小)。- 循环逻辑:
- 外层循环:遍历垂直方向(
v
从1到HALF_PATCH_SIZE
)。 - 内层循环:根据
u_max[v]
确定每行的水平偏移范围d
,保证采样区域为圆形。
- 外层循环:遍历垂直方向(
- 对称性优化:
- 同时处理
v
和-v
行的像素(通过val_plus
和val_minus
)。 v_sum
累加垂直方向梯度(val_plus - val_minus
)。m_10
累加水平方向矩(u * (val_plus + val_minus)
)。m_01
累加垂直方向矩(v * v_sum
- 同时处理