本文主要参考高翔博士的视觉SLAM十四讲第二版中的7.3章节内容。
文章目录
- 1 对极约束
- 2 本质矩阵E
- 3 单应矩阵
1 对极约束
现在,假设我们从两张图像中得到了一对配对好的特征点,如图7.9
所示(假如后面我们有若干对这样的匹配点,根据这些点的匹配关系,我们就可以恢复处相机的运动),目的是希望求取两帧图像之间的运动:
假设:
- 第一帧和第二帧的运动为 R , t R,t R,t
- 两个相机的中心分别为 O 1 , O 2 O_1,O_2 O1,O2
- I 1 I_1 I1中有一个特征点 p 1 p_1 p1
- I 2 I_2 I2中对应特征点 p 2 p_2 p2
如果 p 1 , p 2 p_1, p_2 p1,p2两个特征点匹配正确,说明它们确实是同一个空间点在两个成像平面上的投影。
那么在以上的假设和匹配正确的基础上,有以下术语来描述它们的关系,连线 O 1 p 1 ⃗ \vec{O_1p_1} O1p1和连线 O 2 p 2 ⃗ \vec{O_2p_2} O2p2在三维空间中会相交于点 P P P:
- 极平面: O 1 , O 2 , P O_1,O_2,P O1,O2,P三个点确定的平面
- 基线: O 1 , O 2 O_1,O_2 O1,O2的连线
- 极点: O 1 , O 2 O_1,O_2 O1,O2的连线与成像平面 I 1 , I 2 I_1,I_2 I1,I2的交点 e 1 , e 2 e_1,e_2 e1,e2
- 极线:极平面与两个像平面 I 1 , I 2 I_1,I_2 I1,I2之间的相交线 l 1 , l 2 l_1,l_2 l1,l2
从代数角度来分析这里的几何关系,假设在第一帧的坐标系下,设
P
P
P的空间位置为:
P
=
[
X
,
Y
,
Z
]
T
(1)
P=[X,Y,Z]^T\tag{1}
P=[X,Y,Z]T(1)
根据针孔相机模型,可知两个像素点
p
1
,
p
2
p_1, p_2
p1,p2的像素位置为:
s
1
p
1
=
K
P
,
s
2
p
2
=
K
(
R
P
+
t
)
(2)
s_1p_1=KP, \quad s_2p_2=K(RP+t)\tag{2}
s1p1=KP,s2p2=K(RP+t)(2)
其中
K
K
K为相机内参矩阵,
R
,
t
R,t
R,t为两个坐标系的相机运动。
由于齐次坐标下,一个向量将等于它自身乘以任意的非零常数,这通常表达一个投影关系,
s
1
p
1
s_1p_1
s1p1和
p
1
p_1
p1成投影关系,它们在齐次坐标的意义下是相等的(尺度意义下的相等),故记作:
s
p
≃
p
sp\simeq p
sp≃p
那么,公式2
的投影关系可写为:
p
1
≃
K
P
,
p
2
≃
K
(
R
P
+
t
)
(3)
p_1\simeq KP, \quad p_2\simeq K(RP+t)\tag{3}
p1≃KP,p2≃K(RP+t)(3)
现取:
x
1
=
K
−
1
p
1
,
x
2
=
K
−
1
p
2
(4)
x_1=K^{-1}p_1, \quad x_2=K^{-1}p_2 \tag{4}
x1=K−1p1,x2=K−1p2(4)
这里
x
1
,
x
2
x_1, x_2
x1,x2是两个像素点的归一化平面上的坐标,代入公式3
得:
x
2
≃
R
x
1
+
t
(5)
x_2\simeq Rx_1+t \tag{5}
x2≃Rx1+t(5)
两边同时左乘
t
∧
t^{\wedge}
t∧得:
t
∧
t
=
0
t^{\wedge}t=0
t∧t=0
t
∧
x
2
≃
t
∧
R
x
1
(6)
t^{\wedge}x_2 \simeq t^{\wedge}Rx_1 \tag{6}
t∧x2≃t∧Rx1(6)
然后两侧再同时左乘
x
2
T
x_2^T
x2T得:
x
2
T
t
∧
x
2
≃
x
2
T
t
∧
R
x
1
(7)
x_2^Tt^{\wedge}x_2 \simeq x_2^Tt^{\wedge}Rx_1 \tag{7}
x2Tt∧x2≃x2Tt∧Rx1(7)
观测等式左侧,
t
∧
x
2
t^{\wedge}x_2
t∧x2是一个与
t
t
t和
x
2
x_2
x2都垂直的向量,它再和
x
2
x_2
x2做内积时,结果是
0
0
0,又由于左侧和右侧是齐次坐标下的尺度意义上的相等,
0
0
0乘以任意非零常数的结果也为
0
0
0,于是可以把
≃
\simeq
≃写出通常的等号,即:
x
2
T
t
∧
R
x
1
=
0
(8)
x_2^Tt^{\wedge}Rx_1=0 \tag{8}
x2Tt∧Rx1=0(8)
然后,结合公式4
,重新代入
p
1
,
p
2
p_1,p_2
p1,p2得:
p
2
T
K
−
T
t
∧
R
K
−
1
p
1
=
0
(9)
p_2^TK^{-T}t^{\wedge}RK^{-1}p_1=0 \tag{9}
p2TK−Tt∧RK−1p1=0(9)
公式8
和公式9
都称为对极约束,几何意义是
O
1
,
P
,
O
2
O_1,P,O_2
O1,P,O2三者共面,对极约束中同时包含了平移和旋转,并习惯把中间的部分记作两个矩阵:基础矩阵
F
F
F(Fundamental Matrix
) 和 本质矩阵
E
E
E(Essential Matrix
):
E
=
t
∧
R
,
F
=
K
−
T
E
K
−
1
,
x
2
T
E
x
1
=
p
2
T
F
p
1
=
0
(10)
E=t^{\wedge}R, \quad F=K^{-T}EK{-1}, \quad x_2^TEx_1=p_2^TFp_1=0 \tag{10}
E=t∧R,F=K−TEK−1,x2TEx1=p2TFp1=0(10)
由于
E
E
E和
F
F
F只相差了相机内参,而内参在SLAM
中一般是已知的,所以实践中往往使用更简单的
E
E
E,以下继续从
E
=
t
∧
R
E=t^{\wedge}R
E=t∧R,来解决相机位姿估计的问题:
- 根据配对点的像素位置求出 E E E
- 根据 E E E求出 R , t R,t R,t
2 本质矩阵E
本质矩阵
E
=
t
∧
R
E=t^{\wedge}R
E=t∧R,是一个3*3
的矩阵,内有9
个未知数,从构造方式来看,本质矩阵有以下特性:
- 本质矩阵是由对极约束定义的,由于对极约束是等式为零的约束,所以对E乘以任意非零常数后,对极约束依然满足,称为 E E E在不同尺度下是等价的,即尺度等价性;
- 根据 E = t ∧ R E=t^{\wedge}R E=t∧R,可证,本质矩阵 E E E的奇异值必定是 [ σ , σ , 0 ] T [\sigma, \sigma, 0]^T [σ,σ,0]T的形式,即本质矩阵的内在性质;
- 由于平移和旋转各有
3
个自由度,但由于尺度等价性,所以 E E E实际有5
个自由度。
E
E
E实际有5
个自由度,理论上最少可以用5
对点来求解
E
E
E,但
E
E
E的内在性质是一种非线性性质,在估计时会带来麻烦,因此,可只考虑它的尺度等价性,使用8
对点来估计
E
E
E,即经典的八点法(Eight point algorithm
),八点法只利用
E
E
E的线性性质,故可在线性代数下求解:
假设一对匹配点,它们的归一化坐标为
x
1
=
[
u
1
,
v
1
,
1
]
T
,
x
2
=
[
u
2
,
v
2
,
1
]
T
x_1=[u_1, v_1, 1]^T, x_2=[u_2, v_2, 1]^T
x1=[u1,v1,1]T,x2=[u2,v2,1]T,根据对极约束中的公式10
,可得:
(
u
2
,
v
2
,
1
)
(
e
1
e
2
e
3
e
4
e
5
e
6
e
7
e
8
e
9
)
(
u
1
v
1
1
)
=
0
(11)
\begin{pmatrix} u_2, v_2, 1 \\ \end{pmatrix} \begin{pmatrix} e_1& e_2 & e_3\\ e_4& e_5 & e_6\\ e_7& e_8 & e_9 \end{pmatrix} \begin{pmatrix} u_1 \\ v_1 \\ 1 \\ \end{pmatrix}=0 \tag{11}
(u2,v2,1)
e1e4e7e2e5e8e3e6e9
u1v11
=0(11)
其中本质矩阵
E
E
E展开,写成向量的形式:
e
=
[
e
1
,
e
2
,
e
3
,
e
4
,
e
5
,
e
6
,
e
7
,
e
8
,
e
9
]
T
e=[e_1, e_2, e_3, e_4, e_5, e_6, e_7, e_8, e_9]^T
e=[e1,e2,e3,e4,e5,e6,e7,e8,e9]T
那么对极约束公式11
可写成与
e
e
e有关的线性形式:
[
u
2
u
1
,
u
2
v
1
,
u
2
,
v
2
u
1
,
v
2
v
1
,
v
2
,
u
1
,
v
1
,
1
]
⋅
e
=
0
(12)
[u_2u_1,u_2v_1,u2,v_2u_1,v_2v_1,v_2,u_1,v_1,1]\cdot e=0 \tag{12}
[u2u1,u2v1,u2,v2u1,v2v1,v2,u1,v1,1]⋅e=0(12)
同理,八点法中的其他7
个点也有相同的表示,8
个点放到一个线性方程中,即:
(
u
2
1
u
1
1
u
2
1
v
1
1
u
2
1
v
2
1
u
1
1
v
2
1
v
1
1
v
2
1
u
1
1
v
1
1
1
u
2
2
u
1
2
u
2
2
v
1
2
u
2
2
v
2
2
u
1
2
v
2
2
v
1
2
v
2
2
u
1
2
v
1
2
1
⋯
⋯
⋯
⋯
⋯
⋯
⋯
⋯
⋯
u
2
8
u
1
8
u
2
8
v
1
8
u
2
8
v
2
8
u
1
8
v
2
8
v
1
8
v
2
8
u
1
8
v
1
8
1
)
(
e
1
e
2
e
3
e
4
e
5
e
6
e
7
e
8
e
9
)
=
0
(13)
\begin{pmatrix} u_2^1u_1^1 & u_2^1v_1^1 & u_2^1 &v_2^1u_1^1 & v_2^1v_1^1 & v_2^1 & u_1^1 & v_1^1 & 1\\ u_2^2u_1^2 & u_2^2v_1^2 & u_2^2 &v_2^2u_1^2 & v_2^2v_1^2 & v_2^2 & u_1^2 & v_1^2 & 1 \\ \cdots & \cdots &\cdots &\cdots &\cdots &\cdots &\cdots &\cdots &\cdots \\ u_2^8u_1^8 & u_2^8v_1^8 & u_2^8 &v_2^8u_1^8 & v_2^8v_1^8 & v_2^8 & u_1^8 & v_1^8 & 1 \end{pmatrix} \begin{pmatrix} e_1 \\ e_2 \\ e_3 \\ e_4 \\ e_5 \\ e_6 \\ e_7 \\ e_8 \\ e_9 \end{pmatrix}=0 \tag{13}
u21u11u22u12⋯u28u18u21v11u22v12⋯u28v18u21u22⋯u28v21u11v22u12⋯v28u18v21v11v22v12⋯v28v18v21v22⋯v28u11u12⋯u18v11v12⋯v1811⋯1
e1e2e3e4e5e6e7e8e9
=0(13)
该线性方程组的系数矩阵由特征点位置构成,大小为8*9
,
e
e
e位于该矩阵中的零空间中,如果系数矩阵是满秩(秩为8
),那么零空间维数为1
,即
e
e
e构成一条线,与本质矩阵
e
e
e的尺度等价性是一致的。
假设8
对匹配点的矩阵满足秩为8
,那么通过公式13
即可求得本质矩阵
E
E
E。
那么接下来的问题就是如何根据已经估算的本质矩阵
E
E
E,恢复出相机的运动姿态
R
,
t
R,t
R,t,这个过程用奇异值分解(SVD
)求解的,假设
E
E
E的SVD
为:
E
=
U
Σ
V
T
(14)
E=U\Sigma V^T \tag{14}
E=UΣVT(14)
其中
U
,
V
U,V
U,V为正交阵,
Σ
\Sigma
Σ为奇异值矩阵,根据
E
E
E的内在性质,可知
Σ
=
d
i
a
g
(
σ
,
σ
,
0
)
\Sigma=diag(\sigma, \sigma, 0)
Σ=diag(σ,σ,0),而在SVD
分解中,对于任意一个
E
E
E,存在两个可能的
R
,
t
R,t
R,t与之对应:
t
1
∧
=
U
R
Z
(
π
2
)
Σ
U
T
,
R
1
=
U
R
Z
T
(
π
2
)
V
T
t
2
∧
=
U
R
Z
(
−
π
2
)
Σ
U
T
,
R
2
=
U
R
Z
T
(
−
π
2
)
V
T
(15)
\begin{gather} t_1^{\wedge}=UR_Z(\frac{\pi}{2})\Sigma U^T, \quad R_1=UR_Z^T(\frac{\pi}{2})V^T \\ t_2^{\wedge}=UR_Z(-\frac{\pi}{2})\Sigma U^T, \quad R_2=UR_Z^T(-\frac{\pi}{2})V^T \end{gather} \tag{15}
t1∧=URZ(2π)ΣUT,R1=URZT(2π)VTt2∧=URZ(−2π)ΣUT,R2=URZT(−2π)VT(15)
其中,
R
Z
(
π
2
)
R_Z(\frac{\pi}{2})
RZ(2π)表示沿
Z
Z
Z轴旋转90°
得到的旋转矩阵,同时,由于
−
E
-E
−E和
E
E
E等价,所以对任意一个
t
t
t取负号,也会得到同样的结果。因此,从
E
E
E分解到
R
,
t
R,t
R,t时,一共存在4
个可能的解。
图7-10
形象地展示了分解本质矩阵得到的4
个解。我们已知空间点在相机(蓝色线)上的 投影(红色点),想要求解相机的运动。在保持红色点不变的情况下,可以画出4
种可能的情况。 不过幸运的是,只有第一种解中
P
P
P在两个相机中都具有正的深度。因此,只要把任意一点代入4
种解中检测该点在两个相机下的深度,就可以确定哪个解是正确的了。
剩下的一个问题是: 根据线性方程解出的
E
E
E, 可能不满足
E
E
E的内在性质,它的奇异值不 一定为
[
σ
,
σ
,
0
]
[\sigma, \sigma, 0]
[σ,σ,0]的形式。这时,我们会刻意地把
Σ
\Sigma
Σ矩阵调整成上面的样子。通常的做法是:对八点 法求得的
E
E
E进行SVD
,会得到奇异值矩阵:
E
=
d
i
a
g
(
σ
1
,
σ
2
,
σ
3
)
E = diag(\sigma1, \sigma2, \sigma3)
E=diag(σ1,σ2,σ3), 不妨设
σ
1
>
σ
2
>
σ
3
\sigma1> \sigma2> \sigma3
σ1>σ2>σ3。取:
E
=
U
d
i
a
g
(
σ
1
+
σ
2
2
,
σ
1
+
σ
2
2
,
0
)
V
T
(16)
E= Udiag(\frac{\sigma1+\sigma2}{2},\frac{\sigma1+\sigma2}{2},0)V^T \tag{16}
E=Udiag(2σ1+σ2,2σ1+σ2,0)VT(16)
这相当于是把求出来的矩阵投影到了
E
E
E所在的流形上。当然, 更简单的做法是将奇异值矩阵取成
d
i
a
g
(
l
,
1
,
0
)
diag(l, 1, 0)
diag(l,1,0),因为
E
E
E具有尺度等价性,所以这样做也是合理的。
3 单应矩阵
除了基本矩阵和本质矩阵,二视图中还有一种常见的矩阵:单应矩阵
H
H
H(Humography
),它描述了两个平面之间的映射关系。
单应矩阵通常描述处于共同平面上的一些点在两张图像之间的变换关系,设图像 I 1 I_1 I1 和 I 2 I_2 I2 有一对匹配好的特征点 p 1 p_1 p1和 p 2 p_2 p2,这个特征点落在平面 P P P上,设这个平面满足方程:
n T P + d = 0 (17) n^TP+d=0 \tag{17} nTP+d=0(17)
也即:
−
n
T
P
d
=
1
(18)
\frac{-n^TP}{d}=1 \tag{18}
d−nTP=1(18)
然后,结合公式2
和公式3
,得:
p
2
≃
K
(
R
P
+
t
)
≃
K
(
R
P
+
t
)
⋅
−
n
T
P
d
≃
K
(
R
−
t
n
T
d
)
P
≃
K
(
R
−
t
n
T
d
)
K
−
1
p
1
\begin{gather} p_2\simeq K(RP+t) \\ \simeq K(RP+t)\cdot\frac{-n^TP}{d} \\ \simeq K(R-\frac{tn^T}{d})P \\ \simeq K(R-\frac{tn^T}{d})K^{-1}p_1 \end{gather}
p2≃K(RP+t)≃K(RP+t)⋅d−nTP≃K(R−dtnT)P≃K(R−dtnT)K−1p1
于是,可得到一个直接描述图像坐标
p
1
p_1
p1和
p
2
p_2
p2之间的变换,把中间这部分定义为单应矩阵
H
H
H,即:
p
2
≃
H
p
1
(19)
p_2\simeq Hp_1 \tag{19}
p2≃Hp1(19)
它的定义与旋转、平移及平面的参数有关。与基础矩阵
F
F
F类似,单应矩阵
H
H
H也是一个3*3
的矩阵,求解时的思路和F
类似, 同样可以先根据匹配点计算H
,然后将它分解以计算旋转和平移。把上式展开,即:
(
u
2
,
v
2
,
1
)
≃
(
h
1
h
2
h
3
h
4
h
5
h
6
h
7
h
8
h
9
)
(
u
1
v
1
1
)
(20)
\begin{pmatrix} u_2, v_2, 1 \\ \end{pmatrix}\simeq \begin{pmatrix} h_1& h_2 & h_3\\ h_4& h_5 & h_6\\ h_7& h_8 & h_9 \end{pmatrix} \begin{pmatrix} u_1 \\ v_1 \\ 1 \\ \end{pmatrix} \tag{20}
(u2,v2,1)≃
h1h4h7h2h5h8h3h6h9
u1v11
(20)
这里仍旧是尺度意义下的相等,所以H矩阵也可以乘以任意非零常数,实际处理可令h_9=1(在它取非零值时),然后根据第3行,去掉这个非零因子,可得:
u
2
=
h
1
u
1
+
h
2
v
1
+
h
3
h
7
u
1
+
h
8
v
1
+
h
9
v
2
=
h
4
u
1
+
h
5
v
1
+
h
6
h
7
u
1
+
h
8
v
1
+
h
9
\begin{gather} u_2=\frac{h_1u_1+h_2v_1+h_3}{h_7u_1+h_8v_1+h_9} \\ v_2=\frac{h_4u_1+h_5v_1+h_6}{h_7u_1+h_8v_1+h_9} \end{gather}
u2=h7u1+h8v1+h9h1u1+h2v1+h3v2=h7u1+h8v1+h9h4u1+h5v1+h6
整理可得:
u
2
=
h
1
u
1
+
h
2
v
1
+
h
3
−
h
7
u
1
u
2
−
h
8
v
1
u
2
v
2
=
h
4
u
1
+
h
5
v
1
+
h
6
−
h
7
u
1
v
2
−
h
8
v
1
v
2
(21)
\begin{gather} u_2=h_1u_1+h_2v_1+h_3-h_7u_1u_2-h_8v_1u_2 \\ v_2=h_4u_1+h_5v_1+h_6-h_7u_1v_2-h_8v_1v_2 \end{gather} \tag{21}
u2=h1u1+h2v1+h3−h7u1u2−h8v1u2v2=h4u1+h5v1+h6−h7u1v2−h8v1v2(21)
这样,一组匹配点对就可以构造出两项约束(事实上有三个约束,但是因为线性相关, 只取前两个),于是自由度为8
的单应矩阵可以通过4
对匹配特征点算出(在非退化的情况下, 即这些特征点不能有三点共线的情况),即求解以下的线性方程组(当
h
9
=
0
h_9=0
h9=0时, 右侧为零):
(
u
1
1
v
1
1
1
0
0
0
−
u
1
1
u
2
1
−
v
1
1
u
2
1
0
0
0
u
1
1
v
1
1
1
−
u
1
1
v
2
1
−
v
1
1
v
2
1
u
1
2
v
1
2
1
0
0
0
−
u
1
2
u
2
2
−
v
1
2
u
2
2
0
0
0
u
1
2
v
1
2
1
−
u
1
2
v
2
2
−
v
1
2
v
2
2
u
1
3
v
1
3
1
0
0
0
−
u
1
3
u
2
3
−
v
1
3
u
2
3
0
0
0
u
1
3
v
1
3
1
−
u
1
3
v
2
3
−
v
1
3
v
2
3
u
1
4
v
1
4
1
0
0
0
−
u
1
4
u
2
4
−
v
1
4
u
2
4
0
0
0
u
1
4
v
1
4
1
−
u
1
4
v
2
4
−
v
1
4
v
2
4
)
(
h
1
h
2
h
3
h
4
h
5
h
6
h
7
h
8
)
=
(
u
2
1
v
2
1
u
2
2
v
2
2
u
2
3
v
2
3
u
2
4
v
2
4
)
(22)
\begin{pmatrix} u_1^1 & v_1^1 & 1 & 0 & 0 & 0 & -u_1^1u_2^1 & -v_1^1u_2^1\\ 0 & 0 & 0 & u_1^1 & v_1^1 & 1 & -u_1^1v_2^1 & -v_1^1v_2^1 \\ u_1^2 & v_1^2 & 1 & 0 & 0 & 0 & -u_1^2u_2^2 & -v_1^2u_2^2\\ 0 & 0 & 0 & u_1^2 & v_1^2 & 1 & -u_1^2v_2^2 & -v_1^2v_2^2 \\ u_1^3 & v_1^3 & 1 & 0 & 0 & 0 & -u_1^3u_2^3 & -v_1^3u_2^3\\ 0 & 0 & 0 & u_1^3 & v_1^3 & 1 & -u_1^3v_2^3 & -v_1^3v_2^3 \\ u_1^4 & v_1^4 & 1 & 0 & 0 & 0 & -u_1^4u_2^4 & -v_1^4u_2^4\\ 0 & 0 & 0 & u_1^4 & v_1^4 & 1 & -u_1^4v_2^4 & -v_1^4v_2^4 \end{pmatrix} \begin{pmatrix} h_1 \\ h_2 \\ h_3 \\ h_4 \\ h_5 \\ h_6 \\ h_7 \\ h_8 \end{pmatrix}=\begin{pmatrix} u_2^1 \\ v_2^1 \\ u_2^2 \\ v_2^2 \\ u_2^3 \\ v_2^3 \\ u_2^4 \\ v_2^4 \end{pmatrix} \tag{22}
u110u120u130u140v110v120v130v140101010100u110u120u130u140v110v120v130v1401010101−u11u21−u11v21−u12u22−u12v22−u13u23−u13v23−u14u24−u14v24−v11u21−v11v21−v12u22−v12v22−v13u23−v13v23−v14u24−v14v24
h1h2h3h4h5h6h7h8
=
u21v21u22v22u23v23u24v24
(22)
这种做法把
H
H
H矩阵看成了向量,通过解该向擞的线性方程来恢复
H
H
H,又称直接线性变换法(Direct Linear Transform, DLT
)。与本质矩阵相似,求出单应矩阵后需要对其进行分解,才可以得到相应的
R
,
t
R,t
R,t,分解的方法包括数值法和解析法。与本质矩阵相似的分解类似,单应矩阵的分解同样会返回4
组解,同时,可计算出它们分别对应的场景点所在平面的法向量。如果已知成像的地图点的深度全为正值(即在相机前方),则又可排除两组解,最后仅剩两组解,这时需要通过更多的先验信息进行判断。通常,可通过假设已知场景平面的法向量来解决,如场景平面与相机平面平行,那法向量
n
n
n的理论值为
1
T
1^T
1T。
单应性在SLAM
中具有重要意义。 当特征点共面或者相机发生纯旋转时,基础矩阵的自由度下降,这就出现了所谓的退化(degenerate
)。现实中的数据总包含一些噪声,这时如果继续使用八点法求解基础矩阵,基础矩阵多余出来的自由度将会主要由噪声决定。为了能够避免退化现 象造成的影响,通常我们会同时估计基础矩阵F
和单应矩阵H
,选择重投影误差比较小的那个作为最终的运动估计矩阵(详细的案例可参考ORB-SLAM2中单目初始化Initializer)。
⭐️👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍🌔