티스토리 뷰

반응형

지난 글에서 3차원 점 하나를 픽셀까지 옮기는 식을 만들었다. $u = f_x X/Z + c_x$, 나눗셈 한 번이면 끝이었다. 그런데 그 식에는 조용한 가정이 하나 깔려 있었다. 광선이 완벽하게 직진한다는 가정이다.

실제로 해보면 이 가정이 얼마나 위험한지 바로 드러난다. 벽에 붙은 표지판 모서리의 3차원 좌표를 알고, 카메라 위치도 안다. 투영식에 넣으면 "$u = 624$ 픽셀에 찍혀야 한다"는 답이 나온다. 그런데 사진을 열어보면 그 모서리는 581 픽셀에 있다. 43 픽셀이 어긋난 것이다.

지난 글에서 3m 앞 사람의 키가 사진에서 215 픽셀이었다. 그 사람 키의 5분의 1만큼 틀렸다는 뜻이다. 계산이 틀린 게 아니다. 계산은 맞았고, 모델이 부족했다.


1. 렌즈는 광선을 휘게 만든다

편의점 천장 모서리에 달린 둥근 방범거울을 떠올려 보자. 거울 한가운데에 비친 물건은 멀쩡해 보이는데, 가장자리로 갈수록 납작해지고 안쪽으로 밀려 보인다. 여기서 중요한 건 밀리는 정도가 중심에서 얼마나 떨어졌느냐에만 달려 있다는 점이다. 위쪽 가장자리든 오른쪽 가장자리든 중심에서 같은 거리면 같은 정도로 밀린다. 방향은 상관없고 거리만 문제가 된다.

렌즈에서도 정확히 같은 일이 벌어진다. 사진 한가운데는 거의 정확하고, 가장자리로 갈수록 점들이 안쪽으로 또는 바깥쪽으로 밀린다. 다만 원인은 다르다. 거울은 표면 자체가 휘어 있어서 그렇지만, 렌즈를 통과한 상은 평평한 센서에 맺히는데도 휜다. 원인은 다른데 결과로 나타나는 무늬가 같은 것이다.

흔한 오해 하나. 셀카에서 코가 커 보이는 건 렌즈 왜곡이 아니다. 코가 카메라에 훨씬 가까워서 생기는 원근 효과이고, 이건 지난 글의 $1/Z$ 가 이미 설명하는 현상이다. 렌즈 왜곡은 같은 거리에 있는 점이라도 화면 가장자리에 있으면 밀리는 것을 말한다.

왜곡이 없다면 실제 렌즈로 찍으면 모든 직선이 직선으로 남는다 중심은 멀쩡하고 가장자리만 휜다 왜곡은 보기 쉽게 과장했습니다
그림 1. 통 모양(barrel) 왜곡. 중심에서 멀어질수록 어긋남이 급격히 커진다.

2. 수식으로 정리하기

정규화 좌표

왜곡을 적으려면 먼저 중심에서 얼마나 떨어졌는지를 잴 기준이 필요하다. 픽셀 단위로 재면 카메라마다 값이 달라지니, $f$ 를 곱하기 전 단계의 비율을 쓴다. 지난 글에서 $X/Z$ 라고 불렀던 그 값이고, 이걸 정규화 좌표라고 한다.

EQ-01 · 정규화 좌표와 반경
$$ x = \frac{X}{Z}, \qquad y = \frac{Y}{Z}, \qquad r^2 = x^2 + y^2 $$

$r$ 은 사진 중심에서 그 점까지의 거리다. 중심이면 $r = 0$ 이고 가장자리로 갈수록 커진다. 앞으로 나올 모든 왜곡 계수는 이 $r$ 하나에만 반응한다.

반경 방향 왜곡

실제로 찍히는 자리는 이렇게 어긋난다.

EQ-02 · 반경 방향 왜곡
$$ \begin{aligned} x_d &= x\left(1 + k_1 r^2 + k_2 r^4 + k_3 r^6\right) \\[6pt] y_d &= y\left(1 + k_1 r^2 + k_2 r^4 + k_3 r^6\right) \end{aligned} $$

그리고 이 왜곡된 좌표에 $K$ 를 적용하면 진짜 픽셀 위치가 나온다. 지난 글의 식과 비교하면 달라진 건 딱 하나, $x$ 자리에 $x_d$ 가 들어간 것뿐이다.

