Dyna-SLAM代码解读:Geometry.cc(三)

            matProjDepth = __matProjDepth.colRange(0, h);
            vMPCurrentFrame = _vMPCurrentFrame.colRange(0, h);
            vAllMatRefFrame = _vAllMatRefFrame.rowRange(0, h);
            vLabels = _vLabels.rowRange(0, h);
            vAllDepthRefFrame = __vAllDepthRefFrame.rowRange(0, h);

            cv::Mat aux;
            cv::hconcat(cv::Mat::eye(3, 3, CV_32F), cv::Mat::zeros(3, 1, CV_32F), aux);
            cv::Mat matCurrentFrame = K * aux * vMPCurrentFrame;

            cv::Mat mat2CurrentFrame(matCurrentFrame.cols, 2, CV_32F);
            cv::Mat v2AllMatRefFrame(matCurrentFrame.cols, 3, CV_32F);
            cv::Mat mat2ProjDepth(matCurrentFrame.cols, 1, CV_32F);
            cv::Mat v2Labels(matCurrentFrame.cols, 1, CV_32F);
            cv::Mat _vAllDepthRefFrame(matCurrentFrame.cols, 1, CV_32F);

            int j = 0;
            for (int i(0); i < matCurrentFrame.cols; i++)
            {
                float x = ceil(matCurrentFrame.at<float>(0, i) / matCurrentFrame.at<float>(2, i));
                float y = ceil(matCurrentFrame.at<float>(1, i) / matCurrentFrame.at<float>(2, i));
                if (IsInFrame(x, y, currentFrame))
                {
                    const float d = currentFrame.mImDepth.at<float>(y, x);
                    if (d > 0)
                    {
                        mat2CurrentFrame.at<float>(j, 0) = x;
                        mat2CurrentFrame.at<float>(j, 1) = y;
                        v2AllMatRefFrame.at<float>(j, 0) = vAllMatRefFrame.at<float>(i, 0);
                        v2AllMatRefFrame.at<float>(j, 1) = vAllMatRefFrame.at<float>(i, 1);
                        v2AllMatRefFrame.at<float>(j, 2) = vAllMatRefFrame.at<float>(i, 2);
                        _vAllDepthRefFrame.at<float>(j, 0) = vAllDepthRefFrame.at<float>(i, 0);
                        float d1 = matProjDepth.at<float>(0, i);
                        mat2ProjDepth.at<float>(j, 0) = d1;
                        v2Labels.at<float>(j, 0) = vLabels.at<float>(i, 0);
                        j++;
                    }
                }
            }

这段代码的主要作用是根据之前代码段中的筛选和复制操作后得到的数据,对一些新的矩阵进行初始化和赋值。

具体解释如下:

  • matProjDepth = __matProjDepth.colRange(0, h);:将之前 _matProjDepth 矩阵中的列范围从0到h的部分复制给 matProjDepth 矩阵。
  • vMPCurrentFrame = _vMPCurrentFrame.colRange(0, h);:将之前 _vMPCurrentFrame 矩阵中的列范围从0到h的部分复制给 vMPCurrentFrame 矩阵。
  • vAllMatRefFrame = _vAllMatRefFrame.rowRange(0, h);:将之前 _vAllMatRefFrame 矩阵中的行范围从0到h的部分复制给 vAllMatRefFrame 矩阵。
  • vLabels = _vLabels.rowRange(0, h);:将之前 _vLabels 矩阵中的行范围从0到h的部分复制给 vLabels 矩阵。
  • vAllDepthRefFrame = __vAllDepthRefFrame.rowRange(0, h);:将之前 __vAllDepthRefFrame 矩阵中的行范围从0到h的部分复制给 vAllDepthRefFrame 矩阵。

这些操作是为了截取之前复制并筛选的矩阵的有效范围。

接下来,代码创建了几个新的矩阵并进行了初始化:

  • aux 矩阵是一个3×4的矩阵,通过在3×3的单位矩阵右边添加一个3×1的零矩阵得到。
  • matCurrentFrame 矩阵通过将矩阵 aux 与矩阵 vMPCurrentFrame 相乘,并再次与矩阵 K 相乘得到。
  • mat2CurrentFrame 矩阵是一个大小为 matCurrentFrame 列数×2的矩阵。
  • v2AllMatRefFrame 矩阵是一个大小为 matCurrentFrame 列数×3的矩阵。
  • mat2ProjDepth 矩阵是一个大小为 matCurrentFrame 列数×1的矩阵。
  • v2Labels 矩阵是一个大小为 matCurrentFrame 列数×1的矩阵。
  • _vAllDepthRefFrame 矩阵是一个大小为 matCurrentFrame 列数×1的矩阵。

 

