본문 바로가기

Engineering

[SLAM] Direct Sparse Odometry (DSO) 논문 및 코드 리뷰 (1)

본 포스트에서는 direct method 기반의 VO 알고리즘으로 유명한 DSO 논문을 리뷰한다. DSO 코드를 분석하면서 논문에서는 생략된 디테일한 부분들이 굉장히 많다는 것을 알게되었고 이미 잘 정리된 다른 분들의 자료를 참고하여 수식 유도부터 코드 리뷰까지 포함하는 정리본을 작성하게 되었다.

 

1. Initialization

1.1 Calibration

direct method는 밝기오차를 최적화하여 카메라의 포즈를 추정하기 때문에 이미지의 밝기 차이에 민감하다. SLAM에서 주로 사용하는 머신비전 카메라는 일반적으로 이미지의 밝기 변화에 따라 노출시간을 자동으로 조절하므로(auto exposure) 노출시간에 따른 밝기 변화가 심한 경우 direct method는 정상적으로 작동하지 않을 수 있다. 아래는 [13] 논문의 예시이다.

Photometric Calibration (위) before (아래) after

1.1.1 Photometric Calibration

따라서 DSO 논문에서는 VO 알고리즘에서 일반적으로 수행하는 geometric calibration과 더불어 photometric calibration이라는 방법을 수행하였다. photometric calibration은 카메라의 노출시간(exposure time), 비네팅(vignetting), 카메라 반응함수 등을 고려하여 direct method가 지속적으로 밝기오차를 최적화할 수 있도록 한다. 자세한 공식은 다음과 같다.

Ii(x)=G(tiV(x)Bi(x))Ii(x):=tiBi(x)=G1(Ii(x))V(x)

- G() : 카메라 노출시간에 따른 반응함수 (response function)

- ti : 노출시간 (exposure time)

- V() : 비네팅 (vignetting)

- B() : 복사 조도 (irradiance)

- I() : 관측된 픽셀 밝기

- I() : 캘리브레이션 된 픽셀 밝기

 

B() 에 대한 자세한 설명은 링크1, 링크2를 참고하면 된다. 우선 같은 장소에 대해 다른 노출시간을 적용하면서 카메라의 노출시간에 따른 반응함수 G()와 복사 조도 B()을 추정한다. 해당 방법은 DSO Photometric Calibration paper 를 참조하여 작성하였다. 

Response Calibration. Where U := G^-1

다음으로 V()을 추정한다. 벽에 AR marker를 설치하여 카메라의 포즈를 추정하면서 이미지 중앙을 기점으로 주변의 어두워지는 정도를 함수로 예측한다.

DSO는 위와 같은 photometric calibration 과정을 거쳐서 노출시간 변화에 상대적으로 invarant한 이미지 영상 I()을 사용하였다.  

DSO's Photometric Calibration

위 그림에서 중간의 그래프를 보면 이미지 시퀀스에 따른 노출시간의 변화를 의미한다. 값을 보면 동일한 데이터 내에서도 0.018ms ~ 10.5ms까지  최대 500배 이상의 노출시간 변화가 발생하는 것을 알 수 있다. DSO는 이러한 카메라 노출시간 변화에 따른 밝기 변화를 에러함수로 모델링하지 않고 캘리브레이션함으로써 direct method의 포즈 추정 성능을 대폭 상승시켰다. 

 

1.2 Error Function Formulation

다음과 같이 3차원 공간 상의 한 점 X1과 2차원 이미지 평면 상의 한 점 p1은 다음과 같은 관계를 가진다. 

p1=π(X1)=Kρ1X1

X1=π1(p1)=K1/ρ1p1

 

- {Ci} : 카메라 좌표계

- X1 : 3차원 공간 상의 한 점

- p1 : 2차원 이미지 평면 상의 한 점

- K : 카메라 내부 파라미터 (3x3 행렬)

ρ1=1/Z1 : 깊이 값의 역수 (inverse depth)