EQ-03 · 최종 픽셀 좌표
$$ u = f_x\,x_d + c_x, \qquad v = f_y\,y_d + c_y $$
기호읽는 법정체단위
$x, y$엑스 / 와이 정규화 좌표. $f$ 를 곱하기 전의 비율. "정면 대비 얼마나 옆인가" 없음
$r$ 사진 중심에서 그 점까지의 거리. 왜곡의 세기를 결정하는 유일한 값 없음
$k_1, k_2, k_3$케이 원·투·쓰리 반경 왜곡 계수. 음수면 통 모양, 양수면 바늘꽂이 모양으로 휜다 없음
$x_d, y_d$엑스 디 / 와이 디 왜곡된 정규화 좌표. 실제 렌즈를 통과한 뒤의 자리 없음
$p_1, p_2$피 원 / 피 투 접선 왜곡 계수. 렌즈와 센서가 나란하지 않을 때 생김. 보통 아주 작음 없음
접선 왜곡 p1, p2 는 어떻게 생겼나

렌즈와 센서가 완벽히 나란하게 조립되지 않으면, 점이 중심 방향이 아니라 살짝 비스듬하게 밀린다. 이걸 접선 왜곡이라고 하고 식은 이렇다.

보조식 · 접선 왜곡까지 포함
$$ \begin{aligned} x_d &= x\left(1 + k_1r^2 + k_2r^4 + k_3r^6\right) + \left[\,2p_1xy + p_2\left(r^2 + 2x^2\right)\right] \\[6pt] y_d &= y\left(1 + k_1r^2 + k_2r^4 + k_3r^6\right) + \left[\,p_1\left(r^2 + 2y^2\right) + 2p_2xy\,\right] \end{aligned} $$

대괄호 안이 새로 붙은 항이다. 반경 왜곡과 달리 $x$ 와 $y$ 가 섞여 있는데, 방향에 따라 다르게 밀린다는 뜻이다. 요즘 카메라는 조립 정밀도가 높아서 $p_1, p_2$ 가 $0.001$ 수준으로 나오고, 실제로 캘리브레이션을 돌려보면 거의 0에 붙어 있어 무시해도 되는 경우가 많다.


3. 손으로 돌려보기

서두의 43 픽셀을 직접 만들어 보자. 지난 글과 같은 카메라를 쓴다. $f_x = 380$, $c_x = 320$, 해상도 640×480이고, 캘리브레이션 결과는 $k_1 = -0.28$, $k_2 = 0.09$ 로 나왔다고 하자. 광각 렌즈에서 흔한 값이다. 볼 지점은 사진 오른쪽 가장자리 근처, 세로로는 정중앙인 자리다. 정규화 좌표로 $x = 0.8$, $y = 0$ 이다.

왜곡이 없다면

EQ-04 · 이상적인 위치
$$ u = 380 \times 0.8 + 320 = 304 + 320 = 624 $$

왜곡을 넣으면

먼저 괄호 안의 배율부터 계산한다. $r = 0.8$ 이므로 $r^2 = 0.64$, $r^4 = 0.4096$ 이다.

EQ-05 · 왜곡 배율
$$ \begin{aligned} 1 + k_1r^2 + k_2r^4 &= 1 + (-0.28)(0.64) + (0.09)(0.4096) \\[4pt] &= 1 - 0.1792 + 0.0369 = 0.8577 \end{aligned} $$

배율이 1보다 작다. 점이 중심 쪽으로 당겨진다는 뜻이다. 이 값을 넣으면 실제 픽셀 위치가 나온다.

EQ-06 · 실제로 찍히는 위치
$$ \begin{aligned} x_d &= 0.8 \times 0.8577 = 0.6861 \\[6pt] u &= 380 \times 0.6861 + 320 = 260.7 + 320 = 580.7 \end{aligned} $$

624에 있어야 할 점이 581에 찍혔다. 43 픽셀이다.

주점 r = 0.4 · 약 11 px 이상적 위치 u = 624 실제로 찍히는 위치 u = 581 43 px 밀리는 방향은 항상 중심을 향한다. 밀리는 양은 중심에서 멀수록 급격히 커진다.
그림 2. 중심 근처는 10 픽셀 안쪽, 가장자리는 40 픽셀 이상 어긋난다.

모서리는 더 심하다

사진의 네 모서리는 중심에서 가장 먼 지점이다. 640×480 기준으로 계산하면 $r \approx 1.05$ 가 나온다.

EQ-07 · 모서리에서의 어긋남
$$ \begin{aligned} 1 + k_1r^2 + k_2r^4 &= 1 - 0.28(1.109) + 0.09(1.229) = 0.800 \\[6pt] \Delta r &= 1.05 - 1.05 \times 0.800 = 0.210 \\[6pt] \Delta u &= 380 \times 0.210 \approx 80\ \text{px} \end{aligned} $$

모서리에서는 80 픽셀이 밀린다. $r$ 이 0.8에서 1.05로 30% 커졌는데 어긋남은 43에서 80으로 거의 두 배가 됐다. $r^2$ 과 $r^4$ 이 곱해져 있으니 당연한 결과다.