循环,根据一些条件筛选和赋值操作,通过将符合条件的数据从一个矩阵复制到另外一些矩阵中。

具体的解释如下:

  • int j = 0;:初始化一个变量 j 为 0,用于记录符合条件数据的索引。
  • for (int i(0); i < matCurrentFrame.cols; i++):循环遍历 matCurrentFrame 矩阵的列数,i 从 0 开始递增。
  • float x = ceil(matCurrentFrame.at<float>(0, i) / matCurrentFrame.at<float>(2, i));:计算将 matCurrentFrame 矩阵第一行第 i 列的值除以第三行第 i 列的值,并向上取整,得到 x 坐标。
  • float y = ceil(matCurrentFrame.at<float>(1, i) / matCurrentFrame.at<float>(2, i));:计算将 matCurrentFrame 矩阵第二行第 i 列的值除以第三行第 i 列的值,并向上取整,得到 y 坐标。
  • if (IsInFrame(x, y, currentFrame)):判断坐标 (x, y) 是否在 currentFrame 的帧范围内。
  • 在上一步的条件满足时,继续执行以下操作:
    • const float d = currentFrame.mImDepth.at<float>(y, x);:获取 currentFrame 的深度图像中坐标 (y, x) 处的深度值并赋值给变量 d。
    • if (d > 0):判断深度值是否大于 0。
    • 在上一步的条件满足时,执行以下赋值操作:
      • mat2CurrentFrame.at<float>(j, 0) = x;:将 x 坐标值赋给 mat2CurrentFrame 矩阵第 j 行第 0 列。
      • mat2CurrentFrame.at<float>(j, 1) = y;:将 y 坐标值赋给 mat2CurrentFrame 矩阵第 j 行第 1 列。
      • 将相关的值从其他矩阵复制到目标矩阵,例如:
        • v2AllMatRefFrame.at<float>(j, 0) = vAllMatRefFrame.at<float>(i, 0);
        • _vAllDepthRefFrame.at<float>(j, 0) = vAllDepthRefFrame.at<float>(i, 0);
        • float d1 = matProjDepth.at<float>(0, i); mat2ProjDepth.at<float>(j, 0) = d1;
        • v2Labels.at<float>(j, 0) = vLabels.at<float>(i, 0);
      • 最后,增加 j 的值使其递增。

这段代码的目的是根据条件筛选并复制符合条件的数据到新的矩阵中,以便进行后续处理和计算。

            vAllDepthRefFrame = _vAllDepthRefFrame.rowRange(0, j);
            vAllMatRefFrame = v2AllMatRefFrame.rowRange(0, j);
            matProjDepth = mat2ProjDepth.rowRange(0, j);
            matCurrentFrame = mat2CurrentFrame.rowRange(0, j);
            vLabels = v2Labels.rowRange(0, j);

            cv::Mat u1((2 * mDmax + 1) * (2 * mDmax + 1), 2, CV_32F);
            int m(0);
            for (int i(-mDmax); i <= mDmax; i++)
            {
                for (int j(-mDmax); j <= mDmax; j++)
                {
                    u1.at<float>(m, 0) = i;
                    u1.at<float>(m, 1) = j;
                    m++;
                }
            }

 

这段代码涉及到一些矩阵操作和循环。

具体的解释如下:

  • vAllDepthRefFrame = _vAllDepthRefFrame.rowRange(0, j);:将 _vAllDepthRefFrame 矩阵的前 j 行(索引从 0 到 j-1)复制给 vAllDepthRefFrame 矩阵。
  • vAllMatRefFrame = v2AllMatRefFrame.rowRange(0, j);:将 v2AllMatRefFrame 矩阵的前 j 行复制给 vAllMatRefFrame 矩阵。
  • matProjDepth = mat2ProjDepth.rowRange(0, j);:将 mat2ProjDepth 矩阵的前 j 行复制给 matProjDepth 矩阵。
  • matCurrentFrame = mat2CurrentFrame.rowRange(0, j);:将 mat2CurrentFrame 矩阵的前 j 行复制给 matCurrentFrame 矩阵。
  • vLabels = v2Labels.rowRange(0, j);:将 v2Labels 矩阵的前 j 行复制给 vLabels 矩阵。
  • 上述操作将通过之前的循环筛选出来的部分数据赋值给新的矩阵。
  • cv::Mat u1((2 * mDmax + 1) * (2 * mDmax + 1), 2, CV_32F);:创建一个 CV_32F 类型的矩阵 u1,其行数为 (2 * mDmax + 1) * (2 * mDmax + 1),列数为 2。
  • int m(0);:初始化一个变量 m 为 0,用于记录索引。
  • for (int i(-mDmax); i <= mDmax; i++):循环遍历 i,从 -mDmax 开始,每次增加 1,直到 mDmax
  • 在上一步的循环中,继续执行以下操作:
    • for (int j(-mDmax); j <= mDmax; j++):循环遍历 j,从 -mDmax 开始,每次增加 1,直到 mDmax
    • 在内部循环中,执行以下操作:
      • u1.at<float>(m, 0) = i;:将变量 i 的值赋给矩阵 u1 的第 m 行第 0 列。
      • u1.at<float>(m, 1) = j;:将变量 j 的值赋给矩阵 u1 的第 m 行第 1 列。
      • 增加变量 m 的值使其递增。

