关于Opencv中棋盘格标定对内外参求导详解

内外参求导详解

参考资料

1、Opencv源码 此cvProjectPoints2()函数

算法原理介绍

1. 成像模型

[ u v 1 ] \begin{bmatrix} u \\ v \\ 1 \\ \end{bmatrix} uv1 = [ f x 0 c x 0 f y c y 0 0 1 ] \begin{bmatrix} fx &0 &cx \\ 0 &fy &cy \\ 0 &0 &1 \\ \end{bmatrix} fx000fy0cxcy1 ( 1 + k 1 ∗ y 2 + k 2 ∗ r 4 ) (1+k1*y^2+k2*r^4) (1+k1y2+k2r4) [ r 1 r 2 r 3 t 1 r 4 r 5 r 6 t 2 r 7 r 8 r 9 t 3 0 0 0 1 ] \begin{bmatrix} r1&r2&r3&t1 \\ r4&r5&r6&t2 \\ r7&r8&r9&t3\\ 0 & 0 & 0 & 1 \\ \end{bmatrix} r1r4r70r2r5r80r3r6r90t1t2t31 [ X Y Z 1 ] \begin{bmatrix} X \\ Y\\ Z \\ 1\\\end{bmatrix} XYZ1 1 Z \frac {1}{Z} Z1

此模型为传统模型,不做过多赘述

对此我们将此模型转化为:
[ u v 1 ] \begin{bmatrix} u \\ v \\ 1 \\ \end{bmatrix} uv1 = [ f x 0 c x 0 f y c y 0 0 1 ] \begin{bmatrix} fx &0 &cx \\ 0 &fy &cy \\ 0 &0 &1 \\ \end{bmatrix} fx000fy0cxcy1 [ x ˇ y ˇ 1 ] \begin{bmatrix} \check{x} \\ \check{y}\\ 1 \\\end{bmatrix} xˇyˇ1

