검색결과 리스트
글
solvePnP 함수 사용법과 Rodrigues 표현법
opencv의 solvePnP 함수 사용법과 3차원 회전변환을 표현하는 한 방법인 Rodrigues' rotation formula에 대한 내용입니다.
1. solvePnP 사용법
solvePnP 함수는 영상을 획득한 카메라의 위치 및 방향 (camera pose)을 알아낼 때 유용하게 사용할 수 있습니다만, 인터넷에 사용법 정보가 잘 없는 것 같아 여기에 적어봅니다.
[solvePnP 사용예제]
// matching pairs
vector<Point3f> objectPoints; // 3d world coordinates
vector<Point2f> imagePoints; // 2d image coordinates
// camera parameters
double m[] = {fx, 0, cx, 0, fy, cy, 0, 0, 1}; // intrinsic parameters
Mat A(3, 3, CV_64FC1, m); // camera matrix
double d[] = {k1, k2, p1, p2}; // k1,k2: radial distortion, p1,p2: tangential distortion
Mat distCoeffs(4, 1, CV_64FC1, d);
// estimate camera pose
Mat rvec, tvec; // rotation & translation vectors
solvePnP(objectPoints, imagePoints, A, distCoeffs, rvec, tvec);
// extract rotation & translation matrix
Mat R;
Rodrigues(rvec, R);
Mat R_inv = R.inv();
Mat P = -R_inv*tvec;
double* p = (double *)P.data;
// camera position
printf("x=%lf, y=%lf, z=%lf", p[0], p[1], p[2]);
위에서 구한 P는 카메라의 위치를 나타내고, 회전변환(월드좌표->카메라좌표) 행렬 R로부터는 카메라의 자세(방향) 정보를 추출할 수 있습니다.
2. Rodrigues' rotation formula (이하 2014.4.22 추가된 내용)
opencv의 solvePnP 함수에서 반환되는 rvec는 Rodrigues를 컴팩트(compact)하게 표현한 벡터입니다. 먼저, Rodrigues가 무엇인지 살펴본 후 opencv에서 사용하는 Rodrigues 표현법에 대해 살펴보겠습니다.
3차원에서 회전변환은 보통 3 × 3 행렬로 표현됩니다. 그런데, Rodrigues를 사용하면 임의의 3차원 회전변환을 4개의 값(회전축 벡터 + 회전각) 만으로 표현할 수 있습니다. 3차원 공간에서 점 p를 회전축 v에 대하여 θ만큼 회전시킨 값은 다음 식에 의해 계산될 수 있는데, 이 식을 Rodrigues' rotation formula라고 부릅니다 (Rodrigues는 이 식을 만든 프랑스 수학자의 이름).
--- (1)
이 때, v는 단위벡터(unit vector)이어야 하고 회전방향은 오른손 법칙을 따릅니다 (엄지를 펴고 오른손을 쥐었을 때 엄지의 방향이 회전축 방향, 쥔 손가락의 방향이 + 회전방향).
식 (1)을 행렬 형태로 표현하면 다음과 같습니다.
--- (2)
식 (2)로부터 Rodrigues v = (vx,vy,vz), θ에 대응하는 회전변환 행렬 R이 다음과 같음을 알 수 있습니다.
--- (3)
식 (3)은 우리가 임의의 회전축에 대한 회전을 회전변환 행렬로 표현할 수 있음을 나타냅니다.
반대의 경우로, 임의의 회전변환 행렬에 대한 Rodrigues 표현은 다음 수식을 이용하여 구할 수 있다고 합니다 (참조: 위키피디아).
--- (4)
3. opencv에서의 Rodrigues 표현
opencv에서는 회전변환행렬 표현과 Rodrigues 표현 사이의 상호 변환을 위해 Rodrigues()란 함수를 제공합니다. 그런데, opencv에서 사용하는 Rodrigues 표현은 보다 컴팩트(compact)한 형태로서 단 3개의 값만으로 회전변환을 표현합니다.
opencv API 설명문서에 따르면 원래 회전변환은 3 자유도이기 때문에 opencv에서는 회전변환을 rod2 = [a, b, c]의 3차원 벡터로 컴팩트하게 표현하고 이로부터 회전각(θ) 및 회전축 벡터(v)는 다음과 같이 추출합니다.
--- (5)
--- (6)
이와같이 solvePnP 함수에서 반환되는 rvec는 Rodrigues에 대한 3차원의 컴팩트한 표현법이므로 회전각 및 회전축을 알기 위해서는 식(5), 식(6)을 이용해야 합니다.
by 다크 프로그래머
'영상처리' 카테고리의 다른 글
카메라의 초점거리(focal length) (50) | 2013.10.23 |
---|---|
solvePnP 함수 사용법과 Rodrigues 표현법 (77) | 2013.09.25 |
매치무브(MatchMove)의 세계 (17) | 2013.09.11 |
이미지 센서와 Raw Bayer Pattern (베이어 패턴) (28) | 2013.09.10 |
설정
트랙백
댓글
- 이전 댓글 더보기
-
혹시..solvepnp의 pnp중 p3p에 대한 자료가 있는 링크를 알고계시면 혹시 알려주실수 있으신가요?
그리고 간단하게나마 시간이 나신다면 p3p에 대해 설명해주실수 있으신가요? 생각만큼 자료가 많지 않은것 같아서요...아니면..검색 키워드라도...ㅠ -
안녕하세요, Camera Calibration 프로그램 글에서 질문을 드렸는데,
이번에는 이 글에서 또 질문을 드리게 되었네요.
제가 지금 하려고 하는 것이, 다크프로그래머 님께서 이 글에서 올려주신 코드로 회전행렬 R과 평행이동 tvec을 이용해, 영상에서의 좌표를 가지고 월드 좌표계에서의 실제 좌표를 찾으려고 하고 있습니다. A의 값은 다크프로그래머님이 올려주신 프로그램을 이용해 구했구요.
<타겟 추적을 위한 카메라의 팬,틸트 제어>와 <Extrinsic Camera Calibration - 카메라의 위치 및 자세 파악>에 올려주신 방법을 사용해서, 영상에서 점의 좌표 (x,y)에 대해서 test_point = [x;y;1] 의 matrix를 만들어 R_inv*(A_inv*test_point - tvec) 과 같은 식으로 구했습니다.(A_inv는 intrinsic parameter를 나타내는 행렬 A의 역행렬입니다.)
그런데 말도 안되는 값이 계속 나오네요, 위 코드를 이용해서 구한 카메라의 위치와 거의 비슷한 값이 나옵니다.
제가 잘못한 점이 무엇일까요?
-
다크pgmr 2015.07.07 17:33 신고
안녕하세요. 최근에 다른 분의 비슷한 질문에 대해서 답변을 드렸던 기억이 납니다. 먼저, http://darkpgmr.tistory.com/82#comment10908438 코멘트를 참조하시기 바랍니다.
가장 큰 문제점은 2D 영상좌표에서 3D 월드좌표를 복원할 수 없는데, 구하고자 하신 점입니다. 사용하신 수식에서 구한 값은 카메라좌표계상의 좌표 A_inv*test_point에 대응하는 월드좌표입니다. A_inv*test_point가 카메라좌표계에서 카메라 원점에서 멀리 떨어져 있는 점이 아니라면 이로부터 구한 월드좌표는 당연히 카메라 원점에 대한 월드좌표(카메라 위치)와 유사하게 나올 것입니다. -
Astroboy 2015.07.09 00:15
답변 감사합니다. 결국에 안되는 이유가 카메라좌표계상에서의 Z값이 없는 상태에서 3D 복원을 하려고 해서 그런 것이군요.
만약 어떠한 정해진 평면(plane) 위에서 움직이는 점을 카메라가 정면이 아니라 비스듬하게 바라보고 있는 상황이라면, 2D to 2D에 관한 관계이니까 충분히 서로 복원할 수 있을 것 같은데요.
직접 기울어져 있는 상황의 각도를 재서 projection되는 식으로 하면 될 것 이라고 생각이 되는데, 그 각도를 정확히 재는게 잘되지 않아서 다른 방법을 찾아보고 있는 중입니다.
이러한 경우에는 2D-2D 변환이니 homography 변환을 구해서 (아는 기준점을 이용해 findHomography()를 사용) 하는 것이 현명한 방법일까요? 아니면 다크프로그래머 님께서 알려주신 extrinsic parameter R,t를 이용해 정해진 2D로 변환하는 방법이 있을까요?
조언 부탁드립니다. 감사합니다.
-
-
-
안녕하세요~
카메라에서 인식한 마커의 네 개의 꼭짓점을 이용해 카메라의 위치와 방향을 알고자 하는데요,
제가 지금 카메라 영상을 이미 calibration을 통해 왜곡을 보정했고,
왜곡이 펴진 이미지 프레임을 영상 처리하고 있습니다.
보니까 solvePnP에서 camera parameter를 사용하는데 이건 왜곡이 보정되기 전의 이미지 프레임으로 꼭짓점을 구해야 하는건가요? -
좋은글 너무 감사합니다.
extrinsic parameter 추정을 해야하는 상황인데요 지식이 부족하여 몇가지 질문을 드리고자 합니다.
위에서 tvec와 camera position을 구하였는데 어째서 두 값이 다른건가요?
tvec은 이동행렬이기 때문에 월드좌표계의 원점을 중심으로 하는 카메라의 위치를 의미하는것이 아닌가요? 어째서 둘이 구분되는지 아직 저의 능력으로는 어렵네요
테스트 해본 결과 camera position이 제가 이해한 쪽으로 올바른 결과가 나오는것 같네요
저의 목적은 단순히 3x4의 변환행렬을 구하는 것인데 (실제 공간에서 물리적 좌표를 측정하였고, 이미지로부터 좌표값을 얻어서 solvePnP에 입력값으로 넣어주었습니다.)
이를 위해서는 rodriguez 출력 R과 tvec을 합치면 되는것인지 궁금합니다.-
다크pgmr 2015.10.06 17:27 신고
안녕하세요. OpenCV의 solvePnP로 구한 R, t는 월드좌표 W를 카메라 좌표 C로 변환시키는 것으로서 그 관계는 C = R*W + t입니다. 이 변환에 의해서 카메라의 위치에 대한 월드좌표 P가 카메라 좌표계에서는 0으로 이동해야 하므로 0 = R*P + t를 만족해야 합니다. 따라서, P = -R^-1*t 가 카메라 원점의 월드좌표가 됩니다.
언뜻 생각하면 t가 카메라의 월드좌표라고 생각하기 쉽습니다. 하지만 월드좌표를 카메라 좌표로 바꾸기 위해서는 회전시킨후 이동시키는 것이 아니라 먼저 평행이동을 시킨 후에 회전을 시켜야 합니다. 즉 C = R(W - p) = RW - Rp가 되어야 합니다. 그런데 solvePnP가 반환하는 R, t는 C=RW+t인 R, t이므로 위와 같은 변형이 필요합니다.
-
-
안녕하세요! 좋은글 감사합니다.
궁금한게 있는데 저는 체스보드와 cvFindExtrinsicCameraParams2 함수를 이용하여 rvec, tvec를 뽑아냈는데 저는 여기서 나오는 rvec값이 라디안 값인줄 알았는데 그럼 이것도 다크님이 설명하신 것처럼 로드리게스의 컴팩트한 값으로 봐야하는 것인가요? -
안녕하세요.
혹시 solvePnP 함수 내에서 어떤 수식을 수행하는지 알 수 있나요??
특정점에 대한 2차원 3차원 정보를 집어넣고, 내부 파라미터, 왜곡계수를 집어넣으면
rvec,tvec이 출력이 되는 것 같은데 solvePnP 함수 내에서 무슨 연산이 일어나는지 궁금합니다. -
안녕하세요. 카메라 기하에 대해서 공부중인 학생입니다. 질문드리고 싶은것이 있습니다.
solvepnp를 통해 얻은 R,t를 이용하면 (월드좌표계 기준 카메라의 좌표:tc) = -R.inv()*t로 표현된다면
월드좌표계에서 현재 카메라의 포즈로가는 변환 관계는 [R.inv()|tc]로 표현될거라고 생각하는데 잘 이해한 것인지 궁금합니다. 즉 solvepnp로 얻은 R의 역행렬은 월드좌표 기준 카메라의 로테이션이 되는것이 맞나요?? -
안녕하세요. 글 잘보고있습니다.
혹시 solvePnP해서 rvec를 구하고, Rodrigues한 R값을 RQDecomp3x3함수적용후
world의 object 회전을 구하려고 합니다.
RQDecomp3x3에 의해 pitch, yaw, roll값을 구했는데...
pitch각의 오차가 너무 크네요. 관련해서 조언 받을수 있을까요? -
안녕하세요! 글들과 댓글을 보면서 궁금증이 생겨서 질문드립니다.
남기신 댓글중에 '그리고 월드좌표 p에서 카메라 좌표 p'로의 변환은 p' = R*p + t로 구해집니다.'
라는 댓글에서 t와 R이 solvepnp로 구한 r,t를 그대로 사용하는 것인가요??
아니면 t의 경우 글의 내용처럼 T = -R.inv()*t 와 같은 변환과정을 수행한 T를 적용해서 변환하여야 하는 것인가요? R의 경우도 마찬가지로 따로 변환과정을 수행해서 사용하는지 궁금합니다. -
안녕하세요. 비전에 입문하여 하나하나 배워가던 중 이곳을 알게 되었습니다.
고수님의 친절한 답글 보고 감동받았습니다.
질문이 있는데요,
위에 SolvePnP에서 구해진 rvec,tvec 을 가지고,
Ow = R^-1*(Oc - t) 에 rvec,tvec 및 Oc=(0,0,0)으로 놓으면,
Ow값이 픽셀단위인가요, 실제 거리(mm or ??) 인가요?
다른 글에 정규평면 관련한 내용이 있었는데,
여전히 이해가 잘 안되어서요.
말씀 부탁드리겠습니다.
-
안녕하세요 다크프로그래머님. 저는 대학교에 진학중인 학생입니다.
요즘 관심이 영상처리에 생겨서 혼자 공부를 진행하고 있습니다.
아직 대학생이다보니 배운것도 적고 혼자 공부하기엔 많이 어렵지만 항상 배우는 자세로 열심히 공부중에 있습니다. 요즘은 켈리브레이션을 직접 만들어보고 싶어서 얕은 지식으로 opencv를 사용하여 제작중인데. 몇가지 궁금증이 생겨서 ㅎㅎ..질문을 드립니다.. 사실 인터넷에서 많은 코드를 접하면서 한줄한줄 이해를 하면서 진행중에 있습니다. 대학교 수준의 질문이라 ㅠㅠ 너무 죄송합니다.
켈리브레이션중 내부 파라미터를 구하는 것은 이해가 되었으나 외부 파라미터를 구하기 위해선 월드 좌표계가 정의되어야 하잖아요? 카메라는 고정인 상태에서 월드 좌표계의 Z축은 외부 파라미터에 아무 관련이 없는건가요? 인터넷의 다양한 분들이 올린 글에 보면
for (int i = 0 ; i < image_num; i++) { //이미지수 5
for (int j = 0 ; j < patten_row ; j++) { // 행수
for (int k = 0 ; k < patten_col ; k++) { //열수
object_points[ i * patten_size + j * patten_col + k ].x = j * chess_size; //26mm
object_points[ i * patten_size + j * patten_col+ k ].y = k * chess_size;
object_points[ i * patten_size + j * patten_col + k ].z = 0.0 ; }}}
이렇게 3차원 공간 좌표를 cvInitMatHeader 통해 Mat 으로 행렬을 만들더군요. 그렇담 이게 월드 좌표계가 되는게 아닌가요? 월드 좌표계가 되는거라면 모든 z값을 0으로 두는데.. 외부파라미터와 상관이 없는건가요..? 죄송합니다. 이해가 잘안되서 이렇게 질문드립니다 ㅠㅠ.
-
다크pgmr 2016.10.20 09:15 신고
체스판을 가지고 카메라 캘리브레이션을 하는 목적은 카메라의 외부 파라미터가 아닌 내부 파라미터를 구하기 위함입니다. 체스판을 기준으로 월드좌표계를 설정하면 카메라 영상을 획득할 때마다 카메라의 자세(R, t)가 바뀌게 됩니다. 즉, 체스판 영상마다 서로 다른 외부 파라미터 값을 가집니다. 하지만 카메라의 내부 파라미터는 카메라의 자세와는 무관한 값이기 때문에 카메라 외부 파라미터가 다른 상황에서도 수학적 제약식을 이용하여 내부 파라미터를 구하게 됩니다. 자세한 수식적 내용에 대해서는 원 논문을 참조하시기 바랍니다 (Z. Zhang. “A Flexible New Technique for Camera Calibration”, TPAMI 2000)
-
질문이 있습니다.
opencv 3.0에 fisheye모델 캘을 하면, instrinsic과 distortion파라미트거 k1, k2, k3, k4가 나오는데,
p1, p2를 나오지가 않습니다.
도저히 이해가 가지가 않아 질문남깁니다. ㅠ-
다크pgmr 2017.07.17 17:10 신고
먼저 알아두셔야 할 것은 카메라 렌즈왜곡모델이 한가지가 아니라는 점입니다. 여러 모델이 존재하며 fisheye는 그 중의 한가지입니다. opencv에 새로 추가된 fisheye 모델은 저도 사용하는 모델이 아니라서 자세한 것은 모릅니다. 하지만 어쨌든 k1, k2, k3, k4의 의미를 알기 위해서는 opencv::fisheye 모델이 어떤 모델인지 공부해야 합니다. 어쨌든 기존의 opencv에 존재하던 기본 모델의 k1, k2, p1, p2와 같은 의미인지는 확인이 필요합니다. 글자가 같다고 무조건 같은 의미라고 생각하면 안됩니다 (저도 실제 같은지 다른지는 모릅니다).
그런데 문제는 solvePnP에서 파라미터로 받는 distCoeffs는 기존의 기본 카메라모델의 k1,k2,p1,p2이어야 한다는 점입니다. 해결책은 2가지입니다. 첫째는, fisheye 모델을 사용하지 말고 기존의 일반적인 카메라모델을 사용해서 k1,k2,p1,p2를 구하는 것입니다 (기본 카메라 모델로 캘리브레이션 해주는 툴은 GML Calibration toolbox 등 좋은 프로그램이 많이 있습니다). 두번째 방법은, solvePnP의 입력으로 픽셀좌표를 사용하지 않고 왜곡 보정된 정규좌표(normalized image coordinate)를 사용하는 것입니다. 그러면 사용한 렌즈왜곡모델에 영향을 받지 않고 카메라의 자세를 추정할 수 있습니다. 단, 이 경우에는 distCoeffs에 k1=k2=p1=p2=0와 같이 왜곡계수를 전부 0으로 해 주면 됩니다.
-
-
위에 답변 감사합니다 ㅎ 많은 도움이 되었습니다.
제가 알고자 하는건 내부와 여기서 구한 외부 파라미터를 가자고 0 0 0월드좌표가 영상상에서 어디인지 찾고 싶습니다.
내부파라미터와 여기서 구한 R 그리고 tvec을 이용하고 내가 알고자 하는 3d 포인트가 2d영상에서 어디인지 알고싶습니다. 그렇다면
rt메트릭스를 3 x 4행렬로 R과 tvec으로 만들고 K*rt*0 0 0 1을 했은데 픽셀좌표가 즉 결과값이 예측이 안되네요. -
좋은 글들 잘 보고 있습니다( _ _)꾸벅
댓글에서 보면 2차례 OpenCV calibrateCamera 함수 보다 GML캘리브레이션 툴을 추천하시는데
어떤 이유인가요?
-
안녕하세요.
R(Rotation Matrix) , T(translation vectors) 관련하여 모르는 부분이 있어 어느 글에 질문을
남겨야 할지 모르겠어 이글에 질문을 남기는 게 맞는 것 같아 질문 남깁니다.
https://darkpgmr.tistory.com/153 (영상의 기하학적 해석)에서
3D 변환을 이용한 방법에 대해서 보고 있는데
카메라 원점의 월드좌표 Cw와 점 Pc의 월드좌표 pw를 구하는 공식에서
pw = R^T*(pc - t)
Cw = R^T*(Cc - t)
공식에서 사용되는 R과 t를 구하려고 합니다.
다시 R과 T를 구하는 공식으로 돌아와서,
월드 좌표 점(4점이상) 과 이미지 좌표 점(4점 이상)을 넣어
solvePnP 함수와 Rodrigues 함수를 이용하여,
R과 T를 구하고 있는데
월드 좌표 점(4점이상) 과 이미지 좌표 점(4점 이상) 없이
카메라에 AHRS(roll,pitch,yaw가 출력 되는 장비)를 부착하여 사용했을 때
오일러 각을 이용해 R(Rotation Matrix)을 도출해 낼수 있고
T의 경우는 따라 구할 수 있는 방법이 없는지 알고 싶습니다.
추가적 식에서 t라는 값이 월드좌표 원점에서 카메라가 이동된 거리를
의미하는 것 같은데 이 생각이 맞는지도 궁금합니다. -
안녕하세요~ 좋은 글 잘 읽었습니다~!
apriltag 마커의 자세를 인식하려는데요~, apriltag의 특징점(코너)들의 3d 좌표를 미리 정의해놨습니다(아, 영상에서 해당 마커의 2d 좌표도 구했구요). 이 3d 좌표가 결국 월드 좌표계 상의 점일텐데, 이 3d특징점들의 원점(O)을 어디에 맞춰야 할지 궁금합니다. 특징점들의 평균 중심으로 할지, 아니면 어느 특정 꼭지점으로 할지 등등...ㅎㅎ. 구지 특정지을 필요가 없을까요? 즉, 어디를 원점으로 두든지 solvePnP 결과에 반영이 되서 나올까요? learncv.org 에 있던 얼굴 자세 추정 예제에서, 헤드 모델의 중심을 코끝에 맞췄던데, 이런것도 다 이유가 있어서 그런가 아닐까 싶어서요~. -
안녕하세요. 포스팅된 글들 전부 유익하게 읽었습니다.
다만 궁금한게 stereo type이 아닌 mono 카메라에서도 이렇게 변환 행렬을 구할 수 있는지 궁금합니다!
그리고 드론에 카메라를 연직 방향으로 달아서 좌표를 구하려고 하는데 3d는 드론의 좌표 그리고 2d로는 pixel 좌표를 입력하는게 맞을까요??
좋은 글들 너무 감사해요!!!! -
안녕하세요. 좋은 글 감사합니다. 정말 많은 도움이 되었습니다.
글을 읽다 궁금증이 생겨 질문을 남깁니다.
카메라 extrinsic matrix에 대한 궁금증인데, 모든 카메라의 extrinsic matrix는 Rodrigues값인가요?
오일러 형식도 3X3 행렬로 되어 있는데, 오일러 형식으로 된 extrinsic matrix는 없는 건가 궁금해서 질문을 남깁니다. 특히 kitti calibration에 대해 공부 중 인데 kitti의 extrinsic calibration 이 Rodrigues형식으로 되어있는지 확인하는 방법이 있는지 궁금해서 이렇게 질문을 남깁니다. 혹시 자세한 자료가 있는 곳을 아시다면 알려주세요!!-
다크pgmr 2021.12.01 15:08 신고
카메라의 자세는 3x3 rotation matrix R과 3x1 translation vector t로 표현하는 것이 일반적입니다. 합쳐서 [R|t]로 표현하구요. 이중 rotation 성분은 행렬 R 대신에 오일러 각, rodrigue, quaternion 등 여러 방식으로 표현할 수 있습니다. 그러니, rodrigue는 카메라의 방향을 표현하는 다양한 방식 중에서 하나일 뿐입니다. 3x3 rotation 행렬로 표현하는 것이 가장 일반적인 표현이구요. kitti 데이터셋에서 어떤 방식을 사용하는지는 모르겠지만, 데이터 포맷 정보 등에 보면 나와있지 않을까요?
-