본문 바로가기
AIML 분야/Depth, Camera Pose, VO, SLAM 등

DF-VO 논문 리뷰 & 코드 셋업해보기

by 포숑은 맛있어 2021. 6. 17.
반응형

아래 깃허브는 두 논문에 대한 코드

  • Visual Odometry Revisited: What Should Be Learnt?
  • DF-VO: What Should Be Learnt for Visual Odometry?

 https://github.com/Huangying-Zhan/DF-VO          

 

 

KITTI Dataset도 미리미리 잘 다운 받아주자.

링크 요청하면 빨리 왔다.

 

과정 (별거없음)

  1. conda를 사용하라고 한다. 매우 살짝 빈정이 상하지만 도커 위에 얹어보기로 한다...
    난 도커가 있어야하니까
  2. 설치하는동안 KITTI Odometry 데이터셋 압축을 풀어주자. 압축해제가 오래 걸린다.
    심볼릭 링크를 추가하라는데 귀찮아서 안했다. 뭐... config 파일 바꿔주자
  3. import 에러: libs가 없다고 뜬다.
    해결법: sys path 추가: 현재 쓰고있는 DF-VO 레포를 추가하는 코드를 넣어줬다.
  4. opencv 에러: 도커 쓰고있어서 그런것같은데 opencv-python-headless로 설치해주고, 화면에 interface 출력해주는 코드 다 꺼버렸다.
  5. 뭔가 못읽는 에러
    굉장히 어이없지만 디폴트에 확장자가 jpg로 되어있다. png로 바꿔주자... ㄱ-

 

결과

3가지 output이 나온다.

 

- global parameters 12개. txt 파일로 프레임마다 뽑힌다. 뭐 원래 그렇듯이...

- 프레임별 visualization (아래 사진)

- map visualization (아래 사진에 왼쪽 것만 자른 것)

아래와 같은 정보로 추정된다. 아직 논문 읽고 있어서...

- 이전 프레임과 현재 프레임의 feature matching

- single view depth prediction

- forward, backward optical flow prediction.

- flow consistency (optical? rigid?)

 

 

 

음, 하지만 나는 DF-VO 논문을 안 읽어서 뭘 한건지 전혀 알 수가 없다. output이 대체 뭘 뽑은거람?

논문을 읽으러 가자.

https://arxiv.org/pdf/2103.00933.pdf

 

 

 

Abstract.

 

Monocular Visual Odometry에 있어서, Multi-view geometry-based 기법들이 좋았다고 한다. 하지만 이 기법들은 scene이 dynamic하거나 Low-texture일 경우에는 취약하다.

게다가 monocular라면 필연적으로 scale-drift문제가 있어서, 에러가 시간이 갈수록 점점 누적되는 문제가 있다.

그래도 요즘 딥러닝이 발전하면서 나아졌지만 그래도 geometric information을 무시하기 때문에 고전 방법들보다는 안좋다고 한다.

 

따라서, 이 논문에서는 multiview geometry와 딥러닝을 합쳐서 Depth and optical Flow (DF-VO)를 제안한다.

고퀄의 correspondence를 deep flow로부터 얻어낸 다음, geometric module을 통해 camera pose를 복원해낸다고함.

 

 

여담) 근데 코드에 스테레오 뭐시기 본것같은데 그건 뭐지? monocular VO잖아

 

 

 

Introduction.

localizing과 주변 정보를 알아내는건 몹시 중요하다. 자율주행이라든가. 이걸 하는데에 있어서 비용절감을 위해 비전 기반의 기술을 선호한다.

그래서 이 논문에서도 monocular visual odometry 문제를 해결하려고 한다.

VO의 목표?
움직이는 카메라의 6DoF motions를 맞추는 것

아니 근데 geometry 기반 VO가 대체 뭔가 싶은데, 그게 SIFT같은거 사용해가지고 sparse feature들 찾은 후 매칭하는거 말하나봄.

그런데 이 논문에서는 다르게 dense prediction 쓸거임. 여기에 올렸었는지는 기억 안나는데 암튼 전에 리뷰했던 LiteFlowNet같은거 사용해서 Optical Flow를 뽑는데, forward/backward 사이에 consistency constraint를 줄거임.

그리고 scale 얘기도 언급이 되는데, monocular다보니까 넘 어려움. 그래서 Epipolar Geometry tracker같은걸 정의했다는데 그냥 아키텍쳐를 이따 읽는걸로 하자

 

 

 

 

 

 

 

--

으아악 도저히 이해가 가지 않아 카메라 파라미터에 대해 찾아보는중

워낙 기초적인거라 논문에 안 써있는 듯 하다

맞게 이해한건지 모르겠는데 일단 확인을 위해 적어본다

https://darkpgmr.tistory.com/32 주로 이 블로그를 참고했다.

 