- K=[fx0cx0fycy001], K1=[fx10fx1cx0fy1fy1cy001]

 

1.2.1 inverse depth parameterization

DSO에서는 3차원 점 X1를 표현할 때 3개의 파라미터 [X1,Y1,Z1]을 사용하는 것이 아닌 1개의 파라미터 (Z1의 역수 ρ1)만 사용한다. 이를 통해 이미지 평면 상의 픽셀 p1의 위치만 알고 있으면 오직 inverse depth ρ1를 사용하여 3차원 점을 완벽하게 표현할 수 있다. 이는 최적화를 수행할 때 1개의 파라미터만 추정하면 되므로 계산 상의 이점을 지닌다. 

 

실제 inverse depth 관련 논문[14]에서는 inverse depth를 사용하면 기존 3차원 공간의 3개 파라미터 대신 6개의 파라미터를 사용한다.

[X,Y,Z][x,y,z,ρ,θ,ϕ]

하지만, DSO 논문에서는 ρ만 차용하여 사용한 것으로 추정된다. 이 때, inverse depth의 성질에 따라 ρ 값은 레퍼런스 프레임의 ρ 값으로만 제한된다. inverse depth를 통해 얻는 이점에 대한 자세한 내용은 해당 블로그를 참조하면 된다.

 

 


 

 

다음으로 카메라가 exp(ξ21)SE(3)만큼 움직여서 {C1}{C2}으로 이동한 경우를 생각해보자. 

- Ti : 카메라의 3차원 포즈 (4x4 행렬)

- ξ21R6 : C1, C2 카메라 간 상대 포즈 변화량 (twist) (6차원 벡터)

- ξ21se(3) : hat 연산자가 적용된 skew symmetric matrix of twist (lie algebra) (4x4 행렬)

- exp(ξ21)SE(3) : C1, C2 카메라 간 상대 포즈 (lie group) (4x4 행렬)

 

X1을 두 번째 카메라 위에 프로젝션한 점 p2는 다음과 같은 공식으로 표현할 수 있다. 
p2=π(exp(ξ21)X1)=π(exp(ξ21)π1(p1))

 

위 식을 inverse depth ρ1, 회전행렬 R과 이동량 t으로 나타내면 논문의 Eq (5) 공식이 된다.

p2=π(Rπ1(p1,ρ1)+t)

- [Rt01]:=T2T11

 

direct method는 밝기 오차 (photometric error)를 에러함수로 사용하므로 픽셀의 밝기 값의 차이를 구해야 한다. 이 때, DSO는 카메라의 exposure time을 고려하여 밝기 오차를 조정하는 파라미터를 사용한다. 이를 photometric calibration parameters (a,b)라고 한다. 또는 affine brightness transfer parameters (a,b)라고도 부른다.

I2(p2)=exp(a)I1(p1)+b

 

- a=tjexp(aj)tiexp(ai)

- b=bibj

- Ii(pj) : i번째 이미지에서 j번째 점의 밝기 (grayscale) (0~255)

- ti : i번째 이미지가 촬영된 순간의 exposure time ([ms] 단위)

- a,b : 두 이미지 간 exposure time을 고려하여 이미지 밝기를 조절하는 파라미터

 

이 때, 두 점의 픽셀 밝기 차이를 에러(error, residual)로 설정한다.

r(p1)=I2(p2)exp(a)I1(p1)b

DSO는 한 점에서 밝기 차이만을 고려하지 않고 한 점 주위의 총 8개의 점들 patch 밝기 차이를 고려한다. 위 이미지와 같이 1개의 점이 생략된 이유는 성능에 크게 영향을 주지 않으면서 4번의 float 연산을 한 번에 계산할 수 있는 SSE2 레지스터를 사용하여 속도를 가속하기 위함이다.

 

patch를 고려하고 weighting 함수 + huber 함수까지 적용한 에러함수 Ep는 다음과 같다. 이 때, patch는 weighted SSD (sum of squared distance)를 사용하여 계산하였다. 

Ep=p1NpwpI2(p2)exp(a)I1(p1)bγ