这段代码的目的是根据一些参数和条件,进行矩阵操作、数据筛选和数值赋值。最后,在一个循环中生成一个新的矩阵 u1,其中的值根据循环变量 ij 的值依次进行赋值。

cv::Mat matDepthCurrentFrame(matCurrentFrame.rows, 1, CV_32F);
            cv::Mat _matProjDepth(matCurrentFrame.rows, 1, CV_32F);
            cv::Mat _matCurrentFrame(matCurrentFrame.rows, 2, CV_32F);

            int _s(0);
            for (int i(0); i < matCurrentFrame.rows; i++)
            {
                int s(0);
                cv::Mat _matDiffDepth(u1.rows, 1, CV_32F);
                cv::Mat _matDepth(u1.rows, 1, CV_32F);
                for (int j(0); j < u1.rows; j++)
                {
                    int x = (int)matCurrentFrame.at<float>(i, 0) + (int)u1.at<float>(j, 0);
                    int y = (int)matCurrentFrame.at<float>(i, 1) + (int)u1.at<float>(j, 1);
                    float _d = currentFrame.mImDepth.at<float>(y, x);
                    if ((_d > 0) && (_d < matProjDepth.at<float>(i, 0)))
                    {
                        _matDepth.at<float>(s, 0) = _d;
                        _matDiffDepth.at<float>(s, 0) = matProjDepth.at<float>(i, 0) - _d;
                        s++;
                    }
                }
                if (s > 0)
                {
                    _matDepth = _matDepth.rowRange(0, s);
                    _matDiffDepth = _matDiffDepth.rowRange(0, s);
                    double minVal, maxVal;
                    cv::Point minIdx, maxIdx;
                    cv::minMaxLoc(_matDiffDepth, &minVal, &maxVal, &minIdx, &maxIdx);
                    int xIndex = minIdx.x;
                    int yIndex = minIdx.y;
                    matDepthCurrentFrame.at<float>(_s, 0) = _matDepth.at<float>(yIndex, 0);
                    _matProjDepth.at<float>(_s, 0) = matProjDepth.at<float>(i, 0);
                    _matCurrentFrame.at<float>(_s, 0) = matCurrentFrame.at<float>(i, 0);
                    _matCurrentFrame.at<float>(_s, 1) = matCurrentFrame.at<float>(i, 1);
                    _s++;
                }
            }

 

这段代码执行了一些计算,涉及到矩阵的操作、条件判断和循环。

具体的解释如下:

  • cv::Mat matDepthCurrentFrame(matCurrentFrame.rows, 1, CV_32F);:创建一个大小为 matCurrentFrame.rows 行 1 列的浮点型矩阵 matDepthCurrentFrame
  • cv::Mat _matProjDepth(matCurrentFrame.rows, 1, CV_32F);:创建一个大小为 matCurrentFrame.rows 行 1 列的浮点型矩阵 _matProjDepth
  • cv::Mat _matCurrentFrame(matCurrentFrame.rows, 2, CV_32F);:创建一个大小为 matCurrentFrame.rows 行 2 列的浮点型矩阵 _matCurrentFrame

