Linear Algebra
🪀

Orb-Slam 1 읽어보기

생성일
2022/06/30 00:25
태그
visual SLAM
feature-based
ORB-SLAM

1. Introduction

Viusal SLAM은 주변 환경을 Reconstruction하면서 카메라 위치를 추정해가는 Task입니다!

ORB-SLAM의 Main Contribution은 이렇습니다!!

여러 Task에서 같은 ORB feature를 사용한다 → 이를 통해 더 효율적인 시스템 구축 가능
Covisibility Graph를 이용한다 → 규모가 큰 환경에서도 실시간으로 동작할 수 있다.
Pose Graph Optimization을 이용한다 → 실시간으로 loop Closing을 활용 할 수 있다.
빛의 세기나 카메라의 시점 변화에 강인하게 Relocalization을 실시간으로 할 수 있다.
Map이나 Pose에 대해서 강인한 Initialization을 제공한다.
keyframe에 대해 적자생존의 원칙을 취한다. (ORB-SLAM에서 제일 중요한 요소가 아닐까?) 많은 keyframe을 뽑지만, 필요없는 keyframe들은 과감히 쳐낸다강인한 성능 제공

2. System Overview

1. 어떠한 Feature를 사용할까요?

ORB slam의 가장 주요한 아이디어mapping, tracking을 진행하기 위한 feature들이 relocalization, loop detection을 하기 위한 place recognition 과정에서도 재사용된다는 것이다!

시스템을 효율적으로 만들어 가장 최소한의 edge만 남겨둔 그래프 계산량을 줄인다! (다른 task를 위해 feature를 따로 뽑지 않아도 된다)

또한 실시간으로 동작해야 하기 때문에 빠른 처리속도가 필요합니다. 그래서 빨리빨리 Feature를 뽑아줘야 할 필요가 있습니다.
다른 feature detecting algorithm (SIFT, SURF, AKAZE)는 실시간에서 사용할만한 속도가 나오지 않는다 그래서 사용하는 게 바로 ORB Feature이다!
ORB Feature를 뽑는 것은 FAST 코너 추출 + BRIEF descriptor의 결합으로 이루어진다.

2. 기본적인 파이프라인은 어떻게 구성되나요?

기본적으로 Tracking, Local Mapping, Loop Closing이 3가지 쓰레드가 병렬적으로 동시에 동작합니다.
Tracking은 각 프레임마다 카메라의 위치를 추정하고 새로운 Keyframe을 언제 추가할지 정합니다. 이전 프레임과 feature matching을 진행하고 motion-only BA를 진행하여 pose를 최적화 합니다. 만약 tracking 과정에서 길을 잃으면, Place Recognition이 사용되어 global relocalization을 진행합니다.
Local Mapping은 앞선 과정에서 만든 Keyframe을 가지고 local BA를 적용하여 카메라를 둘러싸는 환경에 대하여 최적의 reconstruction을 수행합니다. 새로운 Keyframe에서 얻은 feature와 매칭되지 않는다면 Covisiblity Graph에서 연결된 Keyframe들 중에서 찾아서 triangulate하여 3D Point를 복원합니다. 이 때 Culling Policy를 통해 필요없는 Points, Keyframes를 제거합니다.
Loop Closing은 새로운 Keyframe이 추가될 때마다 Loop를 찾으려고 합니다. 만약 Loop가 발견된다면, Similarity Transformation을 통해 loop의 drift error를 추정하고 Pose Graph Optimization을 통해 error를 제거하고 Global Consistency를 지켜냅니다! 이 과정에서 사용하는 것이 Essential Graph입니다.

3. Map Point랑 Keyframe 뜯어보기

Map Point pip_i 가 포함 하고 있는 정보:
월드 좌표계 상에서의 3D 위치 정보 Xw,i\bold{X}_{w,i}
관측 방향을 나타내는 벡터 ni\bold{n}_{i}
Point를 설명해줄 수 있는 ORB descriptor Di\bold{D}_{i}
Point가 관측될 수있는 최단/최소 거리 dmin,dmaxd_{min}, d_{max}
Keyframe KiK_i 가 포함하고 있는 정보:
카메라의 pose Tiw\bold{T}_{iw}
카메라의 intrinsic Parameter (Focal length, Principal Point)
frame에서 뽑은 모든 ORB features

4. Covisibility Graph 와 Essential Graph의 관계

