三角化求空间点

前言


在视觉追踪中或者SLAM中,不可避免的使用到三角化求空间点的坐标的过程,已知条件不同,求解空间点坐标的方法也就不同,因此在这里就总结一下,欢迎讨论。

方法一


已知:两个视图一组匹配点 x 1 x_1 x1 x 2 x_2 x2,每个视图的相机投影矩阵映射关系 P 1 P_1 P1 P 2 P_2 P2.
:3D点的空间坐标。
解法:根据如下公式很容易求得X, x 1 = P 1 X x_1=P_1X x1=P1X
同理, x 2 = P 2 X x_2=P_2X x2=P2X也非常容易求得 X X X得3D点坐标.如果投影矩阵 P 1 、 P 2 P_1、P_2 P1P2不是针对同一个世界坐标系,求得3D点坐标本身就没啥意义。如果针对的是同一个世界坐标系,由于误差的影响, X X X的坐标并不可能完全一致。
而另外一种算法:
x 1 × ( P 1 X ) = 0 x 2 × ( P 2 X ) = 0 x_1 ×(P_1X)=0\\x_2×(P_2X)=0 x1×(P1X)=0x2×(P2X)=0
展开
[ 0 − 1 y 1 0 − x − y x 0 ] [ P 1 T X P 2 T X P 3 T X ] = 0 \begin{bmatrix} 0 & -1 &y \\ 1 & 0&-x\\ -y&x&0\end{bmatrix} \begin{bmatrix} P^{1T}X\\P^{2T}X\\P^{3T}X\end{bmatrix} =0 01y10xyx0P1TXP2TXP3TX=0
即: x ( P 3 T X ) − P 1 T X = 0 y ( P 3 T X ) − P 2 T X = 0 x ( P 2 T X ) − y ( P 1 T X ) = 0 x(P^{3T}X) -P^{1T}X = 0\\y(P^{3T}X) -P^{2T}X = 0\\x(P^{2T}X) -y(P^{1T}X) = 0 x(P3TX)P1TX=0y(P3TX)P2TX=0x(P2TX)y(P1TX)=0
由于第三个公式可以有上两个公式可得,因此有:
x 1 ( P 1 3 T X ) − P 1 1 T X = 0 y 1 ( P 1 3 T X ) − P 1 2 T X = 0 x 2 ( P 2 3 T X ) − P 2 1 T X = 0 y 2 ( P 2 3 T X ) − P 2 2 T X = 0 x_1(P_1^{3T}X) -P_1^{1T}X = 0\\y_1(P_1^{3T}X) -P_1^{2T}X = 0\\x_2(P_2^{3T}X) -P_2^{1T}X = 0\\y_2(P_2^{3T}X) -P_2^{2T}X = 0 x1(P13TX)P11TX=0y1(P13TX)P12TX=0x2(P23TX)P21TX=0y2(P23TX)P22TX=0
可以化简为 A X = 0 AX = 0 AX=0
从而可以求得 X X X的3D坐标.

void Initializer::Triangulate(const cv::KeyPoint &kp1, const cv::KeyPoint &kp2, const cv::Mat &P1, const cv::Mat &P2, cv::Mat &x3D)
{
    cv::Mat A(4,4,CV_32F);

    A.row(0) = kp1.pt.x*P1.row(2)-P1.row(0);
    A.row(1) = kp1.pt.y*P1.row(2)-P1.row(1);
    A.row(2) = kp2.pt.x*P2.row(2)-P2.row(0);
    A.row(3) = kp2.pt.y*P2.row(2)-P2.row(1);

    cv::Mat u,w,vt;
    cv::SVD::compute(A,w,u,vt,cv::SVD::MODIFY_A| cv::SVD::FULL_UV);
    x3D = vt.row(3).t();
    x3D = x3D.rowRange(0,3)/x3D.at<float>(3);
}

两种求解方法后者精度高些。

方法二


已知: 两个相机的相对位姿 T T T的情况下,得到在两个视图下的对应匹配点 x ↔ x ′ x↔x′ xx
求得: 图像点的深度
解法: 以第一个图像帧为参考帧,R和t是第i到第i+1帧的旋转和位移在这里插入图片描述

float3 triangulatenNonLin(
    const float3 &bearing_vector_ref,
    const float3 &bearing_vector_curr,
    const SE3<float> &T_ref_curr)
{
  const float3 t = T_ref_curr.getTranslation();
  float3 f2 = T_ref_curr.rotate(bearing_vector_curr);
  const float2 b = make_float2(dot(t, bearing_vector_ref),
                               dot(t, f2));
  float A[2*2];
  A[0] = dot(bearing_vector_ref, bearing_vector_ref);
  A[2] = dot(bearing_vector_ref, f2);
  A[1] = -A[2];
  A[3] = dot(-f2, f2);

  const float2 lambdavec = make_float2(A[3]*b.x - A[1]*b.y,
      -A[2]*b.x + A[0]*b.y) / (A[0]*A[3] - A[1]*A[2]);
  const float3 xm = lambdavec.x * bearing_vector_ref;
  const float3 xn = t + lambdavec.y * f2;
  return (xm + xn)/2.0f;
}
bool depthFromTriangulation(
    const SE3& T_search_ref,
    const Vector3d& f_ref,
    const Vector3d& f_cur,
    double& depth)
{
  Matrix<double,3,2> A; A << T_search_ref.rotation_matrix() * f_ref, f_cur;
  const Matrix2d AtA = A.transpose()*A;
  if(AtA.determinant() < 0.000001)
    return false;
  // d = - (ATA)^(-1) * AT * t
  const Vector2d depth2 = - AtA.inverse()*A.transpose()*T_search_ref.translation();
  depth = fabs(depth2[0]);
  return true;
}

待完善
参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在计算机视觉中,通过计算图像中的视差信息,可以推断出物体在三维空间中的坐标位置。Python提供了多种方法来实现这一过程。 视差是指在两个图像之间对应之间的水平偏移量,它可以用来衡量物体在不同视角下的位置差异。计算视差通常使用的方法是利用两个图像之间的像素匹配,首先从左右图像中选取对应的像素,然后通过计算这些对应的水平偏移量来得出视差信息。 在Python中,可以使用OpenCV库来进行视差计算。OpenCV提供了StereoSGBM(Semi-Global Block Matching)算法来实现视差计算。该算法首先通过匹配特征来进行初始视差估计,然后通过全局优化来获得更精确的结果。 利用StereoSGBM算法,可以将两个图像输入模型,并设置一些参数,例如窗口大小、最小和最大视差等。然后使用算法计算出视差图,其中每个像素都对应了一个视差值。 然后,可以根据视差值来计算三维坐标。由于相机的内参和基线(两个相机之间的距离)已知,可以使用三角测量的方法来计算三维坐标。通过将视差值和相机参数代入三角测量公式,即可得到对应像素的三维坐标。 总结而言,利用Python中的OpenCV库中的StereoSGBM算法,可以实现通过已知视差来求解三维坐标的问题。这个过程主要包括计算视差图和利用已知相机参数进行三角测量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值