内外参求导详解
参考资料
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+k1∗y2+k2∗r4) [ 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.
{fx∗xˇ+cx=ufy∗yˇ+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′=r7∗X+r8∗Y+r9∗Z+t3r1∗X+r2∗Y+r3∗Z+t1Y′=r7∗X+r8∗Y+r9∗Z+t3r4∗X+r5∗Y+r6∗Z+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+k1∗r2+k2∗r4)∗X′yˇ=(1+k1∗r2+k2∗r4)∗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=fx∗dk1dxˇ
=fx∗r2∗X′
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=fy∗dk1dxˇ
=fy∗r2∗Y′
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=fx∗dk1dxˇ
=fx∗r4∗X′
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=fy∗dk1dxˇ
=fy∗r4∗Y′
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′=r7∗X+r8∗Y+r9∗Z+t3r1∗X+r2∗Y+r3∗Z+t1=Z′′X′′Y′=r7∗X+r8∗Y+r9∗Z+t3r4∗X+r5∗Y+r6∗Z+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=r7∗X+r8∗Y+r9∗Z+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=r7∗X+r8∗Y+r9∗Z+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=Z′Y′
接着我们 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
=2∗X′∗dtdX′
+2∗Y′∗dtdY′
接着我们 畸变函数 求导
k
m
=
1
+
k
1
∗
r
2
+
k
2
∗
r
4
km=1+k1∗r^2+k2∗r^4
km=1+k1∗r2+k2∗r4
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 =k1∗dtdr2 +2∗k2∗r2dtdr2
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=fx∗dtdxˇ
=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=fy∗dtdyˇ
=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+(1−cos(theta))∗r∗rT+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)∗thetax−sin(theta)∗thetax∗r∗rT+(1−cos(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∗=r1∗X+r2∗Y+r3∗Z+t1Y∗=r4∗X+r5∗Y+r6∗Z+t2Z∗=r7∗X+r8∗Y+r9∗Z+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∗ =X∗dxdr1 +Y∗dxdr2 +Z∗dxdr3 =X∗drdR [0]+Y∗drdR [1]+Z∗drdR [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∗ =X∗dydr1 +Y∗dydr2 +Z∗dydr3 =X∗drdR [0]+Y∗drdR [1]+Z∗drdR [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∗
=X∗dzdr1
+Y∗dzdr2
+Z∗dzdr3
=X∗drdR
[0]+Y∗drdR
[1]+Z∗drdR
[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′
=Z∗1drdX∗
−Z∗2X∗drdZ∗
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′ =Z∗1drdY∗ −Z∗2Y∗drdZ∗
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=Z∗1 x = X ∗ Z ∗ x=\frac {X*}{Z*} x=Z∗X∗
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中的自动求导机制,可以避免求导的过程理解