카메라 캘리브레이션 및 YOLO를 이용한 거리 검출 (작성중)

이용욱·2023년 1월 6일
0

Camera

목록 보기
4/4
post-thumbnail

본 포스팅은 카메라(웹캠)을 사용해서 캘리브레이션, 라벨링, 거리 추정까지 진행한다.

Window 환경
PC : Desktop
OS : Window 10
CPU : I7-8700
GPU : GTX 1660TI
CUDA : 11.7 ver.
Memory : 32GB
Camera : Logitech Streaming Webcam
Matlab : R2021a Academic ver.
Editor : VS code

Linux 환경
PC : Desktop
OS : Ubuntu 18.04
CPU : I9-10990
GPU : GTX 1660 TI
CUDA : 11.7 ver.
Memory : 32GB
Camera : Logitech Streaming Webcam
Editor : VS code

0. 오토포커스 끄기

캘리브레이션을 하기 전에 카메라가 가지는 오토포커스 기능을 꺼줘야 한다.

0-1. 윈도우 환경

0-2. 리눅스 환경

오토포커스 끄는 방법

1. 카메라 캘리브레이션

1-1. 전 작업 in Matlab(윈도우)

먼저 체커보드를 다운해서 프린트 해주자.
체커보드 Pattern Generator

적당히 값을 선택해주고, 프린트하여, 카메라 앞에 들고 사진을 30장 이상 찍어주자.

카메라 캘리브레이션을 하기 위해 Window에서 Matlab을 사용한다. Matlab 프로그램에서 위에 있는 탭 중에 '앱'을 클릭하고, Camera Calibrator를 선택한다.

그리고 'Add images'를 클릭하고,

아래와 같이 켈리브레이션에 사용할 이미지를 드래그 해준다. 사진은 최소 30장 이상 찍어서 넣어주길 바란다.

그리고 캘리브레이트를 선택하면 각 사진들에 대한 재투영 평균 에러가 계산되어 오른쪽 그래프에 나타난다. 뿐만 아니라 사진 전체의 평균 에러도 알 수 있어, 빨간색 선인 threshold를 전체 평균에(overall mean error) 맞춰 내려주면 오차가 큰 이미지들은 제외되고 오차가 작은 이미지만을 이용하여 파라미터 추출이 이뤄지게 된다. mean error가 작으면 좋지만 보통 1미만이면 사용 가능하다고 본다. threshold를 내려주고 export paremeter를 클릭하자.

결과적으로 아래와 같은 파라미터들이 추출되고,

여기서 우리가 필수적으로 사용할 파라미터는 Instrinsics parameter이다. 이는 카메라 자체가 가지는 고유의 파라미터 값이라고 생각하면 되고, 파라미터 종류로는 초점거리(focal length), 주점(principal point) 등이 있다.

Instrinsics parameter 안에 들어가면, 다음과 같은 값들이 나오고, 이를 가지고, 추후에 행렬을 생성해야 한다.
Focal length(초점 거리)
Principal point(주점)
Radial Distortion(방사 왜곡)
Tangential Distortion(접선 왜곡)

맨 밑에 instrinsic Matrix에도 focal length, principal point 등이 나오는데,
일반적인 intrinsic matrix는 아래와 같은 형태로 나타나지만,
[fxSkewccx0fycy001]\begin{bmatrix} {f}_x & Skew_-c&{c}_x\\0 & f_y & c_y\\0&0&1\end{bmatrix}
Matlab에서 계산한 결과는 아래와 같이 나오니 주의하여 알맞게 사용하자.
[fxSkewc00fy0cxcy1]\begin{bmatrix}{f}_x&Skew_-c&0\\0&f_y&0\\{c}_x&c_y&1\end{bmatrix}

fx, fy : focal length
cx, cy : principal point
skew_c = skew coefficient

필자의 경우,
fx: 782.6854, fy: 782.0603, cx: 885.3967, cy: 364.155., skew_c: 0 이며,
Radial Distortion(방사 왜곡)계수는
k1: -0.0919, k2: 0.0432 k3: 0(일반적으로 0)
Tangential Distortion(접선 왜곡)계수는
p1: 0, p2: 0 이다.

skew_c가 0으로 나오는 이유는 요즘의 현대 카메라들은 이 값이 극히 작기 때문에 0으로 가정해도 무방하다.