위치$r$배율어긋남
중심0.01.0000 px
중심과 가장자리 사이0.40.958약 11 px
가장자리 중앙0.80.85843 px
모서리1.050.80080 px

4. 왜 이 모양인가

왜 r 의 짝수 제곱만 있나

EQ-02를 다시 보면 이상한 점이 있다. 괄호 안에 $r^2$, $r^4$, $r^6$ 만 있고 $r$ 이나 $r^3$ 은 없다. 이유는 렌즈가 둥글기 때문이다. 렌즈는 광축을 중심으로 어느 방향으로 돌려도 똑같이 생겼으니, 왜곡도 방향과 무관해야 한다. 위쪽 가장자리든 오른쪽 가장자리든 중심에서 같은 거리면 같은 정도로 밀려야 한다는 뜻이다.

이 조건을 만족하려면 왜곡이 $r$ 의 짝수 차수로만 이루어져야 한다. 그리고 $r^2 = x^2 + y^2$ 이니, 짝수 차수는 곧 $r^2$ 의 다항식이다. 식의 모양은 렌즈가 둥글다는 사실 하나에서 나온 것이다.

왜 곱셈으로 붙어 있나

$x_d = x \times (\text{배율})$ 형태인 것도 이유가 있다. 점이 밀릴 때 방향은 바뀌지 않고 거리만 바뀌기 때문이다. 중심과 그 점을 잇는 직선 위에서 앞뒤로만 움직인다. $x$ 와 $y$ 에 똑같은 배율이 곱해져 있는 것도 그래서다. 둘에 다른 값을 곱하면 방향이 틀어져 버린다.

왜 다항식으로 흉내내나

진짜 렌즈의 휘어짐은 유리의 곡률과 굴절률로 결정되는 복잡한 곡선이다. 정확한 함수를 안다면 그걸 쓰면 되겠지만, 문제는 그걸 알 방법이 없다는 것이다. 렌즈 제조사도 개체마다의 조립 오차까지는 알려주지 않는다. 그래서 "모양은 모르지만 매끄러운 곡선일 것이다"라는 가정만 두고 다항식으로 흉내낸다. 항을 늘릴수록 정밀해지고, 계수는 실제 사진을 찍어 측정으로 채운다.

실무에서는 $k_1, k_2$ 두 개만 쓰는 경우가 대부분이다. $k_3$ 까지 가는 건 화각이 아주 넓을 때뿐이다.

식의 방향이 거꾸로다

여기가 이 글에서 가장 중요한 대목이다. EQ-02는 이상적인 좌표에서 왜곡된 좌표를 구하는 식이다. $x$ 를 넣으면 $x_d$ 가 나온다. 그런데 우리가 실제로 마주하는 상황은 정반대다. 손에 있는 건 이미 왜곡된 사진이고, 특징점을 뽑으면 $x_d$ 가 나온다. 필요한 건 왜곡이 없었다면 어디였을지, 즉 $x$ 다.

그러니 EQ-02를 거꾸로 풀어야 하는데, 이 식은 깔끔하게 뒤집히지 않는다. $x_d$ 안에 들어 있는 $r$ 이 $x$ 로 만들어진 값이라, 우변에 미지수가 숨어 있는 구조이기 때문이다.

그래서 실제 구현은 반복 계산으로 푼다. "$x_d$ 를 일단 답이라고 치고 배율을 계산 → 나눠서 $x$ 를 갱신 → 다시 배율 계산"을 대여섯 번 돌리면 수렴한다. OpenCV의 undistortPoints 안에서 벌어지는 일이 정확히 이것이다.


5. 체커보드가 하는 일

그럼 $k_1, k_2$ 같은 숫자는 어떻게 알아낼까. 답은 정답을 이미 아는 물건을 찍는 것이다.

체커보드는 정사각형 크기가 전부 같고, 한 평면 위에 있고, 모든 선이 직선이다. 우리가 이 사실을 미리 알고 있다. 그러니 사진 속에서 그 선이 휘어 있다면, 휘어진 양이 곧 렌즈가 저지른 짓이다. 여러 각도에서 스무 장쯤 찍어 "모든 선이 직선이 되게 하는 $f_x, c_x, k_1, k_2$" 를 찾으면 된다.

고정 각도를 바꿔가며 20장 정도 RESULT fx, fy cx, cy k1, k2 p1, p2
그림 3. 정답을 아는 물건을 찍어서, 그 정답이 되게 만드는 숫자들을 거꾸로 찾는다.

결과로 나오는 여덟 개의 숫자가 그 카메라 한 대의 신분증이다. 다른 카메라에는 쓸 수 없고, 같은 카메라라도 렌즈를 갈아끼우면 다시 재야 한다.


6. 실무에서 걸리는 것들

보정한 이미지에는 다른 K 를 써야 한다