以上步骤是为了创建存储结果的矩阵。

  • int _s(0);:初始化一个变量 _s 为 0,用于记录索引。
  • for (int i(0); i < matCurrentFrame.rows; i++):循环遍历 i,从 0 开始,逐个增加,直到 matCurrentFrame 矩阵的行数。
  • 在上述循环中,执行以下操作:
    • int s(0);:初始化一个变量 s 为 0,用于记录索引。
    • cv::Mat _matDiffDepth(u1.rows, 1, CV_32F);:创建一个大小为 u1.rows 行 1 列的浮点型矩阵 _matDiffDepth
    • cv::Mat _matDepth(u1.rows, 1, CV_32F);:创建一个大小为 u1.rows 行 1 列的浮点型矩阵 _matDepth
    • 在内部循环中,执行以下操作:
      • 根据当前循环中的 i 值计算出 xy 坐标。
      • 获取 currentFrame.mImDepth 矩阵中坐标为 (y, x) 处的值,并赋给变量 _d
      • 如果 _d 大于 0 并且小于 matProjDepth 矩阵中对应位置的值,则进入条件判断内部。
      • 在条件成立的情况下,将 _d 赋值给 _matDepth 矩阵的第 s 行第 0 列,并计算差值赋给 _matDiffDepth 矩阵的第 s 行第 0 列。然后递增 s 的值。
    • 如果 s 大于 0,表示有满足条件的数据,进入条件判断内部。
    • 在条件成立的情况下,截取 _matDepth_matDiffDepth 矩阵的前 s 行。
    • 通过 cv::minMaxLoc 函数计算 _matDiffDepth 矩阵中的最小值、最大值及其位置。
    • 获取最小值位置的横坐标 xIndex 和纵坐标 yIndex
    • 根据索引值,将对应位置的数据赋给结果矩阵 matDepthCurrentFrame_matProjDepth_matCurrentFrame
    • 递增 _s 的值。

这段代码的目的是根据一些条件和数据进行筛选和计算,从而得到最终的结果矩阵和索引值。

 

matDepthCurrentFrame = matDepthCurrentFrame.rowRange(0, _s);
            matProjDepth = _matProjDepth.rowRange(0, _s);
            matCurrentFrame = _matCurrentFrame.rowRange(0, _s);

            mDepthThreshold = 0.6;

            cv::Mat matDepthDifference = matProjDepth - matDepthCurrentFrame;

            mVarThreshold = 0.001; // 0.040;

            vector<Geometry::DynKeyPoint> vDynPoints;

            for (int i(0); i < matCurrentFrame.rows; i++)
            {
                if (matDepthDifference.at<float>(i, 0) > mDepthThreshold)
                {
                    int xIni = (int)matCurrentFrame.at<float>(i, 0) - mDmax;
                    int yIni = (int)matCurrentFrame.at<float>(i, 1) - mDmax;
                    int xEnd = (int)matCurrentFrame.at<float>(i, 0) + mDmax + 1;
                    int yEnd = (int)matCurrentFrame.at<float>(i, 1) + mDmax + 1;
                    cv::Mat patch = currentFrame.mImDepth.rowRange(yIni, yEnd).colRange(xIni, xEnd);
                    cv::Mat mean, stddev;
                    cv::meanStdDev(patch, mean, stddev);
                    double _stddev = stddev.at<double>(0, 0);
                    double var = _stddev * _stddev;
                    if (var < mVarThreshold)
                    {
                        DynKeyPoint dynPoint;
                        dynPoint.mPoint.x = matCurrentFrame.at<float>(i, 0);
                        dynPoint.mPoint.y = matCurrentFrame.at<float>(i, 1);
                        dynPoint.mRefFrameLabel = vLabels.at<float>(i, 0);
                        vDynPoints.push_back(dynPoint);
                    }
                }
            }

            return vDynPoints;
        }
        else
        {
            vector<Geometry::DynKeyPoint> vDynPoints;
            return vDynPoints;
        }
    }

这段代码是一个函数,根据给定的输入参数进行深度图像处理,并返回动态关键点的向量。

函数首先对一些变量进行初始化,包括matDepthCurrentFramematProjDepthmatCurrentFrame(这些都是OpenCV的cv::Mat对象)。然后,定义了一些阈值(mDepthThresholdmVarThreshold)。

接下来,通过对matProjDepthmatDepthCurrentFrame进行减法操作,计算了matDepthDifference。然后,使用一个循环遍历matCurrentFrame的每一行。

在循环中,首先检查matDepthDifference当前行的第一个元素是否大于mDepthThreshold。如果是,则进一步处理该点。

然后,根据matCurrentFrame当前行的前两个元素(即坐标)计算出一个矩形区域,并提取当前帧的深度图像中对应区域的一个小块(patch)。

接下来,使用cv::meanStdDev函数计算patch的均值和标准差,并根据标准差计算方差(var)。

最后,如果方差小于mVarThreshold,则创建一个DynKeyPoint对象,将相关信息(包括位置和参考帧标签)存储在其中,并将该对象添加到vDynPoints向量中。

最后,在函数的末尾,如果输入参数不满足某些条件(判断条件看不到提供的完整代码部分),则返回一个空的vDynPoints向量。

综上所述,该函数的作用是从给定的深度图像中提取满足一定条件的动态关键点,并将这些关键点以DynKeyPoint对象的形式存储在一个向量中返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值