Covisiblity Graph는 각 Keyframe간의 관계성을 표현하기 위한 그래프입니다!
이 그래프는 특정 방향을 가리키지 않고, 가중치만 존재하는 Graph 형태로 표현됩니다. 각 노드가 keyframe을 의미하고, 두 keyframe이 적어도 15개 이상의 같은 3D point를 관측하고 있다면 Keyframe 사이에 edge(연결선)을 이을 수 있습니다. 이 때 공유하는 Map Point의 수만큼 가중치 θ\theta를 두어 edge를 표현합니다.
앞서 소개하는 부분에서 언급하였지만, Pose Graph Optimization을 통해 Loop Closing을 진행하는데, 이 때 위에 있는 Covisiblity Graph를 사용하게 되면 edge들이 너무 많아 연산량에 부담을 줍니다.
이를 해결하기 위해, 조금 더 가벼운 형태의 그래프를 만들어야 하는데, 이것이 Essential Graph입니다. Essential Graph는 모든 Keyframe(node)들은 그대로 둔 채로, 훨씬 적은 수의 edge를 사용합니다.
이러한 시스템을 계속 진행시키면 점진적으로 더더욱 얇은 그래프를 구축하게 되는데, 이것을 Spanning Tree라고 하고, 가장 최소한의 edge만 남겨둔 그래프가 됩니다.
아래 그림에서 실제 Keyframe 입력에 대해 Spanning Tree 표현이 어떻게 되는지 알 수 있습니다.

Q. 시간이 지남에 따라 그래프는 어떻게 업데이트 되나요?

새로운 Keyframe이 포함되면 기존 Tree을 구성하는 노드과 비교하여 가장 많이 겹치는 Keyframe과 연결 짓고, 만약 Keyframe이 삭제 된다면, 그것에 해당하는 링크들도 다 제거 됩니다. 아까 언급했던 ‘적자생존’ 의 원칙에 따라 필요한 노드에 대한 관계는 포함하고 불필요한 노드에 대한 관계는 삭제해 나가는 방식입니다!
Essential Graph를 구성하는 요소들은 다음과 같습니다.
Covisiblity Graph에서 높은 Covisiblity를 갖는 edge (적어도 θ\theta가 100 이상)
Spanning Tree를 구성하는 edge
Loop Closure가 적용된 edge

이러한 여러 요소들이 결합되어 Essential 그래프를 구성하기 때문에,

카메라의 움직임에 대해서 정확한 네트워크로 표현할 수 있게 되며 이를 통해 정확하고 강인한 추정 결과치 또한 얻을 수 있습니다.

3. Automatic Map Initialization

조금 더 공부해야할 것 같다

4. Tracking

Tracking Thread의 경우 카메라의 매 프레임마다 동작합니다
이러한 카메라의 움직임에 대한 최적화는 motion-only BA를 통해 동작합니다.

ORB에서는 뭘 최적화 하는 건가요?

1.
Full BA : 모든 KeyframePoint가 최적화의 대상입니다.
2.
Local BA : Keyframe은 고정된 채로 local area의 모든 Point들이 최적화 대상입니다.
3.
motion-only BA : 모든 Point는 고정된 채로 카메라의 pose만 최적화합니다.

1단계, ORB feature 뽑기

8개 단계 스케일 FAST 코너를 추출합니다. 한 cell당 최소 5개의 코너를 뽑도록 합니다.

2단계, 이전의 frame으로부터 초기 Pose 추정

등속 모델으로 가정하여 카메라의 포즈를 추정하고 이전 프레임의 Map Point를 활용해 guided search?

3단계, Global Relocalization을 통해 초기 Pose 추정

만약 길을 잃게 되면, 현재 프레임을 Bag Of Words에 넣고 그 중에서 현재 프레임과 비슷한 것을 찾습니다,

4단계, Local Map 따기

앞선 과정을 통해 카메라 포즈를 추정하고 각 이미지 평면에서의 feature들의 매칭쌍을 알게된다면, feature들에 해당하는 실제 3D 점을 mapping할 수 있습니다.
각 키프레임 K1,K2K_1, K_2 에서 보이는 맵 포인트들이 현재 프레임에서도 보인다면.
1.
현재 프레임에서 map point를 projection한 x\bold{x} 를 구합니다.
2.
현재 viewing ray v\bold{v} 와 map point의 평균 viewing ray n\bold{n} 와의 각도를 측정해
v · n < cos(60 ◦ ).이면 버립니다.
3.
카메라 중심과 map point간의 거리 dd 를 측정합니다.
4.
프레임에서의 scale의 비율 d/dmaxd/d_{max} 를 계산합니다.
5.
map point를 대표하는 대표 descriptor와 현재 프레임에서 매칭되지 않은 ORB features 랑 비교합니다.
이렇게 함으로써 프레임으로부터 얻은 map point를 포함하여 Camera Pose가 최적화 됩니다.