왜곡을 편 이미지는 원래와 다른 카메라다. 시야가 잘리거나 검은 테두리가 생기고, 그만큼 주점과 초점거리도 달라진다. 원본 $K$ 를 그대로 쓰면 전부 어긋난다. OpenCV라면 getOptimalNewCameraMatrix 가 돌려주는 새 행렬을 써야 한다.

어안 렌즈에는 이 모델이 통하지 않는다

화각이 120도를 넘어가면 $r$ 이 커지면서 다항식이 발산한다. 어안은 Kannala-Brandt 같은 별도의 모델을 쓴다. OpenCV에서도 cv::fisheye 네임스페이스가 따로 있다.

SLAM에서는 이미지를 통째로 펴지 않는 편이 낫다

이미지 전체를 보정하려면 픽셀 30만 개를 전부 다시 매핑해야 한다. 그런데 SLAM이 실제로 쓰는 건 특징점 수백 개뿐이다. 그 좌표만 undistortPoints 로 펴면 계산량이 수백 배 줄어든다. 시각화가 필요할 때만 전체 이미지를 보정하는 게 일반적이다.

체커보드를 정면으로만 찍으면 안 된다

각도가 다양하지 않으면 $f$ 와 보드까지의 거리를 구분할 수 없어서 값이 엉뚱하게 수렴한다. 기울여서, 가까이서, 멀리서, 화면 구석에도 놓고 찍어야 한다. 특히 화면 가장자리에 보드가 걸치도록 몇 장 찍는 게 중요하다. 왜곡이 큰 영역은 거기이고, 거기 데이터가 없으면 $k_1, k_2$ 를 제대로 추정할 수 없다.


7. 한 장 요약

내부 파라미터왜곡 계수
기호$f_x, f_y, c_x, c_y$$k_1, k_2, k_3, p_1, p_2$
하는 일비율을 픽셀로 바꾸고 원점 이동휘어짐 보정
선형인가예 (행렬 곱)아니오 (다항식)
역변환$K^{-1}$ 로 즉시반복 계산 필요
다시 재야 할 때해상도를 바꾸면렌즈를 갈면

핵심은 세 가지다. 첫째, 렌즈는 점을 중심 방향으로 밀어내고 밀리는 양은 중심에서의 거리 $r$ 에만 달려 있다. 둘째, $r$ 의 짝수 제곱만 나오는 건 렌즈가 둥글기 때문이다. 회전 대칭이라는 물리적 사실이 식의 모양을 결정했다. 셋째, 식은 이상 → 왜곡 방향으로 쓰여 있지만 우리에게 필요한 건 그 반대이고, 그래서 반복 계산으로 푼다.

여기까지가 카메라 한 대 안에서 벌어지는 일의 전부다. 3차원 점만 주어지면 이제 픽셀을 정확히 예측할 수 있다. 그런데 그 3차원 점의 좌표는 카메라를 원점으로 잰 값이었다. 로봇이 움직이면 카메라도 움직이고 원점도 함께 움직인다. 공항 로비의 한 지점을 고정된 기준으로 삼으려면 좌표계를 갈아탈 방법이 필요하고, 그러려면 먼저 회전을 숫자로 적을 줄 알아야 한다. 다음 글의 주제다.


8. 확인 문제

  1. $k_1 = +0.15$ 인 렌즈에서 $r = 0.8$ 인 점은 중심 쪽으로 밀리는가, 바깥쪽으로 밀리는가? 배율을 계산해 답해보라.
  2. 640×480에서 구한 $f_x = 380$, $c_x = 320$ 을 1280×960 영상에 쓰려면 어떻게 바꿔야 하는가? $k_1$ 도 바꿔야 하는가?
  3. 왜곡 식에 $r^3$ 항이 있으면 물리적으로 무엇이 이상해지는지 한 문장으로 써보라.
  4. 체커보드를 전부 화면 정중앙에만 놓고 찍었다면 어떤 파라미터가 특히 부정확해지겠는가?
  5. 특징점 500개만 보정하는 것과 640×480 이미지 전체를 보정하는 것의 연산량 비를 어림해보라.

참고 자료

  • Zhang (2000), A Flexible New Technique for Camera Calibration — 체커보드 캘리브레이션의 원전. OpenCV 구현이 이 논문을 따른다.
  • Hartley & Zisserman, Multiple View Geometry in Computer Vision — 6장 카메라 모델
  • OpenCV 문서, Camera Calibration and 3D Reconstruction — 왜곡 모델의 정확한 정의와 함수 목록
  • Kannala & Brandt (2006) — 어안 렌즈용 일반화 모델
← 이전 · 1. 카메라는 3D를 어떻게 2D로 만드나 다음 · 3. 회전을 적는 세 가지 방법 (준비 중)
반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/09   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함