Camera Calibration?

카메라 좌표계(이미지에서 좌표!)에서 월드 좌표계(진짜 3D 환경)로 바꿔주는 변환을 말한다.

핀홀 카메라 모델 기준.

 

변환행렬을 곱하면 좌표가 이동한다는 것은 알 것이다.

 

이미지상의 좌표 = intrinsic parameters 행렬 * extrinsic parameters 행렬 * 월드좌표

거꾸로 하면 이미지 -> 월드좌표겠지

일단 카메라 내부를 생각하면 구조상 어찌저찌 해서 적용되어야하는 변환, 그리고 카메라 위치나 각도때문에 적용되어야하는 변환 둘로 나뉜다는거다.

 

그런데 우리는 camera motion estimation에서는 움직임을 추정할거니까 외부에 대한건 필요한건가? 이걸 모르겠다.

[1 0 0 0][0 1 0 0][0 0 1 0]으로 초기화해놓고, 프레임간 피쳐를 매칭하여 이미지내의 좌표 움직임 -> 월드 좌표로 변환해서 camera motion을 추정하지 않을까?

 

어쨌거나 intrinsic parameters는 4개라고 보면 된다. [cx cy fx fy].

주점과 초점거리이다. 공개된 툴로 쉽게 연산이 가능하다는데 어떻게 하는건지 찾아봐야겠다.

사실 skew_c도 필요한데 요즘은 거의 0으로 둔대서 제외했다. 실제로 DFVO 구현한거 보면 calib.txt에서 값 4개만 읽어온다.

 

extrinsic parameterstranslation(T)과 rotation(R) 변환에 해당한다.

x, y, z 각도랑 translation만 각각 알면 값 6개면 될 것 같은데 행렬로 나타내면 값이 12개이다.

아무튼 이런 T, R을 어떻게 구하는가.

opencv의 solvePnP 함수를 사용하면 된다고 한다.

전제조건은 intrinsic parameters와 최소 4개의 3D 월드좌표-2D 이미지좌표 쌍이 있다는 가정.

 

쓰다가 날려서 대충 패스한다.

Epipolar Geometry, Perspective n Points에 대한 내용도 나온다.

Epipolar Geometry는 두 이미지가 있고 2D-2D corresponding 점이 있다고 하면 F=K^(-T) E K^(-1)인 F나 E를 구한는 것이라고 한다. F가 fundamental matrix, E는 essential matrix, K는 camera instrinsic.

그러면 E, F를 decomposing하면 카메라 모션인 [R,t]를 얻을 수 있다고 한다.

문제는 두가지 가정이 있다고 한다. t=0이 아니라는 점 (rotation만 있으면 모션 구하기 이상해진다고함) 그리고 보고있는 scene이 평면(planar)이라는 것. 게다가 translation을 구한다해도 scale에 달려있다.

 

 

Perspective n points (PnP)3D-2D correspondence를 가지고 카메라 모션을 추정한다. 아! 검색해보면 Opencv의 solvePnP로 모션 추정하는 경우를 많이 봤는데, 이걸 쓰나봐.

two-view problem이라고 하는데, 3D는 i, 이거랑 corresponding한 2D projection을 j번째 뷰 (X_i, pj)라고 하자. 그러면 reprojection error를 최소화하는걸로 구한다.

여기서 [x]는 픽셀좌표계의 인덱싱. 걍 위에서 말한대로 (intrinsic*extrinsic*월드좌표)=이미지좌표니까, 그 이미지좌표에서 차이를 에러라고 정의한 식인듯? 근데 이걸 구하려면 3D 좌표를 알아야하는데, 다시말해 센서로 측정한 데이터가 있다거나 이걸 구하는 알고리즘을 쓰야한다는건데. 역시나 monocular에서 어려웠던 지점이다.

 

본론: DF-VO

일단 feature를 추출하고, 매칭하여 correspondences를 구하는 게 필요하다. 그래야 pose estimation을 하는거고. 이 시스템에선 위에서 언급한 2디-2디와 2디-3디 correspondence를 모두 고려한다. 그러기 위해서,

  • optical flow network를 통해 dense correspondence를 얻음. 이건 2디-2디
  • single view depth network를 통해 3디 구조를 얻을 수 있다면, 여기에 옵티컬 플로우를 끼얹어 3디-2디 correspondence를 얻을 수 있다. 이후 sparse correspondence도 정교하게 했다고 한다.
  • pose estimation을 위해 두 tracker를 사용. E-tracker, PnP tracker.
    아, 아까 epipolar하고 PnP알고리즘과 관련있나봐
  • 암튼 이래저래 monocular VO 시스템을 만들었음

 

뭔가 고전 알고리즘의 접근법을 많이 따르는 듯? 딥러닝이라고 그냥 이미지 좀 때려넣고 [R,t] 맞추라고 하진 않는 것 같다.

 

 