- Np : 중앙 점과 주위의 8개 점들 patch

 

위 공식을 풀어서 다시 표현하면 논문의 Eq (4) 공식이 된다.

Ep=p1Npwp(I2(p2)b2)t2expa2t1expa1(I1(p1)b1)γ=p1NpwpH(r(p1))

 

임의의 weighting 함수 wp는 다음과 같이 정의되고 이미지 gradient가 큰 포인트의 경우 down weighting 된다. (논문의 Eq (7) 공식)

wp=c2c2+I(p)22

 

huber function H(r)는 다음과 같이 정의되고 DSO의 경우 σ=9의 상수값을 가진다.

H(r)={r2/2,|r|<σσ(|r|σ/2)|r|σ

 

위 식을 컴팩트하게 표현하기 위해 wh={1|r|<σσ/|r||r|σ를 사용하면 아래와 같이 나타낼 수 있다. 

 

H(r)=whr2(1wh/2)

 

이를 두 카메라 이미지 상의 모든 점들에 대해 에러를 계산하면 아래와 같다. (논문의 Eq (8) 공식)

Ephoto:=iFpPijobs(p)Ep

- F : 모든 프레임

- Pi : i번째 프레임의 모든 포인트

- obs(p) : 관측된 모든 포인트

1.3 Gauss-Newton Optimization

huber function까지 적용한 에러함수 H(r)은 다음과 같다. 

H(r)=whr2(1wh/2)

이 때, DSO에서 H(r)wh/2 부분은 상대적으로 크기가 작으므로 생략하였다. 

H(r)=whr2(1wh/2)whr2

 

위 함수를 least square method로 최적화하기 위해서 H(r)가 squared form이라고 가정하면 f(x)Tf(x)=H(r)를 만족하는 f(x)를 생각할 수 있고 이 때, f(x)가 최소이면 f(x)의 제곱인 H(r) 역시 최소가 된다. 

 

f(x)Tf(x)=H(r)

f(x)=wh r=wh(I2(p2)exp(a)I1(p1)b)

 

따라서 해당 문제를 f(x) 최소화 문제로 변경할 수 있고 이 때 state variable x는 다음과 같다. 

x=[ ρ1(1),,ρ1(N),δξT,a,b ](N+8)×1T

 

- ρ1(i) : 1번 이미지에서 i번째 inverse depth 값 (N개)

- δξ : 두 카메라 간 상대 포즈 변화량 (twist) (6차원 벡터) (6개)

- a,b : 두 이미지 간 exposure time을 고려하여 이미지 밝기를 조절하는 파라미터 (2개)

 

f(x)는 비선형 함수이므로 non-linear least square method를 사용하여 최소화해야 한다. 이를 위해 Gauss-Newton(GN) method가 사용된다. GN은 반복적으로(iterative)  f(x+Δx) 값이 감소하는 Δx를 구하여 비선형 함수를 최적화하는 방법 중 하나이다.

1.3.1. Gauss-Newton method

자세한 과정은 다음과 같다.

1. f(x+Δx)를 1차 테일러 전개하면 다음과 같이 근사할 수 있다. 

f(x+Δx)f(x)+JΔx

2. 12f2(x+Δx)의 최소값을 구한다고 가정하면 해당 함수의 1차 미분이 0이 되는 Δx를 구하면 그 점이 최소가 된다. 

f(x+Δx)Tf(x+Δx)(f(x)+JΔx)T(f(x)+JΔx)

=f(x)Tf(x)+2f(x)TJΔx+ΔxTJTJΔx

=c+2bΔx+ΔxTHΔx

3. 12f2(x+Δx)의 최소값은 다음과 같이 구할 수 있다. 

12f2(x+Δx)Δx=f(x+Δx)f(x+Δx)Δx(f(x)+JΔx)J=0

4. 위 식을 정리하면 다음과 같은 식이 나오고 

JTJΔx=JTf(x)

5. 이를 컴팩트하게 표현하기 위해 치환하면 다음과 같다. 

 HΔx=b

- H=JTJ

- b=JTf(x)

6. 위 식을 계산하면 최적의 Δx를 계산할 수 있고 이를 기존의 state variable에 업데이트 해준다.

Δx=H1b

xx+Δx

1.4 Jacobian Derivation

앞서 언급한 GN 방법을 사용하여 최적화를 하기 위해서는 Jacobian J 계산이 선행되어야 한다.

f(x+Δx)f(x)+JΔx

 

f(x)의 state variable x를 다음과 같이 정의했으므로 총 N+8개의 변수에 대한 Jacobian을 계산해야 한다. (idepth(N), relative pose(6), photometric param(2))

x=[ ρ1(1),,ρ1(N),δξT,a,b ](N+8)×1T

 

1.4.1 Derivation of photometric parameters

photometric param a,b에 대한 Jacobian은 다음과 같이 계산할 수 있다.

f(x)a=whexp(a)I1(p1)

f(x)b=wh

 

- f(x)=wh r=wh(I2(p2)exp(a)I1(p1)b)

 

1.4.2 Derivation of relative pose

에러함수 f(x)가 카메라 포즈 변화량 δξ에 따라서 어떻게 변하는 지 계산하기 위해 f(x)δξ를 구해야 한다. 다음과 같이 Jacobian 연쇄법칙을 사용하여 f(x)δξ를 유도할 수 있다. 이를 위해 개별 Jacobian들을 모두 구해야 한다.

 

f(x)δξ=f(x)p2p2δξ=f(x)p2p2X2X2δξ

 

Ix,Iyp2에서 각각 x,y 방향의 이미지 gradient라고 하면 f(x)p2는 다음과 같이 구할 수 있다. 

f(x)p2=whI2(p2)p2=wh[ Ix  Iy ]

 

다음으로 p2δξ=p2X2X2δξ를 구해보면, 우선 p2X2는 2차원 이미지 평면 상의 점 p2와 3차원 공간 상의 점 X2 사이의 관계를 의미하므로 두 점 사이에는 다음과 같은 공식이 성립한다.

[u2v21]=ρ2[fx0cx0fycy001][X2Y2Z2]

 

- ρ2=1Z2,X2=[ X2 Y2 Z2 ]T

 

위 식을 통해 u2,v2,X2,Y2,Z2 관계식을 도출할 수 있고 이를 토대로 p2X2를 구해보면 아래와 같다. 

p2X2=[u2X2u2Y2u2Z2v2X2v2Y2v2Z2]=[ρ2fx0ρ22fxX20ρ2fyρ22fyY2]

 

다음으로 p2δξ=p2X2X2δξ에서 X2δξ를 구하기 전 δξ에 대해 알아보면 δξR6는 3차원 카메라의 포즈 변화량을 의미하고 twist라고 부른다. δξse(3)는 twist에 hat operator를 적용하여 skew symmetric matrix로 변환한 값으로써 lie algebra of SE(3)라고 부른다. 위 값에 exponential mapping을 적용하면 4x4 행렬의 3차원 포즈 ΔTSE(3)로 변환할 수 있다. 이를 lie group of SE(3)라고 부른다. 자세하게 표현하면 다음과 같다. 

δξ=[δvδw]=[δvxδvyδvzδwxδwyδwz]R6

δξ=[δwδv0T0]se(3)R4×4

ΔT=exp(δξ)=[ΔRΔt01]SE(3)R4×4

 

이를 바탕으로 X2δξ를 유도해보면 다음과 같다. 

X2δξ=limδξ0exp(δξ)X2X2δξlimδξ0(I+δξ)X2X2δξ=limδξ0δξX2δξ=limδξ0[δwδv0T0][X21]δξ=[IX20T0T]

X2δξ=[ I X2 ]=[1000Z2Y2010Z20X2001Y2X20]in non-homogeneous form

지금까지 유도한 공식들을 결합하여 하나의 Jacobian of relative pose로 표현하면 다음과 같다. 

f(x)δξ=f(x)p2p2δξ=f(x)p2p2X2X2δξ

f(x)p2=whI2(p2)p2=wh[ Ix  Iy ]

p2δξ=[ρ2fx0ρ22fxX2ρ22fxX2Y2fx+ρ22fxX22ρ2fxY20ρ2fyρ22fyY2fyρ22fyY22ρ22fyX2Y2ρ2fyX2]=[ρ2fx0ρ22fxu2fxu2v2fx+fxu22fxv20ρ2fyρ22fyv2fyfyv22fyu2v2fyu2]

- u=X2Z2,v=Y2Z2in the normalized coordinate. 

f(x)δξ=wh[Ixρ2fxIyρ2fyρ2(Ixfxu2+Iyfyv2)Ixfxu2v2Iyfy(1+v22)Ixfx(1+u22)+Iyfyu2v2Ixfxv2+Iyfyu2]T

 

1.4.3 Derivation of inverse depth

마지막으로 Jacobian of inverse depth f(x)ρ1를 유도해야 한다. f(x)ρ1는 다음과 같이 연쇄적인 Jacobian의 곱으로 표현할 수 있다. 

f(x)ρ1=f(x)p2p2ρ1=f(x)p2p2X2X2ρ1

 

이 때, f(x)p2p2X2는 이전에 미리 구했으므로 X2ρ1만 추가적으로 구하면 된다. 

f(x)p2=whI2(p2)p2=wh[ Ix  Iy ]

p2X2=[u2X2u2Y2u2Z2v2X2v2Y2v2Z2]=[ρ2fx0ρ22fxX20ρ2fyρ22fyY2]

X2ρ1=?

 

p2ρ1=p2X2X2ρ1에서 X2ρ1는 3차원 공간 상의 점 X2와 inverse depth ρ1 사이의 관계를 나타내므로 이를 공식으로 표현하면 다음과 같다. 
X2=R21(K1X1ρ1)+t21

 

위 관계식을 사용하여 X2ρ1를 구해보면 다음과 같다.

X2ρ1=R21(K1X1ρ12)=(X2t21)ρ1=ρ11[ X2tx  Y2ty  Z2tz ]T

 

p2ρ1는 다음과 같이 구할 수 있다.

p2ρ1==ρ11ρ2[fx(u2tztx)fy(v2tzty)]

 

 

따라서 f(x)ρ1=f(x)p2p2ρ1=f(x)p2p2X2X2ρ1에서 f(x)ρ1는 다음과 같이 구할 수 있다. 

f(x)ρ1=whρ11ρ2(Ixfx(txu2tz)+Iyfy(tyv2tz))

 

정리해보면 Initialization에서 사용하는 Jacobian들은 아래와 같다. 

idepth(N)

f(x)ρ1=whρ11ρ2(Ixfx(txu2tz)+Iyfy(tyv2tz))

pose(6)

f(x)δξ=wh[Ixρ2fxIyρ2fyρ2(Ixfxu2+Iyfyv2)Ixfxu2v2Iyfy(1+v22)Ixfx(1+u22)+Iyfyu2v2Ixfxv2+Iyfyu2]T

photometric(2)

f(x)a=whexp(a)I1(p1)

f(x)b=wh

 

모든 Jacobian을 유도했으면 아래와 같이 합쳐준다.

J=[ Jρ  Jy ]1×(N+8)T

 

- y=[ δξT a b ]

- Jρ=[ f(x)ρ1(1)    f(x)ρ1(N) ]1×N for xρ

- Jy=[ f(x)δξ  f(x)a  f(x)b ]1×8  for xy

 

최종적으로 위 Jacobian J를 사용하여 state variable x=[ ρ1(1),,ρ1(N),δξT,a,b ](N+8)×1T=[ xρ xy ]T를 업데이트 할 수 있다. 

 

1.5 Solving the incremental equation (Schur Complement)

Jacobian까지 모두 유도를 마쳤으면 GN 방법을 사용하여 아래와 같은 최적화를 반복해서 풀어야 한다. 

하지만 실제 위 최적화 공식을 반복적으로 풀면 매우 느린 속도로 인해 정상적으로 pose tracking을 할 수 없다. 이는 H1를 계산할 때 매우 큰 H 행렬의 특성 상 역함수를 구하는데 매우 많은 시간이 소모되기 때문이다. 해당 공식을 조금 더 자세히 표현해보면 다음과 같다. 

HΔx=b[HρρHρyHyρHyy][ΔxρΔxy]=[bρby]

 

- y=[ δξT a b ]

- Hρρ=JρTJρ

- Hρy=JρTJy

- Hyρ=JyTJρ

- Hyy=JyTJy

- bρ=JρTf(x)

- by=JyTf(x) : (-)부호를 b 안으로 삽입함

 

Hessian Matrix H를 전개하면 내부 구조는 다음과 같다.

일반적인 경우 3차원 점의 개수가 카메라 pose보다 훨씬 많으므로 다음과 같은 거대한 행렬이 생성된다. 따라서 역행렬을 계산할 때 매우 큰 연산시간이 소요되므로 이를 빠르게 계산할 수 있는 다른 방법이 필요하다. 

이 때, 일반적으로 Schur Complement를 사용하여 computational cost를 낮추어 빠르게 계산한다.

[HρρHρyHyρHyy][ΔxρΔxy]=[bρby]

 

Schur Complement를 위해 양변에 아래와 같은 특수한 형태의 행렬을 곱해준다.

[I0HyρHρρ1I][HρρHρyHyρHyy][ΔxρΔxy]=[I0HyρHρρ1I][bρby]

[HρρHρy0HyρHρρ1Hρy+Hyy][ΔxρΔxy]=[bρHyρHρρ1bρ+by]

 

위 식을 전개해서 ΔxyΔxρ를 순차적으로 계산할 수 있다. 위 식을 전개하면  Δxy만 존재하는 항이 유도된다.

 

1.5.1 Forward Substitution

Δxy=(HyyHsc)1(bybsc)

- Hsc=HyρHρρ1Hρy

- bsc=HyρHρρ1bρ

 

위 식을 통해 Δxy를 먼저 계산한 후 이를 토대로 Δxρ를 계산한다. 이는 H1을 구하는 것보다 더욱 빠르게 최적화 공식을 풀 수 있다.

 

1.5.2 Backward Substitution

Δxρ=Hρρ1(bρHρyΔxy)

 

inverse depth와 관련있는 항인 Hρρ는 NxN 크기의 대각행렬(diagonal matrix)이므로 쉽게 역행렬을 구할 수 있다. 따라서 Hsc,bsc 또한 다음과 같이 비교적 간단하게 계산할 수 있다. 

Hsc=HyρHρρ1Hρy=1JρJρT(JρTJy)TJρTJy

bsc=HyρHρρ1bρ=1JρJρT(JρTJy)TJρTf(x)

 

최종적으로 damping 계수 λ 기반의 Levenberg-Marquardt (LM) 방법을 사용하여 Optimization을 수행한다. 

(H+λI)Δx=b

 

2. Frames

2.1. Pose Tracking

다음으로 pose tracking을 수행하면서 키프레임을 생성하는 알고리즘은 다음과 같다. 새로운 이미지가 들어오면 해당 이미지에 해당하는 3차원 포즈를 아직 모르기 때문에 이를 예측하기 위해 DSO는 가장 최근 두 프레임 {Ci1,2}과 직전의 키프레임 {Ckf}의 정보를 사용한다.

 

두 프레임(Ti1,i2)과 한 개의 키프레임(Ti1,kf)을 참조하여 이들의 상대 포즈를 구한 후 정지, 직진, 후진, 회전 등 다양한 케이스에 대한 밝기 오차를 구한다. 이 때, 가장 높은 이미지 피라미트(가장 작은 크기 이미지)부터 가장 낮은 이미지 피라미드(원본 크기)까지 순차적으로 밝기 오차를 구하는 coarse-to-fine 방법을 통해 현재 프레임의 3차원 포즈를 구한다. 

각 포즈 후보마다 순차적으로 밝기 오차(photometric error)를 계산하고 이를 최적화하여 최적의 포즈를 구한다. 그리고 최적의 포즈에서 다시 한 번 밝기 오차를 구한 후(resNew) 이전 오차(resOld)와 비교하여 충분히 오차가 감소하였는지 판단한다. 충분히 오차가 감소하였다면 다른 포즈 후보를 고려하지 않고 루프를 탈출한다. (coarseTracker::trackNewestCoarse() 함수 참조)

 

여러 포즈 후보들 중 하나의 포즈를 선택한 후 밝기 오차는 다음과 같이 구할 수 있다.

r=I2(p2)exp(a)(I1(p1)b0)b

- p2=π(exp(ξ21)X1)=π(exp(ξ21)π1(p1))

 

이 때, 한 점의 밝기 오차만 계산하는 것이 아닌 주변 8개 점들의 밝기 오차를 모두 계산한다. 다음으로 해당 비선형 함수를 최적화하기 위해 Jacobian을 계산한다.

photometric(2)

ra=exp(a)I1(b0p1)

rb=1

pose(6)

rδξ=[Ixρ2fxIyρ2fyρ2(Ixfxu2+Iyfyv2)Ixfxu2v2Iyfy(1+v22)Ixfx(1+u22)+Iyfyu2v2Ixfxv2+Iyfyu2]T

 

해당 Jacobian을 사용하여 H,b를 각각 계산한다.

H=JTJ

b=JTr

- J=[ f(x)δξ f(x)a f(x)b ]8×1

 

H,b를 각각 계산한 다음 Levenberg-Marquardt (LM) 방법을 통해 반복적으로 에러를 감소시킨다. 초기 λ=0.01로 설정한다.

(H+λI)Δx=b

xx+Δx

- Δx=[ δξT,δa,δb ]1×8T

 

이 때, x1:6SE(3)은 카메라의 포즈를 의미하므로 증분량 Δx1:6se(3)은 실제로 다음과 같이 업데이트 된다.
x1:6exp(Δx1:6)x1:6

 

x7:8은 photometric parameters a,b를 의미하므로 다음과 같이 업데이트 된다.

x7:8x7:8+Δx7:8

 

포즈가 업데이트되면 다시 한 번 에러를 계산한 후 에러가 충분히 감소하였는지 판단한다. 에러가 충분히 감소하였다면 나머지 포즈 후보들을 고려하지 않고 루프를 탈출한다. 그리고 lambda 값을 절반으로 줄인다. 만약 에러가 줄어들지 않는다면 lambda 값을 4배로 늘린 후 다시 수행한다.

f(x)new# of points<f(x)old# of points

YES: λλ/2

NO: λλ4

 

2.2. Keyframe Decision

매 프레임마다 pose tracking이 끝나면 해당 프레임을 키프레임으로 결정할 지 판단한다. 키프레임으로 결정하는 기준은 다음과 같다. 

 

1. 해당 프레임이 가장 첫 프레임인가?

2. (순수 회전을 제외한) 카메라 움직임으로 인한 optical flow의 변화량 + photometric param a,b의 변화량이 일정 기준 이상인가?

3. residual 값이 이전 키프레임과 비교했을 때 급격하게 변했는가?

 

위 세가지 기준 중 하나라도 만족하게 되면 해당 프레임은 키프레임으로 간주된다.

 

3. Non-keyframes

3.1. Inverse Depth Update

키프레임으로 간주되지 않는 프레임의 경우, 해당 프레임은 현재 sliding window에 있는 키프레임들의 immature point idepth 업데이트에 사용된다.

immature point idepth update

업데이트의 자세한 과정은 다음과 같다.

1. 우선, 이전 키프레임에 존재하는 idepth를 알고 있는 immature point들을 상대포즈 [ R | t ]를 기반으로 현재 프레임에 프로젝션한다.

 

2. 이 때, p1을 한 번만 프로젝션하지 않고 epipolar line을 찾기 위해 idepth 값을 변경해서 총 2번 프로젝션한다.

p2r=KRK1p1

p2,min=p2r+Ktρ1,min

p2,max=p2r+Ktρ1,max

 

- ρ1,max가 기존에 설정되어 있지 않다면 임의의 값인 0.01을 사용한다.

 

3. p2,maxp2,minp2,maxp2,min 값을 계산해서 epipolar line의 방향을 구한다. epipolar line을 수식으로 표현하면 다음과 같다.

L:={l0+λ[lx ly]T}

이 때, l0=p2,min는 원점을 의미하고 [lx ly]T=p2,maxp2,minp2,maxp2,min은 방향을 의미한다. λ는 discrete search step size를 의미한다.

4. 다음으로 maximum discrete search 범위를 정한 후 L 위에서 가장 밝기 오차가 작은 픽셀을 선정한다. 이 때도 8-point patch 기반으로 밝기 오차를 계산한다.

 

5. 밝기 오차가 가장 작은 점을 선정했으면 patch 내에서 밝기 오차가 두 번째로 작은 점을 선정한 후 두 오차의 비율을 통해 해당 점의 퀄리티를 계산한다.

 

6. 해당 p2,est 점은 discrete search를 통해 찾은 값이므로 보다 정교한 위치를 찾기 위해 GN 최적화를 수행하여 최적의 위치 p2를 구한다. 

7. 최적화 과정을 통해 최적의 위치 p2를 찾았으면 다음으로 해당 픽셀의 idepth 값을 업데이트해준다. idepth 값을 업데이트하기 위해 해당 점을 수식으로 전개하면 다음과 같다. 

p2r=KRK1p1

p2=p2r+Ktρ1

- p2r=KRK1[ u1 v1 1 ]T=[ m1 m2 m3 ]T

- Kt=[ n1 n2 n3 ]T

를 전개하면

p2=[u2v21]

u2=m1+n1ρ1m3+n3ρ1,v2=m2+n2ρ1m3+n3ρ1

 

이 된다. 이를 idepth를 기준으로 다시 정리하면 다음과 같은 2개의 식이 유도된다.

ρ1=m3u2m1n1n3u2,ρ1=m3v2m2n2n3v2

 

8. 다음과 같이 유도된 식에서 최적의 위치 p2를 넣고 다시 전개하면 다음과 같다.

x gradient가 큰 경우 Δu>Δv

ρ1,min=m3(u2αΔu)m1n1n3(u2αΔu)

ρ1,max=m3(u2+αΔu)m1n1n3(u2+αΔu)

 

y gradient가 큰 경우 Δu<Δv

ρ1,min=m3(v2αΔv)m2n2n3(v2αΔv)

ρ1,max=m3(v2+αΔv)m2n2n3(v2+αΔv)

 

여기서 α 값은 gradient 방향과 epipolar line의 방향이 수직일수록 1에서부터 값이 증가하는 가중치를 의미한다. 해당 α 값이 너무 커지면 두 방향이 거의 수직에 가깝다고 판단하여 idepth 업데이트를 중단한다. 이와 같은 1~8. 과정을 통해 이전 키프레임에서 immature point p1의 idepth 값을 업데이트할 수 있다.

 

References

1. [EN] DSO paper

2. [KR] SLAMKR study 

3. [CH] DSO code reading

4. [CH] jingeTU's SLAM blog

5. [CH] DSO tracking and optimization

6. [CH] DSO initialization

7. [CH] Detailed in DSO

8. [CH] DSO photometric calibration

9. [CH] DSO code with comments

10.[CH] DSO Null Space

11. [CH] DSO (5) Calculation and Derivation of Null Space

12. [KR] goodgodgd's Visual Odometry and vSLAM

13. [EN] DSO Photometric Calibration paper

14. [EN] Inverse Depth paper