【ORB_SLAM2源码解读】计算特征的点的灰度质心(11)

图文讲解

【ORB_SLAM2源码解读】计算特征的点的灰度质心(11)_第1张图片

// keypoint->angle = IC_Angle(image, keypoint->pt, umax);
static float IC_Angle(const Mat& image, Point2f pt,  const vector<int> & u_max)
{
    // .at(), .ptr()获取像素值
    // 一般灰度图像元素是8位的uchar型(注意不是无符号整型, 而是无符号字符型, 元素值0-255)
    // 若图像为单通道图像,直接使用image.at(y, x) = ...;即可对第y行,x列的对应点进行操作。
    // 通过行指针&image.at和偏移量可以索引特征点所在行的每一个像素值
    // 理解cv::Mat 在内存中的存储和像素的索引规则
    const uchar* center = &image.at<uchar> (cvRound(pt.y), cvRound(pt.x));
    // u -15
    // center[u] 88
    // m_10 0
    // m_10 += u * center[u] -1320

    // u -14
    // center[u] 86
    // m_10 -1320
    // m_10 += u * center[u] -2524

    // y乘像素值 求和
    int m_01 = 0;
    // x乘像素值 求和
    int m_10 = 0;
    // center[u] 200
    // cvRound(pt.y)+u 227
    // cvRound(pt.x)+u) 200
    // 计算特征点所在的行, 也就是所谓的地零行,X乘像素值的和
    for (int u = -HALF_PATCH_SIZE; u <= HALF_PATCH_SIZE; ++u){
        m_10 += u * center[u];
    }

    // Go line by line in the circular patch 理解 cv::Mat 在内存中的存储和像素的索引规则
    /**
     * 假设图像为 1024*768 感兴趣区域ROI为 400*200
     * 访问这个感兴趣区域的下一行,图像数据指针的步长step应该为 1024 而不是 200
     * |***| CV_8UC3 彩色图 一个像素需要3个字节24位存储
     * |*| CV_8UC1 灰度图 一个像素需要1个字节8位存储
     * CV_8UC1(CV_位数+数据类型+通道数 C1-C4表示对应的通道数,即有1-4个通道)8位无符号单通道->灰度图片
     */
    int step = (int)image.step1();// 790 理解为图像的宽度
    // std::cout << "image.cols " << image.cols << endl;// 752
    // std::cout << "image.rows " << image.rows << endl;// 480

    // std::cout << "(int)image.step1() " << image.step1() << endl;// 790
    // std::cout << "(int)image.step " << image.step << endl;// 790

    /**
     *     * * * * * * * * * * * * * * * umax[0] = 15  umax16个数值依次是:15 15 15 15 14 14 14 13 13 12 11 10 9 8 6 3
     *     * * * * * * * * * * * * * * * umax[1] = 15
     *     * * * * * * * * * * * * * * * umax[2] = 15
     *     * * * * * * * * * * * * * * * umax[3] = 15
     *     * * * * * * * * * * * * * * umax[4] = 14
     *     * * * * * * * * * * * * * * umax[5] = 14
     *     * * * * * * * * * * * * * * umax[5] = 14
     *     * * * * * * * * * * * * * umax[5] = 14
     *     * * * * * * * * * * * * * umax[7] = 13
     *     * * * * * * * * * * * * umax[7] = 13
     *     * * * * * * * * * * * umax[7] = 13
     *     * * * * * * * * * * umax[9] = 12
     *     * * * * * * * * * * umax[10] = 11
     *     * * * * * * * * * umax[11] = 10
     *     * * * * * * * * * umax[12] = 9
     *     * * * * * * * * umax[13] = 8
     *     * * * * * * umax[14] = 6
     *     * * * umax[15] = 3
     */

    // 遍历 行  1 < v <= HALF_PATCH_SIZE
    for (int v = 1; v <= HALF_PATCH_SIZE; ++v)
    {
        // Proceed over the two lines
        int v_sum = 0;
        int d = u_max[v];
        // 遍历列 -u_max[v] < u < u_max[v]
        for (int u = -d; u <= d; ++u)
        {
            int val_plus = center[u + v*step], val_minus = center[u - v*step];// 像素值

            // 特征点所在行的上面第v行(1 < v < 15)的第u个像素值
            // int val_plus = center[u + v*step];
            // m_10 += u * val_plus;

            // 特征点所在行的下面第v行(1 < v < 15)的第u个像素值
            // int val_minus = center[u - v*step];
            // m_10 += u * val_minus;
            
            m_10 += u * (val_plus + val_minus);

            // 每次计算的两个点 val_plus = center[u + v*step] 是特征点下一行, 最左边的像素值 坐标是 (-u_max[v],pt.y-1)
            // 每次计算的两个点 val_minus = center[u - v*step] 是特征点上一行, 最左边的像素值 坐标是 (-u_max[v],pt.y+1)
            // 需要提前理解 建立图像坐标系 图像在矩阵中的存储结构
            // 每次计算的两个点: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) )
            v_sum += (val_plus - val_minus);// 负号来自于 坐标 y 的值
        }
        // 求质量心的圆形区域内,每个像素坐标v(Y)值,乘像素值center[],求和m_10
        m_01 += v * v_sum;

    }
    // float fastAtan2(float y,float x)  求y 和 x 之间的夹角,向量的x坐标 向量的y坐标 输入一个2维向量,计算这个向量的方向,以度为单位范围是0度-360度
    // fastAtan2函数得出的角度是以X轴正方向为0°方向, 然后角度按照逆时针方向以360°为终点,角度范围0°-360°
    return fastAtan2((float)m_01, (float)m_10);
}// 如何求质心 https://blog.csdn.net/qq_21950671/article/details/107092044

视频讲解

你可能感兴趣的:(从零开始学习SLAM,ORB_SLAM2)