How to do Internal Camera Calibration


서론

ROS2를 사용해서 카메라 내부 캘리브레이션 하는 방법에 대해 설명한다.

Dependencies

카메라 렌즈와 센서의 특성 때문에 발생하는 영상 왜곡을 수학적으로 계산하여 보정값을 찾아내는 프로그램으로 실시간으로 ROS 토픽(image_raw)을 구독(Subscribe)하여 화면을 보면서, 그 위에서 직접 캘리브레이션을 진행한다.

sudo apt update
sudo apt install ros-<distro>-camera-calibration

# 예: Humble의 경우
sudo apt install ros-humble-camera-calibration

카메라 장치 연결확인

카메라가 연결되었는지 확인한다.

보통 /dev/video0 또는 /dev/video1 등으로 나타난다.

ls /dev/video*

카메라를 ROS2 토픽 발행을 통해 이미지를 보고싶다면 v4l2_camera라는 프로그램을 설치해야한다.

만약 이 패키지가 없다면, 직접 C++나 Python으로 OpenCV 등을 이용해 카메라 영상을 캡처하고, 이를 ROS 메시지 구조체에 일일이 담아서 pub.publish() 하는 코드를 짜야 하지만 v4l2_camera 패키지를 설치하면 카메라 이미지를 ROS2 환경에서 쓸 수 있도록 해주는 프로그램이다.

sudo apt update
sudo apt install ros-humble-v4l2-camera

Image Publish

이제 드라이버를 실행하여 이미지를 Ros2 topic형태로 Publish한다.

ros2 run v4l2_camera v4l2_camera_node

# 만약 카메라 장치 번호가 0번이 아니라면? (예: /dev/video2인 경우)
ros2 run v4l2_camera v4l2_camera_node --ros-args -p video_device:="/dev/video2"

실행하면 아래 처럼 에러가 뜨는데

  • Starting camera: 카메라가 정상적으로 작동하기 시작
  • Unable to open camera calibration file: 아직 캘리브레이션을 안 했기 때문에 설정 파일(.yaml)이 없다. 이걸 만들기 위해 지금 캘리브레이션을 하려는 것이므로 무시해도 된다.
  • Permission denied (13): 일부 카메라 제어 기능(밝기 자동 조절 등)에 대한 권한 문제인데, 이미지를 가져오는 데는 지장이 없다.

그리고 토픽을 봐보면 아래 /image_raw, /camera_info라는 토픽이 발행되는걸 볼 수 있다.

하나는 그냥 카메라가 내뱉은 이미지 픽셀값이고 두번째는 캘리브레이션 정보 값들이다.

Camera Calibration 진행

Checker Board준비

아래 링크에서 체커 보드를 준비해준다.

그리고 체커보드 스펙을 확인한다.

이제 체커보드를 준비하고, 노드를 실행 중인 터미널은 그대로 둔 채 새 터미널에서 아래 명령어를 입력한다.

