ORB-SLAM2-金字塔求解-特征点的提取-描述子的计算

//这个成员函数重载了函数括号运算符,让他具有函数的特点
//但是还不知道在其他程序块是如何应用这块代码的。
//InputArray和OutputArray是opencv中的两个函数接口
void ORBextractor::operator()( InputArray _image, InputArray _mask, vector<KeyPoint>& _keypoints,
                      OutputArray _descriptors)
{ 
    if(_image.empty())
        return;
    //将输入的图像转换为Mat数据类型
    Mat image = _image.getMat();
    //判断数据类型是不是8bits单通道类型
    assert(image.type() == CV_8UC1 );

    // Pre-compute the scale pyramid
    //先计算输入图像的金字塔
    ComputePyramid(image);
    //从金字塔中的每一层图像中获取所有的特征点都存储在allKeypoints向量中
    vector < vector<KeyPoint> > allKeypoints;
    ComputeKeyPointsOctTree(allKeypoints);
    //ComputeKeyPointsOld(allKeypoints);

    Mat descriptors;

    int nkeypoints = 0;
    //将每一层获取的特征点的个数累加
    for (int level = 0; level < nlevels; ++level)
        nkeypoints += (int)allKeypoints[level].size();
    if( nkeypoints == 0 )
        _descriptors.release();
    else
    {
        //OutputArray是InputArray的派生类,在使用_OutputArray.getMat()之前要先用create()来为    
         //矩阵分配内存。
        _descriptors.create(nkeypoints, 32, CV_8U);
        descriptors = _descriptors.getMat();
    }

    _keypoints.clear();
    _keypoints.reserve(nkeypoints);

    int offset = 0;
    for (int level = 0; level < nlevels; ++level)
    {
        //首先获取每一层图像上提取的特征点
        vector<KeyPoint>& keypoints = allKeypoints[level];
        //统计每层图像上提取的特征点的个数
        int nkeypointsLevel = (int)keypoints.size();

        if(nkeypointsLevel==0)
            continue;

        // preprocess the resized image
        //每次将金字塔上某一层上的图像复制都workingMat中
        Mat workingMat = mvImagePyramid[level].clone();
        //对这个图像用高斯滤波器进行平滑,输出的图像仍然放在workingMat中的
        GaussianBlur(workingMat, workingMat, Size(7, 7), 2, 2, BORDER_REFLECT_101);
        //平滑之后计算描述子
        // Compute the descriptors
        //一个特征点的描述子占一行
        Mat desc = descriptors.rowRange(offset, offset + nkeypointsLevel);
        computeDescriptors(workingMat, keypoints, desc, pattern);
        //将所有层上的特征点的描述子都放在一起,每一行是一个描述子
        offset += nkeypointsLevel;

        // Scale keypoint coordinates
        if (level != 0)
        {
            //scale是金字塔中不同层图像所代表的尺度,越往上尺度越大
            float scale = mvScaleFactor[level]; //getScale(level, firstLevel, scaleFactor);
            //我们先前在提取金字塔中每一层图像中的特征点时,特征点的坐标都设置为了在当前图像
            //下的坐标,从第i-1层图像变为第i层图像,相当于将图像中每一个像素点的坐标除以1.2
        
            //所以为了得到每一层图像上提取的特征点在原图像中的坐标位置需要乘以1.2。
            for (vector<KeyPoint>::iterator keypoint = keypoints.begin(),
                 keypointEnd = keypoints.end(); keypoint != keypointEnd; ++keypoint)
                keypoint->pt *= scale;
        }
        // And add the keypoints to the output
        _keypoints.insert(_keypoints.end(), keypoints.begin(), keypoints.end());
    }
}
//按照上面的操作步骤是提取到每层图像上的特征点之后直接就计算特征点的描述子,和将每层中提取的特征
//点的坐标还原到原图像上去。而没有先用四叉树对提取的特征点进行优化。

猜你喜欢

转载自blog.csdn.net/weixin_38636815/article/details/82106847