Konsla Hobby
konsla99 님의 블로그 입니다.
Category
카메라 캘리브레이션 (Camera Calibration) 이론)
캘리브레이션
cv::calibrateCamera(); 활용
- OpenCV가 카메라 파라미터를 자동 계산한다.
- 여러 각도에서 촬영 -> 이미지마다 변하는 상대적 위치, 방향, 내부 파라미터 계산
여러각도에서 보기 위해서 대상을 회전, 평행이동이 필요하다.
회전행렬
$$R_x(\psi) = \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos\psi & -\sin\psi \\0 & \sin\psi & \cos\psi\end{bmatrix}R_y(\varphi) = \begin{bmatrix}\cos\varphi & 0 & \sin\varphi \\0 & 1 & 0 \\-\sin\varphi & 0 & \cos\varphi\end{bmatrix} R_z(\theta) = \begin{bmatrix}\cos\theta & -\sin\theta & 0 \\\sin\theta & \cos\theta & 0 \\0 & 0 & 1\end{bmatrix}$$
$$R = R_x(\psi) R_y(\varphi) R_z(\theta)$$ $$R\cdot R^T = I$$
평행 이동 벡터
$$\vec{T} = \vec{O}_{\text{obj}} - \vec{O}_{\text{cam}}$$
최종 좌표 이동
$$\vec{P}_c = R(\vec{P}_o - \vec{T})$$
캘리브레이션 보드
카메라 파라미터를 추정하기 위해 3D공간의 점이 2D이미지에서 어떻게 보이는지 대응점이 필요하다. 이를 위해 캘리브레이션 패턴을 활용한다.
- 체스보드
- 원형 그리드
- QR코드
이러한 패턴은 이미지상의 좌표를 알기 쉽기 때문에 사용된다.
체스 보드 : findChessboardCorners()

bool cv:findChessboardCorners(
cv::InputArray image, //8비트 체스판 이미지
cv::size PatternSize, //행, 열당 코너의 수
cv::OutputArray corners,// 검출된 코너를 저장
//보조 옵션
int flags = cv::CALIB_CB_ADAPTIVE_THRSH
+ cv::CALIB_CB_NOMALIZE_IMAGE
)
- 코너란 내부의 코너를 좌표로 저장
- 기본적으로 평균 밝기에 따라 이미지의 임계값을 지정
- 플레그 사용시 적응형 임계값을 사용
- NOMALIZE_IMAGE : 임계값 도달전 equalizeHist로 정규화
- FILTER_QUADS: 검은 사각형의 투영도에서 얻은 사각형을 찾는다.
- 근사법이며, 방사 왜곡 존재시 이방법은 참이 아님
- FAST_CHECK: 빠른 스캔후 코너가 없으면 이미지 스킵
- (체스판이 없는 이미지가 있다면 사용)
cv::cornerSubPix()
//findChessboardCorners()가 대략적인 위치만 얻음
//상대적인 위치 보정을 위해 사용
bool cv:drawChessboardCorners(
cv::InputArray image, //입출력할 이미지(8UC3)
cv::size PatternSize, //행, 열당 코너의 수
cv::OutputArray corners,// 검출된 코너를 저장
bool patternWasFound // find함수의 반환값
)
- 코너는 색상있는 원으로 표기
- 따라서 8UC3이미지 필요
원형 그리드 : findCirlcesGrid()

- findChessboardCorners() 와 같은 방식으로 처리
- 사용하는 이미지가 다를 뿐이다.
- 이때 코너대신 검출된 원의 중심 좌표를 반환한다.
- 이미지와 같은 비대칭형 그리드를 많이 사용한다.
비대칭형 그리드
- 행과 열을 기억하는것이 중요하다.
- 반복 수행 결과에서 안정성, 결과의 질이 체스판보다 우수하다.
호모그래피
- 한 평면에서 다른 평면 까지의투영 매핑
- 2차원 평면상의 한 점을 카메라의 촬영센서에 매핑하는것
$$\vec{q} = \begin{bmatrix} x \\ y \\ w \end{bmatrix}, \vec{Q} = \begin{bmatrix} X \\ Y \\ Z \\ 1 \end{bmatrix}$$
$$\vec{q}=s \cdot H \cdot \vec{Q}$$
여기서 H는 실제좌표를 이미지 평면에 옮기는 과정으로 내부 파라미터* (회전+ 평행이동) 임을 알 수 있다.
Q = 3차원 좌표의 이미지 평면의 2차원 동차좌표다. 따라서 Z = 0 이 되므로 다음과 같은 수식이 성립한다.
$$q = K \begin{bmatrix} r_1 & r_2 & r_3 & t \end{bmatrix} \begin{bmatrix} X \\ Y \\ Z \\ 1 \end{bmatrix}$$
$$=> q = K \begin{bmatrix} r_1 & r_2 & t \end{bmatrix} \begin{bmatrix} X \\ Y \\ 1 \end{bmatrix}$$ $$\vec{q} = s \cdot H \cdot \vec{Q}일 때 H = M \cdot [r_1 r_2 t]$$
cv::findHomography(
cv::InputArray srcPoints, //2차원 소스 점
cv::InputArray dstPoints, //2차원 결과점
cv::size method = 0 //
double ransacReprojThreshold =3 //최대 재투영 오차
cv::OutputArray mask = cv::noArray,//0이 아닌 점에 대해서만 사용
)
- InputArray 는 원본 평면, 대상 평면의 점
- 2차원의 점이므로 CV_32FC2 요소인 Nx2, Nx1 배열
- method = 0 이면 모든 점을 고려해 재투영 오차 최소화
- 재투영 오차는 원본의 점과 대상의 점 사이를 H배한 유클리드 거리의 제곱 합
- ransacReprojThreshold : RANSAC 에서만 사용됨
- mask : robust 방식에서만 사용,어떤점이 H계산에 사용됐는지 표기
Noise가 많은 경우
method에서 알고리즘을 수정할 수 있다. 3가지 robust 방식을 제공
RANSAC방식
- 입력된 점의 부분집합을 무작위 선택
- 해당 집합의 호모그래피 행렬 계산
- 초기추정과 대략일치하는 점을 찾는다.
- 가장 많은 정상치를 갖는 경우를 찾는다.
LMeds 알고리즘
- 제곱의 최소 중간값 이ㅏㄹ고리즘
- 기존의 평균 제곱 오차 최소화가아닌 중간값 오차 최소화
- 정상치가 50%이상인 경우 사용
RHO
- Ransac에 PROSAC 가중치 적용
- 이상치가 많은 경우 더 빠르다
'Computer Vision > 캘리브레이션' 카테고리의 다른 글
| 카메라 캘리브레이션 - 왜곡 제거 (0) | 2026.03.15 |
|---|---|
| 카메라 캘리브레이션 (0) | 2025.10.23 |
| 카메라 모델과 캘리브레이션-카메라모델 (1) | 2025.10.21 |
| 카메라 캘리브레이션 (Camera Calibration) 이론 (0) | 2025.10.19 |