
카메라 모델과 렌즈 왜곡 (lense distortion)
2022, Mar 29
- 참조 : https://kr.mathworks.com/help/vision/ug/camera-calibration.html
- 참조 : http://jinyongjeong.github.io/2020/06/19/SLAM-Opencv-Camera-model-%EC%A0%95%EB%A6%AC/
- 참조 : http://jinyongjeong.github.io/2020/06/15/Camera_and_distortion_model/
- 참조 : https://docs.nvidia.com/vpi/algo_ldc.html
- 참조 : http://www.gisdeveloper.co.kr/?p=6868
- 참조 : https://ori.codes/artificial-intelligence/camera-calibration/camera-distortions/
- 참조 : http://www.close-range.com/docs/Decentering_Distortion_of_Lenses_Brown_1966_may_444-462.pdf
- 이번 글에서는
카메라 모델의 특성
,카메라 렌즈 왜곡 모델
그리고렌즈 왜곡을 제거하는 방법
등에 대하여 알아보도록 하겠습니다. - 특히 가장 많이 사용되는 카메라 모델인
Generic Camera Model
을 기준으로 살펴볼 예정이며 좀 더 간단한 형태의Brown Camera Model
에 대한 내용은 간략하게 코드적으로 사용하는 방법에 대하여 확인해 볼 예정입니다.
목차
-
Generic 카메라 모델의 3D → 2D
-
Generic 카메라 모델의 2D → 3D
-
Generic 카메라 모델 왜곡 보정을 위한 mapping 함수 구하기
-
Generic 카메라 모델 remap을 이용한 왜곡 영상 → 핀홀 모델 영상
-
Generic 카메라 모델 Pytorch를 이용한 왜곡 영상 → 핀홀 모델 영상
-
Brown 카메라 모델의 3D → 2D
-
Brown 카메라 모델의 2D → 3D
-
Brown 카메라 모델 왜곡 보정을 위한 mapping 함수 구하기
-
Brown 카메라 모델 remap을 이용한 왜곡 영상 → 핀홀 모델 영상
-
Brown 카메라 모델 Pytorch를 이용한 왜곡 영상 → 핀홀 모델 영상
화각에 따른 카메라의 종류
- 카메라에서 가장 중요한 부분 중 하나가 렌즈입니다. 핀홀 모델 카메라는 이론적으로 빛의 직진성을 이용하여 만든 이상적이면서 간단한 카메라 모델이지만 빛의 유입량이 적어 정상적인 이미지를 만들어낼 수 없습니다.
- 따라서 렌즈를 이용하여 카메라에 다양한 영역의 빛이 많이 유입될 수 있도록 (사람의 수정체와 같습니다.) 조절할 수 있습니다. 렌즈의 형태에 따라 카메라가 빛을 유입할 수 있는 영역이 달라지기 때문에 아래 그림과 같이 렌즈에 따른 화각이 결정됩니다.

- 위 그림의 화각과
초점 거리 (focal length)
는 설명을 위한 예시이며 절대적인 기준은 아닙니다. - 이번 글에서는
표준 렌즈
를 사용하는표준 카메라
와어안 렌즈
를 사용하는어안 카메라
에서 렌즈로 인한 물체의 휘어지는Distortion
이 발생하였을 때 처리하는 방법에 대하여 살펴보도록 하겠습니다. - 본 글에서는 크게 2가지의 카메라 모델을 사용할 예정이며 각 카메라 모델의 이름은
Generic Camera Model
과Brown Camera Model
이며 이 모델의 간략한 내용은 글 아래에서 설명하겠습니다.
Radial Distotion과 Tangential Distortion
- 카메라 렌즈로 인하여 발생하는 왜곡은 크게
Radial Distotion
과Tangential Distortion
가 있습니다. 먼저Radial Distortion
부터 살펴보도록 하겠습니다.

