稀疏直接法

文章介绍了如何通过计算图像中指定位置的像素值,利用雅可比矩阵和高斯牛顿法,结合金字塔层次结构进行多层直接法,实现两个图像间相机位姿的估计。方法包括像素梯度求解和稀疏直接法的应用。
摘要由CSDN通过智能技术生成

获取图像中指定位置像素值的函数,通过插值的方法获取(x,y)处的像素:

inline float GetPixelValue(const cv::Mat &img, float x, float y) {}
   

计算雅可比矩阵:

几个重要的参数:

const VecVector2d &px_ref_;//像素坐标 xy
const vector<double> depth_ref_;//深度信息
T21;//相机位姿
Eigen::Vector3d point_ref;//相机坐标系下坐标
Eigen::Vector3d point_cur;//世界坐标系下坐标
u,v;//经变换矩阵求得的第二张图片对应的像素坐标

有了这些我们就可以计算出雅可比矩阵了

for (int x = -half_patch_size; x <= half_patch_size; x++)
            for (int y = -half_patch_size; y <= half_patch_size; y++) {
                double error = GetPixelValue(img1, px_ref[i][0] + x, px_ref[i][1] + y) -
                               GetPixelValue(img2, u + x, v + y);
                Matrix26d J_pixel_xi;
                Eigen::Vector2d J_img_pixel;

                J_pixel_xi(0, 0) = fx * Z_inv;
                J_pixel_xi(0, 1) = 0;
                //.........
                J_img_pixel = Eigen::Vector2d(
                    0.5 * (GetPixelValue(img2, u + 1 + x, v + y) - GetPixelValue(img2, u - 1 + x, v + y)),
                    0.5 * (GetPixelValue(img2, u + x, v + 1 + y) - GetPixelValue(img2, u + x, v - 1 + y))
                );//获得像素梯度

                // total jacobian
                Vector6d J = -1.0 * (J_img_pixel.transpose() * J_pixel_xi).transpose();
                hessian += J * J.transpose();
                bias += -error * J;
                cost_tmp += error * error;
            }

这边是遍历了以(x,y)为中心的像素块,获得了误差,梯度方向,H矩阵,这边求像素梯度,只是简单的求了u+1和u-1的灰度之差除以2,作为其方向的梯度。

估计两个图像之间的位姿

使用高斯牛顿法来获得相机位姿,并将估计的像素位置绘画到第二幅图像上。

void DirectPoseEstimationSingleLayer(){}

多层直接法

把单层直接法拓展到金字塔式的多层直接法上

几个参数

int pyramids = 4;//金字塔层数
double pyramid_scale = 0.5;//金字塔缩放因子
double scales[] = {1.0, 0.5, 0.25, 0.125};//金字塔尺度

多层金字塔

通过循环迭代,逐层构建金字塔,每一层都是上一层图像的一半。

 vector<cv::Mat> pyr1, pyr2; // image pyramids
    for (int i = 0; i < pyramids; i++) {
        if (i == 0) {
            pyr1.push_back(img1);
            pyr2.push_back(img2);
        } else {
            cv::Mat img1_pyr, img2_pyr;
            cv::resize(pyr1[i - 1], img1_pyr,
                       cv::Size(pyr1[i - 1].cols * pyramid_scale, pyr1[i - 1].rows * pyramid_scale));
            cv::resize(pyr2[i - 1], img2_pyr,
                       cv::Size(pyr2[i - 1].cols * pyramid_scale, pyr2[i - 1].rows * pyramid_scale));
            pyr1.push_back(img1_pyr);
            pyr2.push_back(img2_pyr);
        }
    }

  

还要记得根据金字塔尺度调整相机内参

double fxG = fx, fyG = fy, cxG = cx, cyG = cy;  // backup the old values
    for (int level = pyramids - 1; level >= 0; level--) {
        VecVector2d px_ref_pyr; // set the keypoints in this pyramid level
        for (auto &px: px_ref) {
            px_ref_pyr.push_back(scales[level] * px);
        }

        // scale fx, fy, cx, cy in different pyramid levels
        fx = fxG * scales[level];
        fy = fyG * scales[level];
        cx = cxG * scales[level];
        cy = cyG * scales[level];
        DirectPoseEstimationSingleLayer(pyr1[level], pyr2[level], px_ref_pyr, depth_ref, T21);

main

这边是稀疏直接法,我选取2000个像素点,分别把他们添加进去容器里面。调用多层直接法函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值