Deep Predictions

2d-2d, 2d-3d에 해당하는 (pi,pj)나 (Xi,pj) 페어들을 구하는 게 우선이다.
그래서 optical flow network, single-view depth network를 만들었다.

먼저 optical flow는 2d끼리 dense correspondence를 만들기 위함이잖음.
모든 픽셀에서 성능이 좋은건 아니지만, SOTA급 모델들을 쓴다면 준수하게 나온다.
이 논문에서는 모델을 제안한건 아니고, 기존에 있는걸 가져다쓴다. 실제로 깃허브에서 DF-VO 돌렸을땐 LiteFlowNet1을 사용했던 것 같다.

single view depth의 경우, deep depth network를 depth sensor처럼 활용했다고 한다. 하지만 SOTA급을 써도 이 모델들은 성능이 그리 좋지 않다고 한다. relative error가 10%정도이기 때문.

따라서, 2디-2디를 주로 쓰고 2디-3디는 스케일 복원용이나 PnP tracker 정도로 사용. 이 PnP 트래커는 E트래커가 잘 동작하지 못할 때 사용하는 auxiliary trakcer로 사용.

 

Correspondence Selection

dense correspondence를 위에서 구했는데, 다 쓰는게 아니라 일부만 쓰는거임. 왜냐면 이론상 다는 필요 없음.
랜덤하게/균일하게 그냥 뽑아도 되겠지만, 모든 애들이 균일한 성능을 가지는게 아니라 이왕이면 매칭이 잘 되는 점만 뽑는 게 좋을 것.
bi-directional flow consistency를 기반으로한 선택 알고리즘이 있다고 한다.
원점을 forward로 워프시키고, 다시 backward flow로 워프시킨게 원점으로 돌아오게 하는 원리인 듯 하다.
그렇게 가장 consistency가 좋은 점들을 뽑겠다고 한다.

 

  • 기준1: Best-N selection
    이름 그대로. 주로 2000개를 선택한다고 한다.
  • 기준2: Local best-K selection
    더 발전된 방법. 이미지를 M개의 region으로 나누고, 각각에서 best K개씩 뽑는 것. 단, threshold를 둬서 못넘으면 탈락.
    다만 드문 케이스로 correspondence가 불충분하게 나오는데, 이경우에는 constant motion model을 사용한다.
    (E/PnP tracker 대신.)

이렇게 뽑은 점들을 가지고 아까 나온 epipolar geometry의 E matrix를 구할 수 있다.

그러면, 우리가 알고싶은 카메라 모션에 해당하는 [R, t]는 E matrix를 분해해서 얻을 수 있다. 하지만 그렇게 얻은 정보는 scale에 종속적이라고 했다. translation이 unit vector같은거라서, 실제 camera motion을 추정하려면 scale을 알아야 여기에 곱하겠지.

 

Scale Recovery
triangulated depth map을 구해야한다. 

서로 잘 맞는 filtered optical flow와 depth를 선택하는 게 중요하다.
아래 알고리즘을 통해서 iterative하게 s가 수렴할때까지 반복해서 구한다.

 

일단 초기값으로 s를 잡음. 그럼 T가 정해짐. rotation이랑 translation unit vector는 이미 구했으니까.

rigid flow를 구하는데, 아래 T를 알고 K는 카메라 파라미터였고 x는 optical flow에서 아까 선택된 픽셀좌표계의 점.

D는 predicted depth. triangulated depth map

 

 

 

4.5 Model Selection

 

1. Flow Magnitude

flow prediction을 한 다음, essential matrix를 사용하는 기준은 flow magnitude가 충분히 큰 경우에만 쓰는 것이다.

하지만 앞서 말했듯이, camera가 가만히 있는데 물체가 움직이는 경우도 있는데다가 rotation만 있는 경우에는 모션이 이상하게 찍힌다는 단점이 있다.

 

2. Geometric Robust Information Criterion (GRIC)

motion degeneracy문제를 해결하기 위해서 두가지 방법이 있다고 한다. (옛날 논문에 나왔다고함)

1. statistical model selection test. GRIC이라는 이름인데, degeneracy가 발생했는지 안했는지을 알아볼수 있다.

2. multiple motion models. fundamental F와 homography matrix H중에서 GRIC score가 더 낮은걸 택한다.

 

 

 

아 졸려... 괴로워

나중에 읽을래 재밌는거 보러감

 

KITTI Odometry criterion

t_err: average translational error (%)

r_err: average rotational error (degree/100m)

ATE(Absolute trajectory error): 예측한 카메라포즈 (x,y,z)와 GT같의 root MSE

RPE(Relative pose error): frame-to-frame relative pose error

반응형

댓글