- 위 그림은
Radial Distortion
을 나타냅니다.Radial Distortion
은 빛이 렌즈로 입사할 때, 균등하게 들어오지 않고 영역 별로 불균등하게 들어오기 때문에 발생합니다. 이와 같은 이유는 카메라 렌즈를 의도적으로 설계하여 특정 영역을 더 많이 볼 수 있도록 만들기 때문입니다. - 예를 들어 넓은 영역을 보고 싶으면 렌즈 가장자리에 더 많은 빛을 모을 수 있어야 더 많은 빛이 들어와서 이미지 센서에 투영되어 상이 맺힐 수 있습니다.
- 따라서 실세계에서 빛은 직진하지만 카메라 렌즈로 인하여 굽어져서 들어오게 되어 영역 별로 빛이 많이 모이기도 하고 작게 모이기도 합니다. 이러한 이유로 이미지 안에서 물체가 굽어져 보이는 현상이 발생합니다.
- 카메라 렌즈 설계 방법에 따라 어떤 영역에 빛을 더 많이 모이게 할 지를 정할 수 있으며 방법에 따라서
Radial Distortion
이Barrel Distortion
이 되거나Pincusion Distortion
이 됩니다. Barrel Distortion
은 빛이 렌즈를 투과하였을 때, 바깥쪽으로 꺽이도록 설계되어 있습니다. 즉, 빛이 바깥 영역으로 점점 쏠리게 되어 더 넓은 영역을 볼 수 있도록 만듭니다. 이러한 이유로 넓은 영역을 봐야 하는 광각 카메라나 어안 카메라에서 이와 같은 왜곡이 발생합니다.- 반대로
Pincusion Distortion
은 빛이 렌즈를 투과하였을 떄, 안쪽으로 꺽이도록 설계되어 있습니다. 즉, 렌즈 가운데 영역으로 점점 쏠리게 되어 더 좁은 영역을 볼 수 밖에 없지만 더 멀리서 투영된 빛도 맺힐 수 있도록 만듭니다. 따라서 더 멀리 있는 영역을 봐야하는 원거리용 카메라에서 이와 같은 왜곡이 발생합니다. - 이와 같은
Radial Distortion
은 앞으로 다룰 카메라 모델에서Distortion Center (Image Center)
로 부터 계산된Radial Distance
를 다항 함수를 통하여 모델링 합니다. 이 내용은 아래 글에서 다루도록 하겠습니다.
Tangential Distortion
는 카메라 렌즈와 이미지 센서가 평행하게 장착되어 생산되지 못하였을 때 발생하는 왜곡입니다.Tangential Distortion
이 발생하면 이미지는 비스듬히 기울어져 있습니다. 이러한 이유로 직선이 약간 굽어보이게 됩니다.