5단계, 새로운 keyframe 선정하기

극한 카메라의 움직임(특히 회전)에도 카메라의 움직임을 강건하게 추정하기 위해서는 가능한 한 빨리 keyframe을 추가 해주어야 한다. 이를 위한 조건은 아래와 같다.
마지막으로 진행한 Global Relocalization이 끝난 이후로 20프레임 이상은 지나야 한다.
마지막 Keyframe을 삽입한 후로 20 프레임 이상은 지나야 한다.
현재 프레임이 적어도 50개의 point를 추적하고 있어야 한다.
레퍼런스 프레임보다 적어도 90%보다 적어야 한다. (이전 프레임과 너무 비슷하면 안된다는 뜻)

6. Local Mapping

위의 과정에서 새로운 Keyframe을 뽑았고, 이를 KiK_i 로 정의한다.

1단계, Keyframe 삽입하기

KiK_i에 해당하는 노드를 추가함으로써, covisibility Graph를 업데이트 하고, 다른 Keyframe들과 공유하는 map Point를 이용하여 edge를 업데이트 합니다. KiK_i 와 가장 겹치는 keyframe을 연결함으로써 Spanning Tree를 업데이트하고 keyframe의 BoW 표현방법을 계산하여 세로운 Point의 Triangulation 과정을 돕습니다.

2단계, 중요하지 않은 Map Point 골라내기

Map에 Map Point를 남겨 두기 위해서는 테스트를 통과해야 한다. 이렇게 해야 이 맵 포인트가 추적할만하고 잘못 Triangulated 되지 않음을 보장할 수 있다.
Tracking 과정속에서 보일것으로 예상되는 프레임중 25%보다 많이 point를 찾아야 합니다.
만약 map point 생성 중에 하나의 키프레임 이상이 지나쳤다면, 적어도 다른 3개의 키프레임 중에서 발견되어야 합니다.
이 부분은 아직 잘 이해가 안되서… 더 공부를 해 봐야할 것 같습니다

3단계, 새로운 Map Point 만들기

새로운 맵 포인트는 Covisibility Graph 상에서 연결된 Keyframe KcK_c 의 ORB feature와 Triangulation을 진행함으로써 생성됩니다. 만약 Keyframe KcK_c 의 ORB feature와 매칭되는 점은 다른 키프레임의 다른 점들과 매칭을 시도 합니다. 만약 Epipolar Constraint를 만족하지 않는 다면, 폐기합니다.
효과적으로 맵에 표현하기 위해 Positive depth, parallax, reprojection error, scale consistency를 체크합니다.

4단계, Local BA 진행하기

Local Bundle Adjustment는 크게 두가지를 최적화 합니다.
현재 키프레임
covisiblity graph에서 연결된 키프레임들
그러한 키프레임들에서 보이는 맵포인트들
현재 키프레임과 연결되어 있지는 않지만, 같은 점을 보고 있는 키프레임들

5단계, 중요하지 않은 Local Keyframe 골라내기

컴팩트한 맵을 유지하기 위해서는 Local Mapping시 필요없는 키프레임을 찾고 버려야 합니다. 왜나하면 키프레임의 수만큼 BA의 복잡도가 올라가기 때문입니다. 맵이 계속 생성되더라도 키프레임의 수를 어느 정도로 한정해야만 합니다. 다른 3개의 키프레임에서 90%이상 겹치는 키프레임들은 과감히 버립니다.

7. Loop Closing

Loop Closing은 Local Mapping에서 마지막으로 처리한 Keyframe KiK_i 를 가지고 진행합니다.

1단계, Loop가 될 만한 후보군 찾기

Keyframe KiK_i 의 Bag of Words Vector를 Covisiblity Graph 상에서 (θmin=30\theta_{min} = 30) 를 만족하는 벡터와의 Similarity를 측정하고 가장 낮은 점수 smins_{min}를 유지합니다. 만약 recognition database에서 이 값보다 작은 Keyframe이 있다면 버립니다. → 이러한 과정을 통해 강인함 확보!
너무 현재 Keyframe과 가까운 곳에 위치한 Keyframe의 경우 loop로 판단해선 안된다!

2단계, Similarity Transformation을 찾아보자

현재 키프레임과 Loop 키프레임간의 변환관계를 계산해야한다 이를 통해 루프상의 에러를 알 수 있다.

3단계, 루프 합치기

복제된 맵 포인트를 합치고 새로운 엣지를 그래프에추가한다.

4단계, Essential Graph 최적화하기

essential graph에 대해 PGO를 진행한다