ros2 run camera_calibration cameracalibrator --size 10x7 --square 0.025 image:=/image_raw camera:=/
  1. --size 10x7: 설정한 체커보드의 내부 교차점 개수입니다. (칸 수가 아니라 선이 만나는 지점의 개수)
    • 만약 가로 9칸, 세로 7칸짜리 보드라면 선의 갯수 임으로 8x6로 설정해야 한다.
  2. --square 0.025: 체커보드 한 칸의 실제 길이를 미터(m) 단위로 적어야한다.
    • (예: 2.5mm = 2.5cm = 0.024m)
  3. image:=/image_raw: 현재 카메라 노드가 발행 중인 원본 이미지의 토픽 이름입니다.
  4. `camera:=/: 카메라 노드의 네임스페이스
    • 나중에 카메라를 2대 연결하면, 한 대는 camera:=/left, 다른 한 대는 camera:=/right 이런 식으로 구분하기 위해 사용한다. 지금은 한 대뿐이고 토픽 이름이 /camera_info임으로 /로 설정하면 된다.
    • camera:=/: "내 카메라 정보 토픽은 그냥 /camera_info야."
    • camera:=/v4l2_camera: "내 카메라 정보 토픽은 /v4l2_camera/camera_info라는 폴더 안에 있어."

게이지 채우기

프로그램을 실행하면 나오는 X, Y, Size, Skew 게이지를 초록색이 될 때 까지 채워야한다.

  • X, Y: 보드를 좌/우, 위/아래 구석구석으로 가져간다. (렌즈 주변부 왜곡 측정)
  • Size: 보드를 카메라에 아주 가깝게, 그리고 아주 멀게 움직인다.
  • Skew: 보드를 좌우로 45도 정도 확 기울여서 보여준다. (이게 바로 "반듯하지 않은" 상태를 측정하는 것)

Calibration Result

캘리브레이션하는데 조금 기달려야 하며 끝나면 아래 처럼 뜬다.

  • D (Distortion): 렌즈의 휘어짐 정도입니다. 첫 번째 값이 -0.37로 음수이므로, 전형적인 배럴 왜곡(볼록하게 튀어나오는 왜곡)이 있음을 알 수 있다.
  • K (Camera Matrix): 카메라의 초점 거리와 중심점
  • P (Projection): 왜곡을 편 후, 3D 공간을 2D 평면으로 투영할 때 사용하는 행렬

이제 완료됬으면 프로그램에서 Calibrate 버튼을 눌러주고 SAVE버튼을 눌러 Camera Calibration 정보를 저장한다.

그러면 터미널에 캘리된 값들이 저장된 위치가 뜬다.

('Wrote calibration data to', '/tmp/calibrationdata.tar.gz')

이걸 압축 풀어서 적당한 폴더안에 넣어두자.

나는 /home/jj/workspace/stroller_proj/cali 위치에 저장해두겠다.

압축을 풀면 여러 장의 이미지 파일과 함께 ost.yaml, ost.txt 파일이 보인다.

여기서 ost.yaml가 중요하다.

❯ tar -xvzf /tmp/calibrationdata.tar.gz -C /home/jj/workspace/stroller_proj/cali

카메라에 Calibration값 적용하기

다시 토픽을 쏴주는 카메라 노드를 실행해야 한다.

camera_info_url:=file:// 이후에 위의 ost.yaml위치 경로를 넣어준다.

이렇게되면 아까 /image_raw 값과 /camera_info값을 퍼블리시 하는데, 캘리전에는 /camera_info값이 비여있었다면 지금은 ost.yaml(캘리값)을 넣어줘서 원본이미지와 캘리값도 같이 발행하게 된 것이다.

ros2 run v4l2_camera v4l2_camera_node --ros-args -p camera_info_url:=file:///home/jj/workspace/stroller_proj/cali/ost.yaml

경고 분석

  1. [WARN] [1770187553.657778028] [v4l2_camera]: [integrated_webcam_hd:_integrate] does not match narrow_stereo in file /home/jj/workspace/stroller_proj/cali/ost.yaml

이유:

실행하면 아래 처럼 WARN이 뜨는데, 카메라 드라이버가 인식한 실제 하드웨어 이름은 integrated_webcam_hd:_integrate인데, 캘리브레이션 파일(ost.yaml) 안에는 camera_name: narrow_stereo라고 적혀 있어서 발생한 경고임으로 이 부분의 값을 바꿔주자

camera_name 필드 부분을 integrated_webcam_hd:_integrate 로 바꿔주자

vim ost.yaml

이후 다시 실행하면 해당 경고가 사라진다.

  1. [WARN] [1770187900.776752570] [v4l2_camera]: Image encoding not the same as requested output, performing possibly slow conversion: yuv422_yuy2 => rgb8

Ros2에서 요구하는 이미지출력포멧이 RGB인데 카메라 자체는 RawData인 yuv값을 내보내고 있어

이를 변환하는 과정에서 카메라 이미지를 보여주는 성능이 느려질 수 있다는 이야기다.

일단은 크게 문제가 되지 않으니 넘어간다.

Calibration 확인하기

이제 카메라 노드가 발행하는 원본이미지 토픽, 캘리 토픽 두 토픽을 받아

실제로 계산해서 왜곡 보정된 영상을 실시간으로 생성해주는 도구가 image_proc이다.

사용 중인 ROS 2 배포판(Humble, Foxy 등)에 맞춰 설치한다. (Humble 기준 예시)

만약 배포판이 다르다면 humble 자리에 본인의 버전을 넣는다.

sudo apt update
sudo apt install ros-humble-image-proc

이전에 했던 캘리된 파일을 옵션으로 넣은 카메라 노드(v4l2_camera_node)가 켜져 있는 상태에서

즉, 아래 명령어로 터미널이 켜진 상태에서

ros2 run v4l2_camera v4l2_camera_node --ros-args -p camera_info_url:=file:///home/jj/workspace/stroller_proj/cali/ost.yaml

새 터미널을 열고 아래 명령어를 입력한다.

카메라 노드가 발행하는 /image_raw + /camera_info 를 가지고 실제 계산해서 캘리된 이미지를 발행해라!

⇒ /image_rect(rectify의 약자로 바로잡다 라는 뜻이다)

ros2 run image_proc rectify_node --ros-args -r image:=/image_raw -r camera_info:=/camera_info

위 명령어는 자동으로 /image_raw와 /camera_info를 조합해서 /image_rect라는 보정된 영상 토픽을 만들어낸다.

뷰어 실행

rqt에서 진행하니 렉이 너무 걸리고 프레임도 뚝뚝 끊킨다.

ros2 run rqt_image_view rqt_image_view

Rviz에서 실행하면 문제가 없음으로 Rviz에서 실행하자

rviz2
  1. 좌측 하단에 있는 [Add] 버튼을 클릭한다.
  2. 팝업창 상단의 [By Topic] 탭을 클릭한다.
  3. 목록에서 /image_raw 또는 /image_rect 항목을 찾은 뒤, 그 아래에 있는 [Image]를 선택하고 [OK]를 누른다.
    • 참고: 이때 /image_raw를 선택하면 원본 영상, /image_rect를 선택하면 캘리브레이션이 적용된 영상을 보게 된다.

왼쪽이 캘리가 안된 영상이고 오른쪽이 캘리가 된 영상이다. 같은 텀블러인데도 모양이 달라보이는 것이 보일 것이다.