- 카메라 렌즈와 이미지 센서가 평행하지 않으면 위 그림과 같이 기울어지게 되며 왜곡이 발생하게 됩니다.
Generic 카메라 모델과 Brown 카메라 모델
Generic Camera Model
은 이름 그대로 어안 렌즈부터 망원 렌즈 까지 모두 사용 가능한범용적인 카메라 모델
이며 특히 화각이 120도 이상의 광각 렌즈에서 효과를 발휘합니다. 결론적으로는Generic Camera Model
하나만 잘 활용해도 180도 이하 화각의 카메라에서는 충분히 잘 사용할 수 있습니다.Brown Camera Model
은 보통 화각이 100도 이하인 카메라 환경에서 주로 사용합니다.Generic Camera Model
에 비해 계산도 간단한 장점도 있습니다. 다만Generic Camera Model
과 같이 넓은 화각에서는 이 카메라 모델을 사용할 수 없습니다. 사용 시, 정확성이 많이 떨어지게 됩니다.Brown Camera Model
은 간단히 원거리 용도의 카메라에 주로 사용한다고 생각하면 되며Pinhole Camera Model
에 가깝습니다.
- 앞으로 살펴볼 식을 보면
Generic Camera Model
은Tangential Distortion
을 무시하고Radial Distortion
에 집중하여 다항식으로 모델링 한 것을 살펴볼 수 있습니다. 반면Brown Camera Model
은 적당한 다항식 차수의 다항식으로Radial Distortion
을 모델링하고 2차 다항식으로Tangential Distortion
을 모델링합니다.Generic Camera Model
에서 이와 같은 방식을 취하는 이유는 화각이 넓은 카메라에서는Radial Distortion
의 영향이 크기 때문에Tangential Distortion
을 무시할 수 있으며 생산 기술의 발전으로 카메라 렌즈와 이미지 센서가 평행에 가깝게 생산될 수 있어Tangential Distortion
를 실질적으로 무시할 정도가 되기 때문입니다. 따라서Brown Camera Model
에서도Tangential Distortion
을 무시하기도 하며 이와 같은 경우에는Generic Camera Model
과 유사해 집니다. - 어떤 카메라 모델을 사용해야 할 지 고민이 된다면
Generic Camera Model
을 고민없이 사용하는 것이 좋은 방법일 수 있습니다.
Generic 카메라 모델
Generic 카메라 모델의 3D → 2D
Generic 카메라 모델의 2D → 3D
Generic 카메라 모델 왜곡 보정을 위한 mapping 함수 구하기
- 실습을 위해 사용한 데이터는 아래 링크를 사용하였습니다.
- 링크 : https://medium.com/@kennethjiang/calibrate-fisheye-lens-using-opencv-part-2-13990f1b157f
- 본 글에서 사용한 이미지를 그대로 사용하시려면 아래 링크에서 다운 받으시면 됩니다.
- 링크 : https://drive.google.com/file/d/1ApfPPwRIcTVdkZA3Mfwqqg17PlzLdBd2/view?usp=share_link
Generic 카메라 모델 remap을 이용한 왜곡 영상 → 핀홀 모델 영상
Generic 카메라 모델 Pytorch를 이용한 왜곡 영상 → 핀홀 모델 영상
Brown 카메라 모델의 3D → 2D
Brown 카메라 모델의 2D → 3D
Brown 카메라 모델 왜곡 보정을 위한 mapping 함수 구하기
- 실습을 위해 사용한 데이터는 아래 링크를 사용하였습니다.
- 링크 : https://data.caltech.edu/records/jx9cx-fdh55
- 본 글에서 사용한 이미지를 그대로 사용하시려면 아래 링크에서 다운 받으시면 됩니다.
- 링크 : https://drive.google.com/file/d/1MaWrXvGuudMld2prhGk_KQDM4Q5qjpw9/view?usp=share_link
- opencv에서는
undistort
함수를 통하여 왜곡 보정을 하거나initUndistortRectifyMap
을 이용하여 왜곡 보정하는 방법이 있습니다. - 본 글에서는
initUndistortRectifyMap
을 이용하여map_x
,map_y
를 구하고 이 값을 이용하여remap
함수를 사용하여 이미지 전체를 왜곡 보정하거나 포인트의 매핑을 이용하여 포인트 단위로 왜곡 보정하는 방법에 대하여 살펴보도록 하겠습니다. remap
함수를 사용하는 방식을 소개하는 이유는 이 방법이 실제 사용하기에 현실적이며undistort
함수는 느려서 실시간으로 사용할 수 없기 때문입니다. 시간 측정 시, 수백배의 시간 차이가 나는 것을 확인할 수 있습니다.
Brown 카메라 모델 remap을 이용한 왜곡 영상 → 핀홀 모델 영상
remap
함수는 입력 이미지의 x, y 좌표를 출력 이미지의 x, y 좌표 어디에 대응시켜야 할 지 대응 관계를 아래 코드에서 살펴볼map_x, map_y
에 정의해 두고 그 관계를 매핑 시켜주는 함수 입니다.remap
함수는 입력과 출력이 비선형 관계이어서 관계식이 복잡할 때, 간단히 픽셀 별 대응을 통하여 복잡한 비선형 관계를 매핑 관계로 단순화 하기 때문에 연산도 간단하고 컨셉도 단순하여 많이 사용합니다.- 관련 링크 : remap 함수를 이용한 remapping
remap
함수를 사용하기 위해서는map_x
,map_y
룰 구해야 하며 opencv의cv2.initUndistortRectifyMap
를 이용하여 이 값들을 구할 수 있습니다.- 앞에서 표준 카메라의 렌즈 왜곡
# 기존 intrinsic과 distortion을 이용하여 출력할 이미지 사이즈 크기의 왜곡 보정 영상을 생성하기 위한 방법
# 아래 함수를 통해 왜곡 보정된 이미지에서 동작하는 new_intrinsic을 구할 수 있음
new_intrinsic, roi = cv2.getOptimalNewCameraMatrix(
intrinsic, distortion, imageSize=(width, height), alpha, newImageSize=(new_width, new_height)
)
# (new_width, new_height) 크기의 undistortion 이미지를 만들어 냅니다.
# cv2.getOptimalNewCameraMatrix()의 newImageSize와 같은 크기로 만들어야 외곽의 여백을 최소화 할 수 있습니다.
map_x, map_y = cv2.initUndistortRectifyMap(
intrinsic, distortion, None, new_intrinsic, (new_width, new_height)
)
dst = cv2.remap(src, map_x, map_y, cv2.INTER_LINEAR)