참고
Radial Distortion​
xdistorted=x(1+k1r2+k2r4+k3r6){x}_{distorted} = x\left(1+{k}_1{r}^2+{k}_2{r}^4+{k}_3{r}^6\right)
ydistorted=y(1+k1r2+k2r4+k3r6){y}_{distorted} = y\left(1+{k}_1{r}^2+{k}_2{r}^4+{k}_3{r}^6\right)
Tangential Distortion
xdistorted=x+[2p1xy+p2(r2+2x2)]{x}_{distorted}=x+\left[2{p}_1xy+{p}_2\left({r}^2+2{x}^2\right)\right]
ydistorted=y+[p1(r2+2y2)+2p2xy]{y}_{distorted}=y+[{p}_{1}​({r}^{2}+2{y}^{2})+2{p}_{2}​xy]
∴ Distortion Coefficients(왜곡 계수) =(k1 k2 p1 p2 k3)({k}_1 \ {k}_2 \ {p}_1 \ {p}_2 \ {k}_{3})

앱에 대한 더 자세한 이론과 설명은 Mathworks 홈페이지를 참고 바란다.
Matlab Calibration App

1-1-1. Calibration 보정 작업

Calibration 값을 카메라에 적용해서 왜곡을 없애는 작업을 한다. 필자는 python으로 코드를 작성했고, cv를 이용해 웹캠을 읽어서 Calibration 하는 시퀀스를 가진다. 본인들이 원하는 방식대로 맞춰 사용하길 바란다.
mtx는 focla length, principal point를 사용하며, dist는 왜곡 계수를 사용한다.

mtx  = np.array([[782.6854,0,885.3967],[ 0,782.0603,364.1553],[0,0,1,]]) # [(fx,0,cx),(0,cy, fy),(0,0,1)]
dist = np.array([[-0.0919, 0.04332, 0, 0, 0]]) # k1, k2, p1, p2, k3 # (k : RadialDistortion, p : TangentialDistortion)

cap = cv.VideoCapture(0) # 기본 : 0

while True:
    ret, frame = cap.read()
    if not ret:
        break

    if ret == True:
        img_undist = cv.undistort(frame, mtx, dist, None, mtx)
        if cv.waitKey(20) & 0xFF == ord('q'):
            break
    else:
        break
    cv.imshow('frame_calibration',img_undist)
    cv.imshow('frame_original',frame)
cv.destroyAllWindows()
cap.release()

1-2. 전 작업 in ROS(리눅스)

체커보드를 다운해서 프린트 해주자.
체커보드 Pattern Generator(현재 이미지 다운이 안됨.2023년 01월)
http://wiki.ros.org/camera_calibration/Tutorials/MonocularCalibration?action=AttachFile&do=get&target=check-108.pdf
A4 용지에 출력한 체커보드를 이용한다. 출력한 체커보드 Calibration 에 사용되는 체커보드는 9x8 의 체크무늬를 가지고 있지만 흑, 백의 사각형의 교차점의 개 수 8x6 체커보드라고 말한다. 체크무늬를 구성하는 정사각형의 한변의 길이를 측정한다. 측정 결과는 2.45(cm) = 0.0245(m) 이었다. 체커보드를 이용한 Calibration 을 시작하기 전에 Calibration 이 필요한 해당 카메라를 이용한 image_raw 토픽이 ROS 네트워크에 발행 중이어야 한다.

rosrun camera_calibration cameracalibrator.py --fix-aspect-ratio --size 8x6 --square 0.0245 image:=/usb_cam/image_raw camera:=/usb_cam

1-2-1. 전 작업 in ROS(리눅스 환경)

2. 라벨링(Labeling) - Yolo Mark

만약 Could not locate zlibwapi.dll. Please make sure it is in your library path! 라는 에러가 뜨면, zlibdll이 CUDA 폴더 내에 없다는 뜻이다.
C:\Program Files\Microsoft Office\root\Office16\ODBC Drivers\Salesforce\lib 에서 zlibdll을 찾아 복사하고,

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.7\bin 에 붙여 넣으면 된다.


profile
자율주행에 관심이 있으며, Lidar SLAM을 공부하고 있습니다. [개인 홈페이지 : https://woogiee.wixsite.com/youngwooklee]

3개의 댓글

comment-user-thumbnail
2023년 4월 21일

혹시 카메라와 yolo만을 이용해 거리를 측정할 수 있나요? 고정된 실내라면 가능할까요...?

2개의 답글