其中:
{ f x ∗ x ˇ + c x = u f y ∗ y ˇ + c y = v \left\{ \begin{array}{c} fx*\check{x}+cx=u \\ fy*\check{y}+cy=v \end{array} \right. {fxxˇ+cx=ufyyˇ+cy=v

{ X ′ = r 1 ∗ X + r 2 ∗ Y + r 3 ∗ Z + t 1 r 7 ∗ X + r 8 ∗ Y + r 9 ∗ Z + t 3 Y ′ = r 4 ∗ X + r 5 ∗ Y + r 6 ∗ Z + t 2 r 7 ∗ X + r 8 ∗ Y + r 9 ∗ Z + t 3 \left\{ \begin{array}{c} X'= \frac {r1*X+r2*Y+r3*Z+t1}{r7*X+r8*Y+r9*Z+t3} \\ Y'= \frac {r4*X+r5*Y+r6*Z+t2}{r7*X+r8*Y+r9*Z+t3} \end{array} \right. {X=r7X+r8Y+r9Z+t3r1X+r2Y+r3Z+t1Y=r7X+r8Y+r9Z+t3r4X+r5Y+r6Z+t2

{ x ˇ = ( 1 + k 1 ∗ r 2 + k 2 ∗ r 4 ) ∗ X ′ y ˇ = ( 1 + k 1 ∗ r 2 + k 2 ∗ r 4 ) ∗ Y ′ \left\{ \begin{array}{c} \check{x}= (1+k1*r^2+k2*r^4)* X'\\ \check{y} = (1+k1*r^2+k2*r^4) * Y' \end{array} \right. {xˇ=(1+k1r2+k2r4)Xyˇ=(1+k1r2+k2r4)Y

        double X = M[i].x, Y = M[i].y, Z = M[i].z;//世界坐标系
        double x = R[0]*X + R[1]*Y + R[2]*Z + t[0];
        double y = R[3]*X + R[4]*Y + R[5]*Z + t[1];
        double z = R[6]*X + R[7]*Y + R[8]*Z + t[2];
        double r2, r4, r6, a1, a2, a3, cdist, icdist2;
        double xd, yd, xd0, yd0, invProj;
        Vec3d vecTilt;
        Vec3d dVecTilt;
        Matx22d dMatTilt;
        Vec2d dXdYd;

        z = z ? 1./z : 1;
        x *= z; y *= z;//图像坐标系 乘了1/z

        r2 = x*x + y*y;
        r4 = r2*r2;
        r6 = r4*r2;
        a1 = 2*x*y;
        a2 = r2 + 2*x*x;
        a3 = r2 + 2*y*y;
        cdist = 1 + k[0]*r2 + k[1]*r4 + k[4]*r6;
        icdist2 = 1./(1 + k[5]*r2 + k[6]*r4 + k[7]*r6);
        xd0 = x*cdist*icdist2 + k[2]*a1 + k[3]*a2 + k[8]*r2+k[9]*r4;
        yd0 = y*cdist*icdist2 + k[2]*a3 + k[3]*a1 + k[10]*r2+k[11]*r4;

        // additional distortion by projecting onto a tilt plane
        vecTilt = matTilt*Vec3d(xd0, yd0, 1);
        invProj = vecTilt(2) ? 1./vecTilt(2) : 1;
        xd = invProj * vecTilt(0);
        yd = invProj * vecTilt(1);

        m[i].x = xd*fx + cx;
        m[i].y = yd*fy + cy;

首先对fx fy cx cy求导

d p d f x ∣ x = x ˇ \left. \frac{{\rm d}p}{{\rm d}fx} \right|_{x} =\check{x} dfxdp x=xˇ
d p d f y ∣ y = y ˇ \left. \frac{{\rm d}p}{{\rm d}fy} \right|_{y} =\check{y} dfydp y=yˇ
d p d c x ∣ x = 1 \left. \frac{{\rm d}p}{{\rm d}cx} \right|_{x} =1 dcxdp x=1
d p d c y ∣ y = 1 \left. \frac{{\rm d}p}{{\rm d}cy} \right|_{y} =1 dcydp y=1

   if( dpdc_p )
            {
                dpdc_p[0] = 1; dpdc_p[1] = 0; // dp_xdc_x; dp_xdc_y
                dpdc_p[dpdc_step] = 0;
                dpdc_p[dpdc_step+1] = 1;
                dpdc_p += dpdc_step*2;
            }
  if( dpdf_p )
            {
                if( fixedAspectRatio )
                {
                    dpdf_p[0] = 0; dpdf_p[1] = xd*aspectRatio; // dp_xdf_x; dp_xdf_y
                    dpdf_p[dpdf_step] = 0;
                    dpdf_p[dpdf_step+1] = yd;
                }
                else
                {
                    dpdf_p[0] = xd; dpdf_p[1] = 0;
                    dpdf_p[dpdf_step] = 0;
                    dpdf_p[dpdf_step+1] = yd;
                }
                dpdf_p += dpdf_step*2;
            }

因为有两个方程都要对fx,fy,cx,cy求导,比如第一个方程关于fx cx的方程与fy cy无关,所以为0

对畸变系数k1,k2 求导 (我们仅仅考虑k1 k2 其他不多叙述)

d p d k 1 ∣ x = f x ∗ d x ˇ d k 1 ∣ = f x ∗ r 2 ∗ X ′ \left. \frac{{\rm d}p}{{\rm d}k1} \right |_{x} =fx*\left. \frac{{\rm d}\check{x}}{{\rm d}k1} \right| =fx*r^2*X' dk1dp x=fxdk1dxˇ =fxr2X
d p d k 1 ∣ y = f y ∗ d x ˇ d k 1 ∣ = f y ∗ r 2 ∗ Y ′ \left. \frac{{\rm d}p}{{\rm d}k1} \right| _{y}=fy*\left. \frac{{\rm d}\check{x}}{{\rm d}k1} \right| =fy*r^2*Y' dk1dp y=fydk1dxˇ =fyr2Y

d p d k 2 ∣ x = f x ∗ d x ˇ d k 1 ∣ = f x ∗ r 4 ∗ X ′ \left. \frac{{\rm d}p}{{\rm d}k2} \right |_{x} =fx*\left. \frac{{\rm d}\check{x}}{{\rm d}k1} \right| =fx*r^4*X' dk2dp x=fxdk1dxˇ =fxr4X
d p d k 2 ∣ y = f y ∗ d x ˇ d k 1 ∣ = f y ∗ r 4 ∗ Y ′ \left. \frac{{\rm d}p}{{\rm d}k2} \right| _{y}=fy*\left. \frac{{\rm d}\check{x}}{{\rm d}k1} \right| =fy*r^4*Y' dk2dp y=fydk1dxˇ =fyr4Y

   if( dpdk_p )
   {
     dXdYd = dMatTilt*Vec2d(x*icdist2*r2, y*icdist2*r2);
     dpdk_p[0] = fx*dXdYd(0);
     dpdk_p[dpdk_step] = fy*dXdYd(1);
     dXdYd = dMatTilt*Vec2d(x*icdist2*r4, y*icdist2*r4);
     dpdk_p[1] = fx*dXdYd(0);
     dpdk_p[dpdk_step+1] = fy*dXdYd(1);              
     dpdk_p += dpdk_step*2;
   }

下面是关键的对于外参的平移部分T,和旋转部分的R求导
根据此公式
{ X ′ = r 1 ∗ X + r 2 ∗ Y + r 3 ∗ Z + t 1 r 7 ∗ X + r 8 ∗ Y + r 9 ∗ Z + t 3 = X ′ ′ Z ′ ′ Y ′ = r 4 ∗ X + r 5 ∗ Y + r 6 ∗ Z + t 2 r 7 ∗ X + r 8 ∗ Y + r 9 ∗ Z + t 3 = Y ′ ′ Z ′ ′ \left\{ \begin{array}{c} X'= \frac {r1*X+r2*Y+r3*Z+t1}{r7*X+r8*Y+r9*Z+t3} = \frac {X''}{Z''}\\ Y'= \frac {r4*X+r5*Y+r6*Z+t2}{r7*X+r8*Y+r9*Z+t3} = \frac {Y''}{Z''} \end{array} \right. {X=r7X+r8Y+r9Z+t3r1X+r2Y+r3Z+t1=Z′′X′′Y=r7X+r8Y+r9Z+t3r4X+r5Y+r6Z+t2=Z′′Y′′

d X ′ d t ∣ t 1 = 1 r 7 ∗ X + r 8 ∗ Y + r 9 ∗ Z + t 3 = 1 Z ′ ′ \left. \frac{{\rm d}X'}{{\rm d}t} \right |_{t1} = \frac {1}{r7*X+r8*Y+r9*Z+t3}=\frac {1}{Z''} dtdX t1=r7X+r8Y+r9Z+t31=Z′′1
d X ′ d t ∣ t 2 = 0 \left. \frac{{\rm d}X'}{{\rm d}t} \right |_{t2} = 0 dtdX t2=0
d X ′ d t ∣ t 3 = X ′ ′ − Z ′ ′ 2 \left. \frac{{\rm d}X'}{{\rm d}t} \right |_{t3} =\frac {X''}{-Z''^2} dtdX t3=Z′′2X′′

d Y ′ d t ∣ t 1 = 0 \left. \frac{{\rm d}Y'}{{\rm d}t} \right |_{t1} = 0 dtdY t1=0
d Y ′ d t ∣ t 2 = 1 r 7 ∗ X + r 8 ∗ Y + r 9 ∗ Z + t 3 = 1 Z ′ ′ \left. \frac{{\rm d}Y'}{{\rm d}t} \right |_{t2} = \frac {1}{r7*X+r8*Y+r9*Z+t3}=\frac {1}{Z''} dtdY t2=r7X+r8Y+r9Z+t31=Z′′1
d Y ′ d t ∣ t 3 = Y ′ ′ − Z ′ ′ 2 \left. \frac{{\rm d}Y'}{{\rm d}t} \right |_{t3} =\frac {Y''}{-Z''^2} dtdY t3=Z′′2Y′′

对应opencv中

   double dxdt[] = { z, 0, -x*z }, dydt[] = { 0, z, -y*z };

此处在opencv中x,y,z 已经归一化过在代码块1可以看出 z = 1 Z ′ ′ z=\frac {1}{Z''} z=Z′′1 x = X ′ ′ Z ′ ′ x=\frac {X''}{Z''} x=Z′′X′′ y = Y ′ Z ′ y=\frac {Y'}{Z'} y=ZY

接着我们 r2 求导
r 2 = X ′ 2 + Y ′ 2 r^2=X'^2+Y'^2 r2=X′2+Y′2
d r 2 d t ∣ = 2 ∗ X ′ ∗ d X ′ d t ∣ + 2 ∗ Y ′ ∗ d Y ′ d t ∣ \left. \frac{{\rm d}r^2}{{\rm d}t} \right |_{} =2*X'*\left. \frac{{\rm d}X'}{{\rm d}t} \right |_{}+2*Y'* \left. \frac{{\rm d}Y'}{{\rm d}t} \right |_{} dtdr2 =2XdtdX +2YdtdY

接着我们 畸变函数 求导
k m = 1 + k 1 ∗ r 2 + k 2 ∗ r 4 km=1+k1∗r^2+k2∗r^4 km=1+k1r2+k2r4

d k m d t ∣ = k 1 ∗ d r 2 d t ∣ + 2 ∗ k 2 ∗ r 2 d r 2 d t ∣ \left. \frac{{\rm d}km}{{\rm d}t} \right |_{} =k1*\left. \frac{{\rm d}r^2}{{\rm d}t} \right |_{}+2*k2* r^2\left. \frac{{\rm d}r^2}{{\rm d}t} \right |_{} dtdkm =k1dtdr2 +2k2r2dtdr2

d p d t ∣ x = f x ∗ d x ˇ d t ∣ = f x ∗ ( d X ′ d t ∣ ∗ k m + d k m ′ d t ∣ ∗ X ′ ) \left. \frac{{\rm d}p}{{\rm d}t} \right |_{x} =fx* \left. \frac{{\rm d}\check{x} }{{\rm d}t} \right | = fx* ( \left. \frac{{\rm d}X'}{{\rm d}t} \right | *km+ \left. \frac{{\rm d}km'}{{\rm d}t} \right |*X') dtdp x=fxdtdxˇ =fx(dtdX km+dtdkm X)
d p d t ∣ y = f y ∗ d y ˇ d t ∣ = f y ∗ ( d Y ′ d t ∣ ∗ k m + d k m ′ d t ∣ ∗ Y ′ ) \left. \frac{{\rm d}p}{{\rm d}t} \right |_{y} =fy* \left. \frac{{\rm d}\check{y} }{{\rm d}t} \right | = fy* ( \left. \frac{{\rm d}Y'}{{\rm d}t} \right | *km+ \left. \frac{{\rm d}km'}{{\rm d}t} \right |*Y') dtdp y=fydtdyˇ =fy(dtdY km+dtdkm Y)

    if( dpdt_p )
    {
       double dxdt[] = { z, 0, -x*z }, dydt[] = { 0, z, -y*z };
       for( j = 0; j < 3; j++ )
        {
           double dr2dt = 2*x*dxdt[j] + 2*y*dydt[j];
           double dcdist_dt = k[0]*dr2dt + 2*k[1]*r2*dr2dt + 3*k[4]*r4*dr2dt;
           double dicdist2_dt = -icdist2*icdist2*(k[5]*dr2dt + 2*k[6]*r2*dr2dt + 3*k[7]*r4*dr2dt);
           double da1dt = 2*(x*dydt[j] + y*dxdt[j]);
           double dmxdt = (dxdt[j]*cdist*icdist2 + x*dcdist_dt*icdist2 + x*cdist*dicdist2_dt +
                            k[2]*da1dt + k[3]*(dr2dt + 4*x*dxdt[j]) + k[8]*dr2dt + 2*r2*k[9]*dr2dt);
           double dmydt = (dydt[j]*cdist*icdist2 + y*dcdist_dt*icdist2 + y*cdist*dicdist2_dt +
                                       k[2]*(dr2dt + 4*y*dydt[j]) + k[3]*da1dt + k[10]*dr2dt + 2*r2*k[11]*dr2dt);
                    dXdYd = dMatTilt*Vec2d(dmxdt, dmydt);
                    dpdt_p[j] = fx*dXdYd(0);
                    dpdt_p[dpdt_step+j] = fy*dXdYd(1);
          }
                dpdt_p += dpdt_step*2;
    }

opencv中利用3次循环对t1 t2 t3 同时求导

对旋转部分的求导比较复杂 首先利用罗格里格斯公式3*3矩阵中每一个元素对rx ry rz
求导可以发现最后的导数为3 * 27的矩阵

            double c = cos(theta);
            double s = sin(theta);
            double c1 = 1. - c;
            double itheta = theta ? 1./theta : 0.;

            r *= itheta;

            Matx33d rrt( r.x*r.x, r.x*r.y, r.x*r.z, r.x*r.y, r.y*r.y, r.y*r.z, r.x*r.z, r.y*r.z, r.z*r.z );
            Matx33d r_x(    0, -r.z,  r.y,
                          r.z,    0, -r.x,
                         -r.y,  r.x,    0 );

            // R = cos(theta)*I + (1 - cos(theta))*r*rT + sin(theta)*[r_x]
            Matx33d R = c*Matx33d::eye() + c1*rrt + s*r_x;

            Mat(R).convertTo(cvarrToMat(dst), dst->type);

            if( jacobian )
            {
                const double I[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
                double drrt[] = { r.x+r.x, r.y, r.z, r.y, 0, 0, r.z, 0, 0,
                                  0, r.x, 0, r.x, r.y+r.y, r.z, 0, r.z, 0,
                                  0, 0, r.x, 0, 0, r.y, r.x, r.y, r.z+r.z };
                double d_r_x_[] = { 0, 0, 0, 0, 0, -1, 0, 1, 0,
                                    0, 0, 1, 0, 0, 0, -1, 0, 0,
                                    0, -1, 0, 1, 0, 0, 0, 0, 0 };
                for( i = 0; i < 3; i++ )
                {
                    double ri = i == 0 ? r.x : i == 1 ? r.y : r.z;
                    double a0 = -s*ri, a1 = (s - 2*c1*itheta)*ri, a2 = c1*itheta;
                    double a3 = (c - s*itheta)*ri, a4 = s*itheta;
                    for( k = 0; k < 9; k++ )
                        J[i*9+k] = a0*I[k] + a1*rrt.val[k] + a2*drrt[i*9+k] +
                                   a3*r_x.val[k] + a4*d_r_x_[i*9+k];
                }
            }

R = c o s ( t h e t a ) ∗ I + ( 1 − c o s ( t h e t a ) ) ∗ r ∗ r T + s i n ( t h e t a ) ∗ [ r x ] R = cos(theta)*I + (1 - cos(theta))*r*rT + sin(theta)*[r_x] R=cos(theta)I+(1cos(theta))rrT+sin(theta)[rx]
t h e t a = x 2 + y 2 + z 2 theta=\sqrt{x^2+y^2+z^2} theta=x2+y2+z2

d R d x ∣ = s i n ( t h e t a ) ∗ x t h e t a − s i n ( t h e t a ) ∗ x t h e t a ∗ r ∗ r T + ( 1 − c o s ( t h e t a ) ) ∗ d r r t d x ∣ + c o s ( t h e t a ) ∗ x t h e t a ∗ [ r x ] + s i n ( t h e t a ) ∗ d [ r x ] d x ∣ \left. \frac{{\rm d}R}{{\rm d}x} \right | =sin(theta)*\frac {x}{theta}-sin(theta)*\frac {x}{theta}*r*rT+(1-cos(theta))*\left. \frac{{\rm d}rrt}{{\rm d}x} \right |+cos(theta)*\frac {x}{theta}*[r_x]+sin(theta)* \left. \frac{{\rm d}[r_x]}{{\rm d}x} \right | dxdR =sin(theta)thetaxsin(theta)thetaxrrT+(1cos(theta))dxdrrt +cos(theta)thetax[rx]+sin(theta)dxd[rx]
该式子跟opencv里面的代码对不上,还在找问题中,下一版在更新到底是哪里的问题

               double dx0dr[] =
                {
                    X*dRdr[0] + Y*dRdr[1] + Z*dRdr[2],
                    X*dRdr[9] + Y*dRdr[10] + Z*dRdr[11],
                    X*dRdr[18] + Y*dRdr[19] + Z*dRdr[20]
                };
                double dy0dr[] =
                {
                    X*dRdr[3] + Y*dRdr[4] + Z*dRdr[5],
                    X*dRdr[12] + Y*dRdr[13] + Z*dRdr[14],
                    X*dRdr[21] + Y*dRdr[22] + Z*dRdr[23]
                };
                double dz0dr[] =
                {
                    X*dRdr[6] + Y*dRdr[7] + Z*dRdr[8],
                    X*dRdr[15] + Y*dRdr[16] + Z*dRdr[17],
                    X*dRdr[24] + Y*dRdr[25] + Z*dRdr[26]
                };
                for( j = 0; j < 3; j++ )
                {
                    double dxdr = z*(dx0dr[j] - x*dz0dr[j]);
                    double dydr = z*(dy0dr[j] - y*dz0dr[j]);
                    double dr2dr = 2*x*dxdr + 2*y*dydr;
                    double dcdist_dr = (k[0] + 2*k[1]*r2 + 3*k[4]*r4)*dr2dr;
                    double dicdist2_dr = -icdist2*icdist2*(k[5] + 2*k[6]*r2 + 3*k[7]*r4)*dr2dr;
                    double da1dr = 2*(x*dydr + y*dxdr);
                    double dmxdr = (dxdr*cdist*icdist2 + x*dcdist_dr*icdist2 + x*cdist*dicdist2_dr +
                                       k[2]*da1dr + k[3]*(dr2dr + 4*x*dxdr) + (k[8] + 2*r2*k[9])*dr2dr);
                    double dmydr = (dydr*cdist*icdist2 + y*dcdist_dr*icdist2 + y*cdist*dicdist2_dr +
                                       k[2]*(dr2dr + 4*y*dydr) + k[3]*da1dr + (k[10] + 2*r2*k[11])*dr2dr);
                    dXdYd = dMatTilt*Vec2d(dmxdr, dmydr);
                    dpdr_p[j] = fx*dXdYd(0);
                    dpdr_p[dpdr_step+j] = fy*dXdYd(1);
                }
                dpdr_p += dpdr_step*2;

对于 d R d r ∣ \left. \frac{{\rm d}R}{{\rm d}r} \right | drdR 这个结果排列顺序为
d r 1 d x ∣ , d r 2 d x ∣ , d r 3 d x ∣ . . . . . . . . . \left. \frac{{\rm d}r1}{{\rm d}x} \right |,\left. \frac{{\rm d}r2}{{\rm d}x} \right | ,\left. \frac{{\rm d}r3}{{\rm d}x} \right| ......... dxdr1 ,dxdr2 ,dxdr3 .........
d r 1 d y ∣ , d r 2 d y ∣ , d r 3 d y ∣ . . . . . . . . . \left. \frac{{\rm d}r1}{{\rm d}y} \right |,\left. \frac{{\rm d}r2}{{\rm d}y} \right | ,\left. \frac{{\rm d}r3}{{\rm d}y} \right| ......... dydr1 ,dydr2 ,dydr3 .........
d r 1 d z ∣ , d r 2 d z ∣ , d r 3 d z ∣ . . . . . . . . . \left. \frac{{\rm d}r1}{{\rm d}z} \right |,\left. \frac{{\rm d}r2}{{\rm d}z} \right | ,\left. \frac{{\rm d}r3}{{\rm d}z} \right| ......... dzdr1 ,dzdr2 ,dzdr3 .........
就有式子:

{ X ∗ = r 1 ∗ X + r 2 ∗ Y + r 3 ∗ Z + t 1 Y ∗ = r 4 ∗ X + r 5 ∗ Y + r 6 ∗ Z + t 2 Z ∗ = r 7 ∗ X + r 8 ∗ Y + r 9 ∗ Z + t 3 \left\{ \begin{array}{c} X*= r1*X+r2*Y+r3*Z+t1 \\ Y*= r4*X+r5*Y+r6*Z+t2 \\ Z*= r7*X+r8*Y+r9*Z+t3 \end{array} \right. X=r1X+r2Y+r3Z+t1Y=r4X+r5Y+r6Z+t2Z=r7X+r8Y+r9Z+t3

d X ∗ d r ∣ = X ∗ d r 1 d x ∣ + Y ∗ d r 2 d x ∣ + Z ∗ d r 3 d x ∣ = X ∗ d R d r ∣ [ 0 ] + Y ∗ d R d r ∣ [ 1 ] + Z ∗ d R d r ∣ [ 2 ] \left. \frac{{\rm d}X*}{{\rm d}r} \right |=X* \left. \frac{{\rm d}r1}{{\rm d}x} \right | +Y* \left. \frac{{\rm d}r2}{{\rm d}x} \right |+Z* \left. \frac{{\rm d}r3}{{\rm d}x} \right |=X* \left. \frac{{\rm d}R}{{\rm d}r} \right |[0] +Y* \left. \frac{{\rm d}R}{{\rm d}r} \right | [1] +Z* \left. \frac{{\rm d}R}{{\rm d}r} \right |[2] drdX =Xdxdr1 +Ydxdr2 +Zdxdr3 =XdrdR [0]+YdrdR [1]+ZdrdR [2]

d X ∗ d r ∣ = X ∗ d r 1 d y ∣ + Y ∗ d r 2 d y ∣ + Z ∗ d r 3 d y ∣ = X ∗ d R d r ∣ [ 0 ] + Y ∗ d R d r ∣ [ 1 ] + Z ∗ d R d r ∣ [ 2 ] \left. \frac{{\rm d}X*}{{\rm d}r} \right |=X* \left. \frac{{\rm d}r1}{{\rm d}y} \right | +Y* \left. \frac{{\rm d}r2}{{\rm d}y} \right |+Z* \left. \frac{{\rm d}r3}{{\rm d}y} \right |=X* \left. \frac{{\rm d}R}{{\rm d}r} \right |[0] +Y* \left. \frac{{\rm d}R}{{\rm d}r} \right | [1] +Z* \left. \frac{{\rm d}R}{{\rm d}r} \right |[2] drdX =Xdydr1 +Ydydr2 +Zdydr3 =XdrdR [0]+YdrdR [1]+ZdrdR [2]

d X ∗ d r ∣ = X ∗ d r 1 d z ∣ + Y ∗ d r 2 d z ∣ + Z ∗ d r 3 d z ∣ = X ∗ d R d r ∣ [ 0 ] + Y ∗ d R d r ∣ [ 1 ] + Z ∗ d R d r ∣ [ 2 ] \left. \frac{{\rm d}X*}{{\rm d}r} \right |=X* \left. \frac{{\rm d}r1}{{\rm d}z} \right | +Y* \left. \frac{{\rm d}r2}{{\rm d}z} \right |+Z* \left. \frac{{\rm d}r3}{{\rm d}z} \right |=X* \left. \frac{{\rm d}R}{{\rm d}r} \right |[0] +Y* \left. \frac{{\rm d}R}{{\rm d}r} \right | [1] +Z* \left. \frac{{\rm d}R}{{\rm d}r} \right |[2] drdX =Xdzdr1 +Ydzdr2 +Zdzdr3 =XdrdR [0]+YdrdR [1]+ZdrdR [2]
这里的xyz其实代表对rx ry rz角度求导

就有了代码里的

               double dx0dr[] =
                {
                    X*dRdr[0] + Y*dRdr[1] + Z*dRdr[2],
                    X*dRdr[9] + Y*dRdr[10] + Z*dRdr[11],
                    X*dRdr[18] + Y*dRdr[19] + Z*dRdr[20]
                }

后面两个同理
因为 X’=X* /Z*
因此 d X ′ d r ∣ = 1 Z ∗ d X ∗ d r ∣ − X ∗ Z ∗ 2 d Z ∗ d r ∣ \left. \frac{{\rm d}X'}{{\rm d}r} \right |= \frac {1}{Z*} \left. \frac{{\rm d}X*}{{\rm d}r} \right |- \frac {X*}{Z*^2} \left. \frac{{\rm d}Z*}{{\rm d}r} \right | drdX =Z1drdX Z2XdrdZ

d Y ′ d r ∣ = 1 Z ∗ d Y ∗ d r ∣ − Y ∗ Z ∗ 2 d Z ∗ d r ∣ \left. \frac{{\rm d}Y'}{{\rm d}r} \right |= \frac {1}{Z*} \left. \frac{{\rm d}Y*}{{\rm d}r} \right |- \frac {Y*}{Z*^2} \left. \frac{{\rm d}Z*}{{\rm d}r} \right | drdY =Z1drdY Z2YdrdZ

     double dxdr = z*(dx0dr[j] - x*dz0dr[j]);
     double dydr = z*(dy0dr[j] - y*dz0dr[j]);

opencv代码里面 z = 1 Z ∗ z=\frac {1}{Z*} z=Z1 x = X ∗ Z ∗ x=\frac {X*}{Z*} x=ZX

    double dmxdr = (dxdr*cdist*icdist2 + x*dcdist_dr*icdist2 + x*cdist*dicdist2_dr +
                                       k[2]*da1dr + k[3]*(dr2dr + 4*x*dxdr) + (k[8] + 2*r2*k[9])*dr2dr);
    double dmydr = (dydr*cdist*icdist2 + y*dcdist_dr*icdist2 + y*cdist*dicdist2_dr +
                                       k[2]*(dr2dr + 4*y*dydr) + k[3]*da1dr + (k[10] + 2*r2*k[11])*dr2dr);
    dXdYd = dMatTilt*Vec2d(dmxdr, dmydr);
    dpdr_p[j] = fx*dXdYd(0);
    dpdr_p[dpdr_step+j] = fy*dXdYd(1);

剩下的部分跟平移部分的求导一致,不在过多叙述

就此我们的成像模型,对fx,fy,cx,cy,k1,k2,R,T,求导都已完成,后续可以形成雅可比矩阵,带入LM非线性方程进行迭代‘

当然还有另一种方法直接放入Ceres中优化。利用Cerres中的自动求导机制,可以避免求导的过程理解

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值