Project 1
by Yeonjee Jung
이 프로젝트는 Camera Calibration과 Disparity Map, Depth Map을 생성하는 프로젝트이다.
Camera Calibration
먼저, 체커보드를 이용해서 Camera Calibration을 수행한다. 6개의 체커보드 이미지가 있고, 모서리를 찾아서 이를 평면좌표(world point)로 만들어주는 homography matrix를 찾고, 그 matrix에서 intrinsic, extrinsic 파라미터를 찾는 과정이다. Zhang’s method를 사용하여 수행할 수 있다.
Homography Calculation
먼저 s˜q=H˜ps~q=H~p를 만족하는 행렬 HH를 찾아야 한다. (˜q~q는 world point, ˜p~p는 체커보드 좌표)
H=[h11h12h13h21h22h23h31h32h33]으로 표현되고, minH∑mj=1||qj−^qj||2를 최소화하는 H를 찾으면 된다. (qj=[ujvj], ^qj=1h31Xj+h32Yj+h33[h11Xj+h12Yj+h33h21Xj+h22Yj+h23])
이를 정리하면,
minH∑j||[u0(h31Xj+h32Yj+h33)−(h11Xj+h12Yj+h13)v0(h31Xj+h32Yj+h33)−(h21Xj+h22Yj+h23)]||2이 되는데, 각 항을 풀어보면
[−Xj−Yj−1000ujXjujYjuj000−Xj−Yj−1vjXjvjYjvj][h11h12h13h21h22h23h31h32h33]이라고 쓸 수 있다. 앞에 곱해진 행렬을 Lj라고 하면 이 문제는 minx||Lx||2 문제가 된다. (L은 Lj를 세로로 늘어뜨린 행렬) 따라서 LTL의 가장 작은 eigenvalue중 가장 작은 것에 대응하는 eigenvector를 찾으면 된다.
이 때의 H 행렬은 한 이미지당 하나를 찾을 수 있으므로 이 프로젝트에서는 6개의 H 행렬이 나오게 된다.
Intrinsic Parameter
우리는 H행렬을 알고 있고, H=K[r1r2t]이다. 그리고 rT1r1=rT2r2, rT1r2=0이라는 제약을 갖고 있으므로, 우리는 intrinsic matrix K를 알아낼 수 있다.
먼저 H=[h1h2h3]이라고 하자. h1=Kr1, h2=Kr2이기 때문에 r1=K−1h1, r2=K−1h2이다.
위 조건들을 대입해 보면
hT1K−TK−1h1=hT2K−Tk−1h2 hT1K−TK−1h2=0라는 식을 만들어낼 수 있다.
B=K−TK−1=[B11B12B13B21B22B23B31B32B33]이라고 하면,
B=[1α2−γα2βv0γ−u0βα2β−γα2β−γα2β+1β2−γ(v0γ−u0β)α2β2v0γ−u0βα2β−γ(v0γ−u0β)α2β2−v0β2(v0γ−u0β)2α2β2+v20β2+1]이다. (K=[αγu00βv0001]이므로)
B11,B12,B13,B22,B23,B33만 알면 K의 변수들을 구할 수 있으므로 b=[B11B12B13B22B23B33]T를 구하는 것을 목표로 한다.
두 개의 조건을 압축해서
[vT12(v11−v22)T]b=0이라고 쓸 수 있다. (vkl=[h1kh1lh1kh2l+h2kh1lh1kh3l+h3kh1lh2kh2lh2kh3l+h3kh2lh3kh3l]T)
V=[vT12(v11−v22)T]라고 하면 각 V들은 이미지당 하나씩 있으므로, 우리는 총 6개의 V를 가지고 B를 찾을 수 있다. 이 V들을 세로로 합쳐서 V′행렬을 만들고, minb‖V′b‖2 문제를 풀면 b를 구할 수 있다. 이 때의 해는 V′TV′의 eigenvalue중 가장 작은 것에 대응하는 eigenvector를 구하면 된다.
이렇게 구한 b를 이용해서 각각의 변수에
v0=(B12B13−B11B23B11B22−B212) λ=B33−B213+v0(B12B13−B11B23)B11 α=√λB11 β=√λB11B11B22−B212 γ=−B12α2βλ u0=γv0β−B13α2λ를 대입하면 intrinsic matrix K=[αγu00βv0001]를 구할 수 있다.
Extrinsic Parameter
지금까지 구한 H와 K로 extrinsic parameter들을 구할 수 있다. 먼저 정규화를 위한 상수 λ′=1‖K−1h1‖+1‖K−1h2‖2를 구한다. 그 후에는
r1=λ′K−1h1 r2=λ′K−1h2 r3=r1×r2 t=λ′K−1h3을 이용해 extrinsic parameter들을 구한다.
여기서 구한 rotation matrix R=[r1r2r3]은 일반적으로 rotation matrix의 성질을 만족하지 않으므로, 보정을 해줘야 한다. R=UΣVT로 분해할 수 있는데, 여기서 R′=UVT를 구하면 된다.
Maximum Likelihood Estimation (MLE)
우리가 위에서 구한 값은 그저 방정식을 푼 것이지, 물리적으로 아무 의미가 없는 숫자이다. 따라서 MLE를 통해 값을 보정해줄 필요가 있다. MLE추정은 minK,Ri,ti∑i∑j‖qij−^qij‖2를 통해 할 수 있다. (사실 이 식은 H를 찾을 때 썼던 식이다.)
코드에서는 intrinsic, extrinsic 파라미터들을 벡터로 만들어 넘겨서 lsqnonlin 함수를 사용하여 최적화했다.(Matlab)
Depth Map
Depth map을 구하기 위한 과정은 다음과 같다. (좌, 우에서 찍은 이미지가 주어진다.)
- 이미지를 흑백화시킨다.
- cost function을 정해서 cost volume을 만든다.
- cost aggregation을 한다.
- 최소 cost를 갖는 인덱스를 골라 disparity map을 만든다.
- disparity map을 카메라 파라미터를 이용해 depth map으로 변환시킨다.
Preprocessing
단순히 두 이미지를 흑백화시킨다.
Cost Volume
좌측 이미지를 기준으로 한다. 좌측 이미지의 모든 픽셀에 대하여 오른쪽 이미지에서는 왼쪽으로 d만큼 떨어진 픽셀을 고른다. (좌측 이미지에서 (10,5)에 대해, d=5라면 우측 이미지에서는 (5,5)를 고르는 셈.) 좌우 이미지 모두 해당 픽셀 주변의 window크기만큼의 행렬을 골라 벡터화시킨 후, cost를 계산해 cost volume에 저장한다. 이 계산을 minDisparity부터 maxDisparity까지 수행해 cost volume에 저장한다. (이 프로젝트에서 window 크기는 15로 지정하였고, minDisparity는 11, maxDisparity는 140으로 지정하였다. cost 대신에 NCC=∑i∑jAijBij√∑i∑jA2ij√∑i∑jB2ij를 사용하였다.)
Cost Aggregation
각 layer의 cost를 filter를 이용하여 aggregation한다. 이 프로젝트에서는 imguidedfilter 함수에 해당 이미지를 가이드로 사용해서 필터링하였다.
Disparity Map
각 픽셀에 대하여 가장 작은 cost를 가지는 disparity를 고른다. (이 프로젝트에서는 NCC를 사용하였으므로 값이 가장 큰 것을 고른다.)
Depth Map
각 픽셀에 대하여 Z=fTd 공식을 적용하여 depth map을 만든다.
Result
위 표는 카메라 파라미터 측정에 대한 결과이다.
위 이미지는 각각 좌, 우에서 찍은 이미지이다.
위 이미지는 disparity map이다.
위 이미지는 depth map이다.
이 프로젝트에 대한 코드는 링크에서 볼 수 있다.
Subscribe via RSS