slambook2+ch7+orb_self 源码的一点小问题+解读
源码详细解读
下面是一些个人的见解内联代码片
。
// compute the descriptor
void ComputeORB(const cv::Mat &img, vector<cv::KeyPoint> &keypoints, vector<DescType> &descriptors) {
const int half_patch_size = 8;
const int half_boundary = 16;
int bad_points = 0;
for (auto &kp: keypoints) {//剔除在边界上的关键点
if (kp.pt.x < half_boundary || kp.pt.y < half_boundary ||
kp.pt.x >= img.cols - half_boundary || kp.pt.y >= img.rows - half_boundary) {
// outside
bad_points++;
descriptors.push_back({});
continue;
}
//这里并没有计算图像块的灰度质心,只是计算了m10,m01,然后算的角度
float m01 = 0, m10 = 0;
for (int dx = -half_patch_size; dx < half_patch_size; ++dx) {
for (int dy = -half_patch_size; dy < half_patch_size; ++dy) {
uchar pixel = img.at<uchar>(kp.pt.y + dy, kp.pt.x + dx);
m10 += dx * pixel;
m01 += dy * pixel;
}
}
// angle should be arc tan(m01/m10);
float m_sqrt = sqrt(m01 * m01 + m10 * m10) + 1e-18; // avoid divide by zero
float sin_theta = m01 / m_sqrt;
float cos_theta = m10 / m_sqrt;
// compute the angle of this point
DescType desc(8, 0);
for (int i = 0; i < 8; i++) { //8*32=256位的描述子
uint32_t d = 0; //定义一个32位的数据。存储32个0,1数据
for (int k = 0; k < 32; k++) { //循环32次,比较p,q值,计算BRIEF描述子
int idx_pq = i * 32 + k; //每次循环用掉4个值,一共256行数据,一次循环32行,故乘以系数32
cv::Point2f p(ORB_pattern[idx_pq * 4], ORB_pattern[idx_pq * 4 + 1]);
cv::Point2f q(ORB_pattern[idx_pq * 4 + 2], ORB_pattern[idx_pq * 4 + 3]);
// rotate with theta
//这一部分点为double型,有点类似于插值的干法
cv::Point2f pp = cv::Point2f(cos_theta * p.x - sin_theta * p.y, sin_theta * p.x + cos_theta * p.y)
+ kp.pt;
cv::Point2f qq = cv::Point2f(cos_theta * q.x - sin_theta * q.y, sin_theta * q.x + cos_theta * q.y)
+ kp.pt;
//这里再强制类型转换,取最近邻像素坐标的灰度值用于计算
if (img.at<uchar>(pp.y, pp.x) < img.at<uchar>(qq.y, qq.x)) {
d |= 1 << k;
}
}
desc[i] = d;
}//至此,计算出一个点的描述子
descriptors.push_back(desc);
}
cout << "bad/total: " << bad_points << "/" << keypoints.size() << endl;
}
// brute-force matching
void BfMatch(const vector<DescType> &desc1, const vector<DescType> &desc2, vector<cv::DMatch> &matches) {
const int d_max = 40;
for (size_t i1 = 0; i1 < desc1.size(); ++i1) {
if (desc1[i1].empty()) continue;//如果vector是空就为真
//这里前面俩参数都是代表的描述子的number,一个的A图的,一个是B图的,最后一个是用于记录描述子的距离
cv::DMatch m{int(i1), 0, 256};//源码这里有问题,需要强制类型转换
for (size_t i2 = 0; i2 < desc2.size(); ++i2) {//依次比对,寻找最接近那个,所以暴力匹配才需要匹配i1*i2次
if (desc2[i2].empty()) continue;
int distance = 0;
for (int k = 0; k < 8; k++) {
distance += _mm_popcnt_u32(desc1[i1][k] ^ desc2[i2][k]);//SSE指令集,计算变量中1的个数
}
if (distance < d_max && distance < m.distance) {
m.distance = distance;
m.trainIdx = i2;
}
}
if (m.distance < d_max) {
matches.push_back(m);
}
}
}
小错误调试,有的真的属实自己菜
比如,传入图片路径不对,就会有这种错误