본문 바로가기
[Public] 신호처리/기초 영상처리

[OpenCV] 카메라 보정 (#2 투영기하, 동차좌표계)

by 차출발 2011. 12. 28.
반응형
투영변환이 무엇인가요 ?

실세계의 한점 Q = (X, Y, Z)는 3차원의 점이다 
이 점이 앞시간에서 배웠던 투영 스크린 상의 한 점 (X, Y)로 2차원 점으로 
변환되는 관계를 투영 변환이라 한다.



이렇게 투영변환을 사용할 때는 동차 좌표계라고 알려진 좌표계를 사용하는게 편하다.


그럼 동차좌표계가 그럼 무엇인가요?

3D에서는 기본적으로 3차원좌표계이지만 이것을 어떤 목적으로 4차원으로도 확장이 가능하다.
이렇게 어떤목적을 위하여 한 차원의 좌표(n) 을 한차원 추가된 좌표  (n+1)로 표현을 하는 것을 동차 좌표계라 한다.

예를 들자면
3차원 좌표 (x, y, z)는
4차원 좌표 (x, y, z, w)형태로 표현 한다는 것이다.
기본적인 성분 x y z 에 w가 추가된것으로 3D 상에서는 x/w y/w z/w로 나타낸다.



투영행렬에서 동차좌표를 사용하는 이유가 무엇인가요?

시점으로 보이는 점들의 위치가 중요한게 아니라 시점으로 부터 방향이 중요하기 때문이다.

그림을 보자

 

투영행렬에 대한 이론을 간략히 설명한 것이다.
우리가 원하는 것은 3차원의 점들이
2차원 평면인 빨간 네모안에 다 모인다는 것이다.




다음 그림은 점들의 위치가 서로 다른 3차원 점이 2차원에 투영되는 점은 결국 하나가 되버린다느는 것이다.
그래서 시점으로부터 방향이 중요한 것이 무엇인지 이해할 수 있다.



3D에서도 동차좌표를 사용하던데 ?

동차좌표계가 있음으로 오브젝트의 이동을 행렬간의 곱셈으로 표현이 가능하다.
이동, 크기, 회전을 모두 담은 행렬은 최소 4X4 행렬일 수 밖에 없다.
이 행렬과 정산적인 연산을 하기 위해서는 벡터도 행렬이므로 1X4 또는 4X1의 행렬 형태를 맞춰야한드는 것이다.

포인트(w=1)과 벡터(w=0)을 가늠할 수 있는 기준이 되기도 한다.

동차좌표는 방향과 점의 구분시켜준다.
x,y,z의 3차원 좌표계 구조체는 이게 점인지 방향인지 구분이 모호하다.
그래서 동차 좌표계가 포함된 4차원 좌표계로 표현하면 (0은방향 1은 위치)로 표현할 수 있다.


0은 방향을 의미하는 벡터로 
위치,방향으로서 서로 다른 벡터인지 구분이 가능
(방향벡터가 방향이 같고 위치가 다르다라는 것은 확대 또는 축소인 상태)

1은 위치를 의미하는 벡터로
위치가 서로 다른 벡터인지 구분이 가능

0의 동차항을 가지는 벡터는 확대, 축소, 방향변경이 가능하다.
1의 동차항을 가지고 있는 벡터는 이동(위치변화)가 가능하다.

0의 동차를 가지는 벡터는 1~3행
1의 동차항을 가지는 벡터는 4행



그럼 동차좌표계를 어떻게 구하는 가요?

동차좌표계 상 변환된 좌표 = p * 월드행렬 * 뷰행렬 * 투영행렬
투영행렬에서 카메라공간상에 존재하는 점과 카메라 위치사이의 깊이 z를 최종 결과점 x y z 에 각각 곱해지고 w에 저장되는데 바로 이 과정이 동차좌표계를 위한 과정이다.

해당 좌표공간(카메라 공간, 투영공간, 월드 공간)에서 3D 좌표를 얻어내려면 w로 나눠댄면 된다.
여기서 월드공간과 카메라공간에서는 w값이 항상 1이기 때문에 변화가 없지만
투영공간에서는 w값이 카메라 공간에서의 카마레위치에서 부터 정점사이 거리이기 때문에 z값에 따라 정점의 위치와 크기가 변환되는 것임을 짐작할 수 있다.




그럼 우리가 사용하는 이미지카메라 모델의 경우?
 
영상 평면이 투영공간이 되고 이는 2차원 평면이다.
때문에 동차 좌표는 q = (q1, q2, q3)로 표현할 수 있다.
투영공간에서 비례하는 점은 모두 동일 하므로 q1과 q2를 q3로 나누어 줌으로 써 실제 2차원 픽셀 좌표를 얻을 수 있다.

동차 좌표계를 사용하면 fx fy cx cy 등의 카메라 파라메터를 3X3 크기의 행렬 하나로 표현 할 수 있다.
우리는 이 행렬을 카메라 내부행렬이라 부른다.

카메라 내부행렬을 표현하는 방법은 Heikkila 와 Silven의 논문을 참고해보면된다.
(A Four-step Camera Calibration Procedure with Implicit Image Correction)

이제 실세계의 한점이 카마레라로 투영되는 관계는
다음과 같은 간단한 행렬 연산으로 표현이 가능하다.



위행렬을 실제로 곱해보면 w = Z가 되고
점 q는 동차 좌표계로 표현되어 있기 때문에 x와 y좌표값을 Z로 나누어야 원래 좌표를 얻을 수 있따.


그럼 OpenCV에서는 이를 제공해주는 함수는 없나요?

일반 좌표계를 동차 좌표계로 변환하는 cvConvertPointsHomogenious() 함수를 제공하고 있다.

void cvConvertPointsHomogenious(const CvMat* src, CvMat* dst)
일반좌표계를 동차 좌표계로 서로 호환이 가능하다.

입력 Scr 과 dst 의 행렬 차수가 서로 같은 경우 내부 데이터는 단순히 복사되며

행렬차수가 Scr > dst 이면
dst행렬의 원소들은 src 행렬에 저장된 벡터의 맨 마지막 원소로 나머지 원소값들을 나누어 계산된다.

행렬차수가 scr < dst 이면
점들이 모두 복사되면서 dst배려에 있는 모든 벡터의 마지막 원소에 1이 추가된다.





도움이 되셨다면 리플 하나 달아주는 센스 !
리플 하나가 큰 힘이 된답니다 ^^