3D 좌표계 변환 방법 (예: 월드좌표계 - 카메라 좌표계)

영상처리 2013. 7. 25. 14:02

3차원 공간에서 좌표축 또는 좌표계를 변환하는 방법입니다.


3D 월드 좌표계를 카메라 좌표계로 변환하는 것을 예로 들어 설명하겠습니다.


즉, 월드 좌표계(world coordinate system)에서의 점 (X, Y, Z)로부터 카메라 좌표계에서 봤을 때의 좌표 (Xc, Yc, Zc)를 구하는게 목적입니다.


<그림 1>


<그림 1>과 같이 월드좌표계와 카메라 좌표계를 정의하겠습니다.

  • 월드 좌표계: 지면이 XY 평면, 위쪽이 Z축
  • 카메라 좌표계: 카메라 광학축 방향이 Zc, 오른쪽이 Xc, 아래쪽이 Yc


또한 월드 좌표계 내에서 카메라의 위치 및 방향을 다음과 같이 정의하겠습니다.

  • 카메라의 위치: 월드 좌표계 내에서 카메라 좌표축 원점의 위치, (X1, Y1, Z1)
  • pan(팬): 카메라의 좌우 회전각. 광학축이 월드좌표계 Y축과 평행할때 0도, 왼쪽이 +, 오른쪽이 -
  • tilt(틸트): 카메라의 상하 회전각. 광학축이 월드좌표계 Y축과 평행할때 0도, 위쪽이 +, 아래쪽이 -
  • roll(롤):  카메라 광학축을 기준으로 한 회전각으로서, 카메라와 같은 방향을 바라볼 때 반시계 방향이 + 방향


즉, 카메라의 pan, tilt는 카메라 광학축(Zc)이 Y축 방향일 때 0이고 카메라를 위로 들면 tilt가 증가, 왼쪽으로 돌리면 pan이 증가합니다.


이제 풀고자 하는 문제를 정리하면 다음과 같습니다.

카메라의 위치를 (X1, Y1, Z1), 카메라의 팬(pan) 각을 p 라디안, 틸트(tilt)를 t 라디안이라 할 때, 월드좌표계 상의 임의의 점 (X, Y, Z)를 카메라 좌표계 상의 좌표 (Xc, Yc, Zc)로 변환시키는 관계식을 구하라.


좌표계 변환관계는 2가지 방법으로 구할 수 있습니다. 하나는 일련의 회전변환 행렬을 조합하는 것이고, 다른 한 방법은 단위벡터를 이용해 직접 변환행렬을 구하는 방법입니다.



방법 1: 회전변환을 조합하는 방법


월드 좌표축을 카메라 좌표축 방향과 일치되도록 하는 회전변환 행렬을 R이라 하면, R은


 --- (1)


과 같이 구해집니다 (3D 회전변환 행렬에 대해서는 [컴퓨터 비전에서의 Geometry #5] 3D 변환 참조)


☞ Roll까지 고려한 경우, R = Rz(p)Rx(t)Ry(-roll)Rx(-π/2)로 구해진다.


따라서, 월드좌표를 카메라 좌표로 변환시키는 변환식은 다음과 같이 구해집니다.


 --- (2)


좌표축 변환은 일반적인 변환과정을 역으로 적용함에 주의해야 합니다.


식 (2)에서 회전변환은 RRT = I를 만족하기 때문에 R-1 = RT로 구할 수 있습니다. 즉, 식 (2)는 다음과 같이 됩니다.


 --- (3)


☞ 여기서 R은 월드좌표를 카메라좌표로 변환시키는 행렬이 아니라 좌표축을 변환시키는 행렬임에 주의해야 합니다. 즉, R은 월드좌표축->카메라좌표축 변환 행렬입니다. 즉, 좌표로 보면 R은 카메라좌표->월드좌표로 변환시키는 행렬입니다 (좌표축 변환과 좌표변환은 서로 역변환 관계). 이 글에서 정의한 R과 opencv의 solvePnP에서 반환되는 R이 표기가 같아서 서로 혼동스러울 수 있겠지만 solvePnP에서 반환되는 R은 월드좌표->카메라좌표 변환행렬이고, 여기서 정의한 R은 카메라좌표->월드좌표 변환행렬입니다. 즉, 서로 반대입니다. 표기를 통일하는게 좋았겠지만 이 글에서는 설명의 흐름상 어쩔 수 없이 R을 다른 글들과는 다르게(반대로) 정의했습니다..


방법 2: 변환행렬을 직접 구하는 방법


어떤 선형변환 행렬 T가 있을 때, 각각의 좌표축 단위벡터들이 변환 T에 의해서 어디로 가는지만 알면 T를 손쉽게 구할 수 있습니다.


만일, T에 의해 X축 단위벡터 (1, 0, 0)이 (a1,a2,a3)로 가고, Y축 단위벡터 (0, 1, 0)이 (b1, b2, b3), Z축 단위벡터 (0, 0, 1)이 (c1, c2, c3)가 된다면, 변환행렬 T는 다음과 같습니다.


 --- (4)


이제, 이 방법를 이용하여 X축을 Xc, Y축을 Yc, Z축을 Zc로 보내는 변환행렬 R을 구해보겠습니다.


<그림 2>


<그림 2>를 참조하여 각각의 단위벡터가 어디로 이동해야 하는지를 구해보면 다음과 같습니다.


 --- (5)


따라서, 변환행렬 R은 다음과 같이 구해집니다.


 --- (6)


식 (1)과 동일한 결과가 나옴을 확인할 수 있습니다.


나머지 과정은 방법 1과 마찬가지이기에 생략합니다 (최종적으로는 식 (3)과 동일한 변환식이 나옵니다).


☞ 식 (3)은 벽에 고정된 CCTV, 자동차에 고정된 카메라 등에서 좌표계 변환을 할 때 유용하게 활용될 수 있으리라 생각합니다.


by 다크 프로그래머


  • 이전 댓글 더보기
  • BlogIcon 로봇 2016.04.26 20:04 ADDR 수정/삭제 답글

    안녕하세요 블로그를 통해 얻고있는 정보가 많습니다. 글을 읽고 코딩하는 중 pan과 tilt가 모두 0일때는 항상 변환후 Zc의 값이 0인데 원래라면 기준점과 카메라 사이의 거리값이 나와야되지않나요. 이해가 쉽지 않습니다. 도와주세요...

    • BlogIcon 다크pgmr 2016.04.26 20:18 신고 수정/삭제

      안녕하세요. 무언가 좀 이해를 잘못 하고 계신것 같은데요, 일단 카메라좌표계, 월드좌표계의 의미에 대해 http://darkpgmr.tistory.com/77 글을 참조하시면 좋을듯 싶습니다. 그리고 pan = tilt = 0일 때, R^-1 = [1 0 0; 0 0 -1; 0 1 0]이기 때문에 (Xc, Yc, Zc) = (X - X1, -Z + Z1, Y - Y1)이 됩니다. 즉, Zc = Y - Y1이 됩니다. 따라서 Y = Y1일 때만 0이고, 그 외에는 0이 아닌 값이 나옵니다. 어떻게 해서 항상 0의 값이 나오게 됬는지 모르겠네요..

    • BlogIcon 로봇 2016.04.26 20:23 수정/삭제

      제가 실수했습니다. 감사합니다^^

  • 초보자 2016.08.11 18:06 ADDR 수정/삭제 답글

    글을 보다 계속 머리속에 헷깔리는 것이
    카메라 회전행렬 R과 R_inv (R의 역행렬 표기)의 표현에 관한 것입니다.
    보통 월드좌표계에서 카메라좌표계로 변환시 적용되는 회전 행렬을 R로 표현하는지.. 아니면 R_inv로 표현하는건지요?
    여기 식(2)에서는 R_inv로 표현되어 있지만, 다른 게시글에서 solvePnP와 Rodriques로 산출된 변환 행렬을 R로 표현하고 있는데요.
    실제 적용해보니 여기 식(2)의 R_inv와 solvePnP에서 산출된 R이 같은 값을 가지는 것으로 확인되었습니다...그러면 solvePnP의 산출된 R을 R_inv로 봐야 할지....아니면 기준에 따라 달리 해석해야 할 지... 정리가 덜되어서 헷깔립니다.ㅠㅠ.


    • BlogIcon 다크pgmr 2016.08.11 22:22 신고 수정/삭제

      네.. 제가 표기를 혼용하다 보니 혼동을 드린 것 같습니다. 본문의 식 (3) 밑에 해당 설명을 추가하였습니다. 일반적으로 R은 항상 월드좌표->카메라좌표 변환행렬입니다. 즉, 카메라좌표 = R*월드좌표 + t입니다(단, 이 글에서는 R이 반대의 의미로 사용되었습니다). solvePnP에서 반환하는 R도 월드좌표->카메라좌표 변환행렬입니다.

    • 초보자 2016.08.12 09:16 수정/삭제

      시원한 답변 감사합니다.^^;
      잘 정리가 될 것 같습니다.

  • 초보자 2016.08.12 12:05 ADDR 수정/삭제 답글

    다시 궁금한 사항이 있어 문의드려봅니다.
    식(1)에서 X축 회전에 대해서는 그냥 tilt값을 적용하지 않고 (-pi/2 + tilt)를 추가된 의미가 무엇인지 궁금합니다.
    "[영상 Geometry #5] 3D 변환"쪽 게시글의 X축 회전에 대한 행렬식과 다르게 표현되어 있어서...제가 뭔가 이해하지 못한 부분이 있는 것 같은데....설명이 가능하시면 좀 알려주세요.^^

    • BlogIcon 다크pgmr 2016.08.12 14:53 신고 수정/삭제

      그건 tilt의 정의를 확인하시면 됩니다.

    • 초보자 2016.08.12 15:32 수정/삭제

      <그림1>에서 카메라 좌표계와 월드 좌표계의 각 축의 기준이 다르기 때문에 그런건가요?
      월드 좌표계 기준으로 봤을때 카메라 좌표계가 X축에 대해 -90도 회전되어 있는데 이것 때문에 tilt에 대해서만 -pi/2가 적용된 것인지요?

  • CG메인으로CV도하는사람 2018.06.06 11:46 ADDR 수정/삭제 답글

    어쩌다보니 이쪽 계통 기술을 오래 잡고 있게 되어버린 사람입니다만, 이 내용은 연구하는 사람들과 한분야만 파고드는 사람들이이 흔히 범하는 "it's just an implementation issue"라고 줄여버리기에는 너무 복잡하고 심각한 문제가 얽혀있는데다, 쓸데없는 기술장벽조차 만들어 내고 있는 심각한 문제입니다. 따지고 들어가다 보면 결국 구현문제로 귀결될지 몰라도 (소프트웨어 분야에 안 그런 문제가 어딨는가? 싶긴 합니다만), 적어도 이 포스팅에서 설명하는 정도로 간략하게 요약될 성질의 것은 아니라 생각하는데, 어디에서도 이 문제의 심각성을 지적하는 분들은 잘 없더군요.

    경험상, 이러한 혼란의 원인은 크게 3가지정도 있는 듯 합니다.
    1. 3차원 그 자체의 복잡성,
    2. '그래픽스' 와 '비전' 이라는 분야가 독립적으로 발달되어 왔지만 용어가 비슷해서 서로 오해를 부르는 문제,
    3. 다양한 라이브러리와 통일되지 않은 좌표계 설정,

    흔히 1의 내용만 그 문제의 원인으로 생각들 하는 경우가 많은데, 저는 2와 3의 문제가 더 크다고 봅니다. 2의 문제에 대해, 당장 이 포스팅 질문글에도 CG 쪽을 메인으로 하시는 분들의 질문이 자주 보이는데요, 답변 하시는 분도 자신의 분야에서는 맞는 이야기지만 저쪽에서는 의미가 없거나 논점에 어긋난... 이렇듯 비슷한 듯 하면서도 질문과 대답방향이 완전히 어긋나있는 것이 당장 눈에 띄네요.

    분야가 다르다는 것에서 당장 크게 떠오르는게 "프로젝션 행렬"이라는 용어가 있네요, 이게 여러모로 오해를 부르기 딱 좋은게, 이름도 동일하고, 역할도 비슷한데 CG와 CV에서의 정의가 아예 다른 물건이 있습니다. 단적으로 일단 CV의 프로젝션 행렬은 3x4인데, CG는 4x4죠... 설명하자면 길어지므로 생략합니다만, 단순히 행 하나가 준 것이 아니라, 함의가 아예 다릅니다. 생각방식의 차이(CG: 2차원 이미지는 3차원 데이터를 렌더링 한 결과 / CV: 2차원 이미지로부터 3차원 데이터를 재구성)에 기인하는 문제인데. 부르는 이름이 같으니 여러모로 오해를 부르지요.

    3 또한 심각한 문제인데요, 마치 언어와 사고에 대한 사피어-워프 가설처럼 흔히 사용하는 라이브러리가 그 사람의 사고방식(좌표계설정)에도 영향을 미치기 때문입니다. 단적으로, classic 한 컴퓨터 비전하는 분들이 그리도 신성시 하는 Hartley & Zisserman 의 MVG 의 핀홀카메라 부분 확인해 보시면 카메라 좌표계가 Y가 up 으로 설정되어 있는데 반해, 이 포스팅에서는 아무렇지도 않게 카메라 좌표계는 Y를 down 으로 잡고 있지요. 아마 OpenCV 를 늘상 사용하셔서 그것이 포스팅 하신 분 사고에도 영향을 끼쳤다 보입니다.

    그게 뭐가 심각한 문제냐? AR, CG 분야 같이 단순히 비전계통 알고리즘만으로 끝나는 문제가 아닌 것을 하시다 보면 조금 더 와닿을 수 있겠습니다만. CV 주로 하시는 분들은 본인들 역할은 카메라 자세만 잘 뽑으면 된다 생각하시는 분들이 많고, 심하게 말하자면 3축 OpenCV 같은데서 제공하는 라인 드로잉으로 띡 그려놓고 "되지? 그러니까 너네가 잘 갖다 써." 로 끝인 경우를 보게 됩니다. 그런데, 이정도 수준의 모듈은 toy example 에나 통용되지, 제대로 된 물건을 만들기에는 여기저기 어려운 문제가 닥칩니다.

    일단 CG쪽에서 사용하는 라이브러리 보시면 좌표계 설정이 완전히 다른데요, 같은 우수계인 GL 좌표계조차도 기본 up 의 방향이 다르고 따라서 Z 축도 반대방향이 되지요. (CG에서 말하는) 프로젝션 행렬도 이 좌표계 설정에 따르므로, 카메라 행렬 혹은 (CV에서 말하는) 프로젝션 행렬도 여기에 맞춰야 합니다. DX 같은 좌수계로 가면 문제가 더욱 심각해 지지요.

    가끔 해결이랍시고 프로젝션 행렬을 아예 CV 식으로 고쳐버리는 경우가 왕왕 있습니다만, 단순 drawing 명령에는 그것으로 충분할 경우가 많지만, 셰이더나 기타 복잡한 기능을 사용할 때 문제를 안 일으켰던 경우가 별로 기억에 없네요. 특히 물리엔진 같이 설정 조금만 건드렸다가 다 개판되는 경우, 카메라 및 월드 좌표계는 함부로 고치기도 문제가 있기에, up 과 카메라는 라이브러리 설정에서 벗어나지 않도록 해야 하는데, 비전'만' 하는 분들은 이런 부분을 과소평가 하더라고요. 애초에 본인들 좌표설정만 고치면 되는 문제인데 말이지요.

    • BlogIcon 다크pgmr 2018.06.07 13:27 신고 수정/삭제

      이런 댓글을 받다니 한편으로 생소하고 또 재미가 느껴집니다. 사람은 아는 만큼만 보고 이해할 수 있다 보니 저로서는 머리만 긁적이고 있네요.
      그런데, 카메라 Y축을 down으로 잡은 것은 어디서 보고 한 것은 아닙니다. 사실 처음에는 up 방향으로 Y축을 잡고 나름 식들을 세웠었는데요, 이게 이렇게 해서 만든 식들이 뭔가 자연스럽지 않고 자꾸 꼬이는 겁니다. 그러다 나중에 Y축을 down 방향으로 바꾸게 되었는데 모든 식들이 정말 딱딱 맞아 떨어지고 만족스러웠습니다. 그런데, 이게 이미지 좌표 방향과 밀접한 관련이 있는 문제였네요..
      저도 일전에 ar 때문에 그래픽스 함수를 몇번 사용해 본 적이 있는데요, 카메라 자세를 그래픽스 모델에 맞게 변환하는 것이 보통 어려운 일이 아니었습니다. 결국은 카메라의 회전각 성분(오일러 앵글)들을 추출한 후 다시 프로젝션 행렬을 구성하는 방법으로 어찌 어찌 해결은 했습니다만.. 그 좌표축의 차이로 cv와 그래픽스의 접점에서 얼마나 많은 문제가 발생할지 미루어 짐작이 갑니다. 어쨌든 분야마다 나름 체계와 이유가 있다 보니 일정 부분은 이해해야 하지 않나 싶습니다.

    • CG메인으로CV도하는사람 2018.06.07 23:13 수정/삭제

      네, 이미지'만' 생각하면 Y-down 이 참 자연스러운데 말이지요. 하다못해 윈도우 좌표계도 Y-down 이니까요.
      사실 그래픽스 라이브러리를 처음 만질 때도 위-아래 문제는 당혹스럽습니다. 그래픽스 라이브러리는 Y-up이 기본이라 카메라 좌표를 Y-up 에 맞추다 보니 캡처나 인터랙션 프로그램 등에서 생각없이 하다가는 위아래 뒤집히는 문제가 왕왕 나옵니다.

      그런데, 참 모순적인데요, 이미지는 그냥 내가 관찰하기 위한 수단일 뿐이고 그 내부(?)의 3차원 물체를 메인으로 생각하기 시작하면, 그건 또 Y-up 이 굉장히 자연스럽다 느껴집니다. 핀홀카메라가 원리상으로는 상이 뒤집어지지만 아무도 그런것을 고려하지 않듯, 중간의 디테일은 쓸데없고 결과만 보고 싶어하는게 인간이라는 생물의 본성인가 봅니다.

      여튼, 이 두가지의 중간 절충지점과 좌-우수계 변환의 수단으로 world를 Z-up으로 두는 경우가 있긴 한데, 이게 또 모든 라이브러리가 그렇게 짜여진 것은 아니라서, 결국 어딘가에서는 누군가가 삽질을 하지 않을 수 없는 구조가 만들어집니다 (적어도 제가 경험한 한에서는 모두 그랬던 듯). 그냥 대~충 돌아가게 보이는 수준이라면 문제 없게 속이고 넘어갈 수도 있는데, pixel-by-pixel 로 따질 필요가 있는 성질의 일을 하면 이렇게는 못 넘어가지요.

      저도 이런저런 관계로 CG-CV 라이브러리 간의 변환을 많이 경험해 봤지만 할 때마다 새롭고, 결국 삽질은 필요불가결하게 반복하게 되는 것은 정말 어쩔수 없는 문제인가 봅니다...

  • BlogIcon OKOK 2018.06.10 17:06 신고 ADDR 수정/삭제 답글

    안녕하세요. ^^ 좋은 글 감사합니다.!!
    제가 다크님 정보를 통해서 3D to 2D를 해본 경험이 있는데요.
    최근 관련 연구(Slam)에서 2D를 3D로 변환해야하는 과정이 필요합니다....
    모노카메라를 사용해서 2D를 3D로 변환할 수 있나요...?

    • BlogIcon 다크pgmr 2018.06.10 19:46 신고 수정/삭제

      이미지 한장으로는 안되고요, 이미지 여러 장이 있으면 가능합니다.

  • 안녕하세요! 2018.09.11 00:56 ADDR 수정/삭제 답글

    안녕하세요. 다크프로그래머님. 항상 잘 보고 있습니다.

    다름이 아니라 두개의 카메라 간의 R / T 를 구하고 싶은데 머리가 너무 복잡하네요 ㅠㅠ
    하루종일 혼자 생각해봤는데 방도가 잘 떠오르지 않아 댓글 남깁니다.

    두개의 카메라를 한개의 월드좌표계에 대하여 보정을 완료하였고요.

    Camera1 : RC1, TC1
    Camera2 : RC2, TC2

    그렇다면 Camera1, Camera2 간의 R, T 는 어떻게 표현될까요?

    Camera1 좌표계 상의 좌표를 Camera2로 옮기는 것 까진 가능한데
    이 두개의 좌표계 간의 R / T 를 표현하는 방법을 모르겠네요.

    Camera1 좌표계상의 좌표 > World 좌표계
    inv(RC1)*(Camera1 Point - TC1).

    이렇게 나온 월드 좌표계 기준 좌표를 다시

    RC2 * (World Point) + TC2

    이렇게 계산하면, 카메라1 좌표계 상의 좌표를 카메라2 좌표계 상의 좌표로 옮기는것 까지는 이해가 가는데 ㅠㅠ

    Camera1 - Camera2 간의 R / T 를 RC1, TC1, RC2, TC2를 이용해서 나타낼 수 있을까요?

    • BlogIcon 다크pgmr 2018.09.11 09:25 신고 수정/삭제

      문제를 직접 풀으시려는 것이 보기 좋습니다. 제가 보기에는 이미 문제를 다 풀으셨는데요, w = inv(R1)(c1-t1), c2 = R2w+t2 를 연립하면 c2 = R2(inv(R1)(c1-t1))+t2 = R2inv(R1)c1 - R2inv(R1)t1 + t2 이네요. 그러니, c1->c2의 R = R2inv(R1), t = - R2inv(R1)t1 + t2 입니다.

  • 캘린이 2018.10.22 11:34 ADDR 수정/삭제 답글

    안녕하세요 다크프로그래머님 좋은 글 감사합니다.

    좌표계 변환에서 질문이 있습니다. 위에 올려주신 내용은 월드 좌표계를 R 행렬을 구해서 카메라 좌표계로 변환하는 방법을 작성해주셨는데,

    그러면 반대로 카메라 좌표계를 월드 좌표계로 변환하는 과정은 저 (3)번 식에서 [Xc, Yc, Zc] 를 [X, Y, Z] 로 서로 바꾸는 즉, 서로 위치만 바꾸고 R행렬도 역행렬이 아닌 (1)의 R식을 사용하여 구하면 되는것일까요?

    그리고 혹시 그 식에서 X1,Y1,Z1 이 카메라 원점이라고 하셨는데 그게 월드기준에서의 카메라의 실제 X,Y,Z를 뜻하는것인가요??

    • BlogIcon 다크pgmr 2018.10.22 20:52 신고 수정/삭제

      질문1) 식을 다시 정리하면 됩니다. Xc = R^-1(Xw - X1)을 다시 정리하면, Xw - X1 = RXc 에서 Xw = RXc + X1와 같이 변환됩니다.
      질문2) 네 그렇습니다.

  • miso77 2018.11.28 15:39 ADDR 수정/삭제 답글

    안녕하세요. 관련 작업을 하면서 다크프로그래머님 블로그 도움을 너무나 많이 받고 있어 늦었지만 감사 드립니다. 그 동안은 블로그 참조하여 구현을 하는쪽에 초첨을 맞춰다면 이해를 하고 싶어 다시금 보고 있는데요. 궁금한 부분이 있어 문의를 드립니다.

    http://darkpgmr.tistory.com/122 이 글을 보면(카메라의 위치 및 자세 파악)
    solvePnP로 구한 R, T를 이용하여 월드좌표에서 카메라좌표 또는 그 반대 변환을 할 수 있습니다.
    실제로 solvePnP로 구한 R의 성분을 보면 모든 성분이 0이 아닌 값을 가집니다.
    (R, T를 갖고 카메라 위치를 구하거나, triangulation등을 수행하면 맞게 나오는 걸로 봐서는 잘 구한 것 같습니다.)

    그런데, 여기 글을 보면 R 성분 중 하나가 0([2][0])이 됩니다. (Rinv도 마찬가지)
    solvePnP로 구한 R과 위에서 언급하신 pan, tilt로 얻은 R이 동일한 회전행렬을 의미하는거 같은데요.

    회전행렬이 다를 수가 있는 것인지 아니면 제가 착각을 하고 있는 것인지 궁금합니다.


    • BlogIcon 다크pgmr 2018.11.28 18:54 신고 수정/삭제

      그건 제가 카메라의 roll을 0으로 놓고 식을 세웠기 때문입니다. roll이 0이 아니라면 임의의 행렬이 가능합니다.

  • 휴... 어렵다 2018.11.30 14:44 ADDR 수정/삭제 답글

    안녕하세요 블로그 글 많이 참고하여 도움이 됐습니다. 여쭤보고싶은게 있는데요
    일단 제가 하는 작업은 카메라에서 보이는 물체에 달려있는 가속도센서 값을 추정하는 작업입니다.
    여기서 제가 어려워하는 포인트는 가속도센서는 자기의 센서 축을 가지고 가속도값을 산출할텐데( 제생각에는 이부분이 월드 좌표계라고 생각합니다) 그거를 카메라가 보는시점은 카메라 좌표계이기때문에 카메라좌표계를 월드 좌표계로 바꿔야 한다고 생각하는데요 이 포스팅 내용과 연관시키면 쉬울거같은데 관련지식이 부족해서 잘 연관이안되네요 ㅜㅜ 혹시 도움받을수잇을까요

    • BlogIcon 다크pgmr 2018.11.30 18:09 신고 수정/삭제

      카메라가 움직인다면 거의 불가능할 것 같구요, 카메라 위치가 고정인 경우라면 카메라좌표계를 월드좌표계로 설정하면 될 것 같습니다.
      그런데, 카메라로 가속도를 측정하는 것보다는 가속도 센서에서 나오는 값을 사용하는 것이 좀더 간단하고 정확할 것 같은데요, 어떤 이유에서 카메라가 필요한지 궁금하네요.

  • miniont 2018.11.30 16:30 ADDR 수정/삭제 답글

    비젼만 15년 넘게 했는데, 항상 수식 계산에서 막힐 때 해결책을 주는게 다크님 페이지입니다. 늘 고맙게 생각됩니다. 공부를 제대로 안하고 먹고사는게 창피하네요.

    • 곰돌이만세 2018.11.30 17:49 수정/삭제

      저도 그렇습니다. 막히면 다크님에게로...
      부끄럽지만 또 노력계속하면 좋은 결과가 올겁니다.

    • BlogIcon 다크pgmr 2018.11.30 18:12 신고 수정/삭제

      저도 수식만 나오면 머리가 멍해지고, 이건가 저건가 따지다 보면 몇 시간이 훌쩍 지나가곤 합니다. ^^

  • BlogIcon sevity 2019.01.10 12:44 신고 ADDR 수정/삭제 답글

    혹시 오일러 rotation 사용시 발생하는 gymbal lock에 대해서 아시나요?
    사용하신 변환도 오일러 rotation으로 보이는데 gymbal lock문제는 없는지 궁금합니다.

    • BlogIcon 다크pgmr 2019.01.16 11:40 신고 수정/삭제

      네, 동일하게 발생합니다. tilt가 +- 90이 되면 pan과 roll이 구분되지 않는 문제가 있습니다.

  • 부산촌님 2019.11.07 13:31 ADDR 수정/삭제 답글

    안녕하세요?
    다크프로그래머 님.
    참으로 좋은자료 감사하고 있습니다.
    외람되게 질문 드립니다.
    -------------------------------------------------------------
    --------------------------+-----------------------------------
    --------------------------|-----------------------------------
    |
    |
    카메라

    카메라 높이 : 6.85m
    도로 중앙과 카메라 까지의 거리 : 149m

    위 그림과 같이 고정형 카메라에서 정면과 좌우 도로를 보고 있습니다.
    삼각함수를 사용 해서 정면과 좌우 특정거리를 이동하면 중앙선에 화면이 벗어나고 있습니다.

    계산 방법이 있나요?






    • BlogIcon 다크pgmr 2019.11.12 22:54 신고 수정/삭제

      제가 이해력이 딸려서인지 질문이 무엇인지 잘 모르겠네요. 계산 방법을 물으셨는데, 무엇을 계산하고자 하는지 내용이 없습니다. 글을 읽는 사람이 초등학생이라고 생각하고 차분하게 설명해 보시기 바랍니다.

    • 부산촌님 2019.11.16 13:10 수정/삭제

      죄송합니다.
      제가 표현력이 부족해서 말도 되지 않는 질문을 한거 같습다.

      좌표 변환을 찾다보니 이 글을 보게 되었고 제가 하고 있는 개념이랑 맞는것 같은데 뭐라고 질문 할수 없어 이렇게 표현했나 봅니다.
      다시정리해서 질문 드리도록 하겠습니다.
      수고하세요...

  • shinywings 2021.01.18 18:26 ADDR 수정/삭제 답글

    안녕하세요 다크프로그래머님.

    현재 다크프로그래머님 블로그를 보며 "고정된 카메라에서 [R t] 함수를 구하는 방법"을 공부하고 있습니다.
    올려주신 관련 내용들과 댓글들을 참조해서 공부하는데 이 내용에서 식(1) ~ 식(3)까지 제가 이해가 잘 안가는 부분이 있어 질문드립니다.

    원래 처음에 제가 이해한 것은
    1. solvePnP로 구한 로드리게즈 회전 변환 벡터로 구한 회전 행렬 R은 카메라를 이동시킬때 "월드 좌표 -> 카메라 좌표"로 변환하는 행렬이고
    2. tilt, pan 을 통해 얻은 회전 행렬 R은 "카메라가 고정 되어 있을 때" "월드 좌표계 -> 카메라 좌표계"로 회전하는 R이다. "월드 좌표-> 카메라 좌표" 회전 행렬 R을 안쓰는 이유는 카메라가 고정 되어 있기 때문에 (pitch, roll, yaw)가 필요한 회전 행렬을 (tilt, pan) 두개만 가지고 "월드 좌표축 -> 카메라 좌표축"을 회전하는 R을 표현할 수 있기 때문에 이것을 사용한다. 왜냐하면 좌표축 회전하는 R t를 가지고 모든 "월드 좌표 -> 카메라 좌표"를 구할 수 있기 때문이다.
    따라서, 둘다 "월드 좌표 -> 카메라 좌표"로 변환하는 회전 행렬이지만 고정되어 있는 것이냐 아니냐에 따라 회전 행렬이 달라진다. 라고 이해 했었습니다.

    하지만 댓글 답변 달아주신 것들과 https://darkpgmr.tistory.com/122를 보면 R에 대해 정의을 내려주신 것을 보고나서
    식(1) P_c = RP_w+T, P_w=R^(-1)(P_c-T)에서
    "월드 좌표 -> 카메라 좌표" 에 맞게 회전하는 것을 보통 R이라 하고
    "카메라 좌표축 -> 월드 좌표축" 에 맞게 회전하는 것이 R^(-1) 라고 이해했습니다.

    이 것을 기준으로 삼아

    이 글의 식(1)의 R은 "월드 좌표축을 카메라 좌표축 방향과 일치되도록 하는 회전변환 행렬을 R이라 하면,..."에서 나온 R을 기준대로 보면 R^(-1) 이라고 이해했습니다.

    근데 P_c = {X_c, Y_c, Z_c} 라고 봤을 때, 식(2) P_c = R^(-1)(P_w-P_1)을 기준대로 다시 고쳐쓰면 P_c = R(P_w-P_1) 가 되기때문에 기준으로 잡아주신 P_c = RP_w+T 이랑 다릅니다.
    제가 어디서 뭘 놓친걸까요? ㅠㅠ

    ========================
    추가로 식(3)에 보면 회전 행렬이 roll == 0 으로 두고 계산하셔서 roll이 0이 아닌 경우(로드리게즈 공식을 통해 얻은 회전 행렬)에는 임의의 행렬이 될 수 있다고 하셨는데 (miso77님 댓글 참조했습니다.)

    식(1)에서 회전행렬에 roll 요소를 고려해주는 경우에도 저 식을 똑같이 써도 괜찮을까요??
    제가 구한 회전행렬이 각 원소가 0이 아닌 어떤 임의의 행렬이 나온 경우에는 저 식처럼 R[2][0] 부분을 0으로 만들어준 다음 tilt, pan을 구해도 괜찮을까요??

    • BlogIcon 다크pgmr 2021.01.19 16:03 신고 수정/삭제

      안녕하세요. 먼저 R의 표기로 혼동을 드려서 미안합니다. 처음 공부할 때 스스로 기호를 정하고 식을 도출하다보니 그렇게 되었는데, 비전 분야에서 사용하는 기호체계와 다른 것을 나중에 알게 되었습니다. 질문에 답변을 드리면,
      1. P_c = RP_w + t에서 t를 카메라의 위치(월드좌표)라고 생각하신 것 같습니다. t는 카메라의 월드좌표가 아니며, -R^(-1)t가 카메라의 월드좌표입니다. P_c = 0을 대입해보면 카메라 원점의 월드좌표가 -R^(-1)t 임을 확인할 수 있습니다.
      2. R[2][0]을 0으로 만든다고 해서 Roll이 반영된 행렬이 나오지는 않습니다. Roll까지 고려한 full 회전변환 행렬은 아래와 같습니다.
      R(0,0) = cos(pan)*cos(roll)+sin(pan)*sin(tilt)*sin(roll);
      R(0,1) = sin(pan)*cos(roll)-cos(pan)*sin(tilt)*sin(roll);
      R(0,2) = cos(tilt)*sin(roll);
      R(1,0) = cos(pan)*sin(roll)-sin(pan)*sin(tilt)*cos(roll);
      R(1,1) = sin(pan)*sin(roll)+cos(pan)*sin(tilt)*cos(roll);
      R(1,2) = -cos(tilt)*cos(roll);
      R(2,0) = -sin(pan)*cos(tilt);
      R(2,1) = cos(pan)*cos(tilt);
      R(2,2) = sin(tilt);
      단, 여기서 R은 전통적인 컴퓨터비전에서 사용하는 표기에 따른 P_c = RP_w + t에서의 R입니다.

    • BlogIcon shinywings 2021.01.27 08:18 수정/삭제

      답변 감사드립니다.

      1번은 말씀해주신대로 제가 평행이동 t와 카메라좌표 T=-R^-1t를 같다고 생각해서 계속 헤맸었습니다... ㅠㅠ
      그래서 원래 월드좌표 -> 카메라 좌표로 가는 변환은 P_c = R(P_w+T) 로 정의된다는걸 깨달앗씁니다. 그래서 1번 문제는 해결되었는데

      2번에서 말씀해주신 행렬을 제 나름대로 어떻게 회전이 되는건지 이해해보려고 했는데 조금 어려움이 있습니다. R(0,0)에서 sin(pan) 이 되려면 -90도 회전이 되어야 하는데 이 가정으로 회전을 만들어보려니까 말씀하신 것처럼 행렬 원소들이 안나옵니다.
      혹시 어떻게 유도 하셨는지 여쭤봐도 될까요??

    • BlogIcon 다크pgmr 2021.01.28 15:37 신고 수정/삭제

      네, 위 답글의 수식에 오류가 있었습니다. 위 답글에 정정된 식을 적었으니 다시 확인해 주시기 바랍니다. 유도과정은 본문 내용에 추가했습니다 (식(1) 밑의 손가락 기호).

  • masici12 2021.03.22 21:45 ADDR 수정/삭제 답글

    안녕하세요, 다크프로그래머님.
    좋은 자료를 쉽게 알려주셔서 공부를 진행하는데 큰 도움을 받아 감사합니다.
    한 가지 궁금한 점이 있는데,
    여기서는 월드좌표계를 기준으로 카메라 좌표로 변환하는 것으로 이해했는데 그렇다면 반대로
    카메라 좌표계를 기준으로하여 z축으로 수직으로 내려온 월드좌표계를 설정할 때.(이때 카메라 자세정보를 알고 있어 회전변환 R을 직접구하고 카메라의 높이를 월드좌표계 1로 지정 ex> 1.7m = (0,0,1) = T 로 하려고 함) "Pw = R*Pc + T"(Cw = R*Cc + T) 이런 식으로 놓고 설정해도 문제가 되지 않을까요??
    (최종으로 하고자 하는 것 : SolvePnP를 사용하지 않고 직접 R과 t를 구하여(여기서 R과 t는 카메라 좌표계 => 월드 좌표계) 사진에 매번 4개의 점을 찍지 않아도 t가 카메라의 높이 값이 되는 월드좌표계를 설정하여 영상의 물체와의 거리를 알려고 합니다.)

    • BlogIcon 다크pgmr 2021.03.23 10:13 신고 수정/삭제

      말씀하신 방향이 일반적이지는 않지만 충분히 가능하다고 생각됩니다. 하지만, 굳이 카메라 높이를 1로 정규화할 필요는 없을 것 같습니다. t = 1이 되도록 정규화를 해서 사용한다면 나중에 구한 값에도 모두 1.7을 곱해서 사용해야 할 것입니다.. 그리고, 일반적인 방식을 따르는 것이 확장성이나 호환성 측면에서 더 좋지 않나 생각됩니다.

    • BlogIcon masici12 2021.03.23 10:43 수정/삭제

      답변감사드립니다.
      가능성있다면 R을 만들때, 카메라 좌표계를 월드 좌표계로 바꾸는 측면이니까 기존 R = Rz(p)Rx(t)Ry(-roll)Rx(-π/2) 을 "R = Rz(p)Rx(t)Ry(-roll)Rx(π/2)"로 바꿔서 사용하는게 맞는걸까요?

    • BlogIcon 다크pgmr 2021.03.23 11:44 신고 수정/삭제

      본문의 R이 카메라좌표계를 월드좌표계로 바꾸는 R입니다. 변형할 필요없이 그대로 사용하면 됩니다. 그리고 변형이 필요한 경우에는 R의 역행렬을 구해서 사용해야 합니다 (적으신 것처럼 행렬의 일부만 변형해서는 안됩니다)

  • BlogIcon Maru Jang 2021.04.29 21:47 신고 ADDR 수정/삭제 답글

    안녕하세요 2d 라이다에 인식되는 점들을 카메라 이미지 평면에 동기화시키려고 공부하다가 여기서 글들을 타고타고 공부하고 있고 아주 큰 도움이 되고 있습니다.
    질문이 하나 있어서 이렇게 답글을 남기게 되었습니다.
    제 환경이 월드 좌표계의 원점이 라이다라고 하고 카메라 좌표계로 변환을 할때 (2) 식에서 회전변환 외에 평행이동변환 때문에 x1 y1 z1 좌표를 빼주잖아요? 그 x1, y1, z1 좌표를 현실에서는 라이다 설치 위치와 카메라 설치 위치의 좌표 차이를 실측해야하는 게 맞는건지 확인 차 질문드립니다.

    • BlogIcon 다크pgmr 2021.05.07 14:23 신고 수정/삭제

      해당 분야에 대해 잘은 모르지만 굳이 실측까지 하지 않더라도 방법들은 있을 것으로 생각됩니다. 2d lidar camera calibration으로 검색해 보면 방법들이 나오지 않을까 싶습니다.

  • 김은우 2021.05.10 09:19 ADDR 수정/삭제 답글

    안녕하세요 항상 감사히 잘 보며 공부하고 있습니다.
    궁금한게 있어 질문 드리려 하는데

    서로다른 좌표계를 연동하여 하나의 좌표점을 찾는것은 이해가 되었는데
    혹시 그 좌표점에서의 벡터값(기울어짐 정도) 도 구하는 방법이 따로 있을까요?

    3D 카메라에서 인식했을때의 틀어짐 정도를 월드좌표계에서는 어떠한 형식으로 받아오는지 궁금합니다.

  • 가나다 2021.05.18 09:03 ADDR 수정/삭제 답글

    안녕하세요~ 다크프로그래머님 포스팅을 보며 많은 도움을 받고 있는 사람입니다.

    다름이 아니라 궁금한 것이 있는데 카메라의 회전 행렬을 구하기 위해서는 카메라의 좌표축을 알아야 하는데 그 방법은 무엇인가요?

    그리고 이동행렬을 구하기 위해서는 카메라 좌표축의 원점이 월드 좌표계 내에서 어느 위치인지는 어떻게 알 수 있을까요??

    시간이 되신다면 답변 해주시면 큰 도움이 될것입니다~

    • BlogIcon 다크pgmr 2021.05.18 17:08 신고 수정/삭제

      카메라의 3차원 위치 및 자세는 solvePnP를 이용해 구할 수 있습니다. 자세한 내용은 https://darkpgmr.tistory.com/122 글을 참고하시기 바랍니다.

    • BlogIcon 가나다 2021.05.24 09:42 수정/삭제

      3D 카메라를 활용할 시에도 동일하게 적용이 가능한가요?

      3D카메라를 로봇에 부착하여 로봇의 위치를 보정하는 것을 해보려하는데 3D 카메라의 좌표계를 월드 좌표계 기준에서 파악하기 어렵네요

    • BlogIcon 다크pgmr 2021.05.24 17:26 신고 수정/삭제

      기하학적인 연산을 푸는 것이기 때문에 어떤 카메라도 적용은 가능합니다. 그런데, 3D 카메라의 해상도가 낮으면 정확도가 문제가 될 것 같습니다. 3D 카메라에는 특화된 캘리브레이션 방법이 있을 것도 같은데, 3D 카메라 쪽은 저도 써보지 않아서 잘은 모르겠습니다.

  • 비전학생 2021.08.24 18:15 ADDR 수정/삭제 답글

    안녕항세요 다크님 Geometry 부분 찾아보고 검색하다가 다크님 블로그의 Geometry 부분 글을 읽다다가 지금 여기까지 반복해서 읽어보고 배우고 있습니다. 감사합니다.

    3D 도 결국에는 2D의 연속이라고 생각을 하는데 어떨 때 어떤 변환 및 처리를 해야하는지 감이 잘안오기도하네요..


    1-(1) 현재 object(ex 얼굴,단일이미지 아님)라는 3차원 모델을 opengl기반인 라이브러리를 사용하여 렌더링이 가능합니다.
    1-(2) 이 3차원 모델을 스테레오 카메라(2개의 카메라가 가로로 놓여짐,고정할 예정,물체는 움직일 수 있음)를 통해 보여지는 화면에다가 렌더링한 3차원 모델 object를 띄우고 싶습니다.
    1-(3) a가 예를들어 얼굴에 대한 3차원 모델이면 (2)에서 카메라를 통해서 얼굴이 비춰지면 그 얼굴에 object의 모델을 연결할때는, object를 3D 변환한다 라고 생각하는게 더맞는 개념일까요??

    2-그리고 캘리브레이션,월드좌표->카메라좌표, 카메라좌표->월드좌표 와 같은 작업을 하는것은 결국 같은 공간에서 좌표계마다 축,방향 이 다르기 때문에 이것을 맞춰주고 동일한 축,방향에서 처리하기 위함이 맞나요??

    3- 카메라를 통해서 보이는 화면을 볼때 이화면의 좌표계는 카메라좌표계가 맞나요??

    비전도 처음이고 좌표계에 대한 개념이 정확하게 잡히지 않아 질문도 너무 두루뭉실하게 드려서 죄송합니다.


    • BlogIcon 다크pgmr 2021.08.26 09:53 신고 수정/삭제

      안녕하세요. 좌표계의 개념에 대해서는 https://darkpgmr.tistory.com/77 글을 참고하시기 바랍니다. 카메라좌표계나 월드좌표계 모두 3차원 좌표계이지만, 카메라좌표계는 카메라를 따라 움직이는 카메라 중심의 좌표계이고 월드좌표계는 카메라와는 무관한 외부의 좌표계라는 점이 다릅니다.
      한가지 이해하셔야 할 것은 '좌표'라는 것은 '좌표계'에 종속된 개념이라는 것입니다. 자신의 눈 앞에 한 점이 있다고 상상해 봅니다. 이 점을 카메라로 봤을 때의 좌표(카메라좌표)와 벽의 한 모서리를 원점으로 했을 때의 좌표는 서로 다를 것입니다. 즉, 동일한 위치의 점이지만 기준이 무엇인지에 따라서 이 점의 좌표는 계속 바뀔 수 있습니다.
      이제 문제는, 공간의 한 점 P의 A 좌표계 좌표를 알고 있을 때 B좌표계 기준의 좌표를 어떻게 구할 것인데요, 이를 좌표계 변환이라고 합니다. 3D에서 좌표계 변환을 위해서는 두 좌표계 사이의 rotation, translation 관계를 알면 됩니다.
      풀고 계신 문제는 스테레오 카메라로 실제 물체의 3차원 좌표를 구한 후, 구해진 좌표(카메라좌표)에 대응되는 그래픽 모델의 좌표(월드좌표)를 카메라좌표로 변환하여 화면에 투영하는 것으로 생각됩니다. 월드좌표를 카메라좌표로 변환하기 위한 R, t 행렬은 solvePnP를 이용해 구할 수 있습니다. 관련 내용에 대해서는 https://darkpgmr.tistory.com/122 글을 참고하시기 바랍니다.

    • BlogIcon 비전학생 2021.08.26 18:27 수정/삭제

      댓글 달아주셔서 감사합니다. 제눈에 보이는 컵을 기준으로할때 눈(카메라), 임의의 기준에서 본 좌표(월드) 이렇게 설명해주시니 단번에 이해가 가네요. 결국은 카메라를 통해 화면에 보이는 2D영상도 카메라좌표계 라고 이해가 되네요.
      한가지 더 궁금한게 있어서 여쭤봅니다..
      현재 카메라를 통해 보여지는 프로그램화면은 (a)카메라좌표계, (b)띄우려고하는 그래픽모델의 좌표계, (c)실제 공간의 3차원 좌표계, 이렇게 3개의 좌표계가 있을때 b를 a로 맞춰주면 이론상 제가원하는 지점에 띄울 수가 있는게 맞나요??

    • BlogIcon 다크pgmr 2021.08.26 18:44 신고 수정/삭제

      이론적으로야 당연히 가능합니다. 다만 어떤 방법이 효율적일지는 구체적인 상황이나 제약조건에 따라 달라지는 것이기 때문에 본인이 직접 문제를 해결해 나가면서 풀어야 될 것으로 생각됩니다.

  • 릴리 2021.08.31 20:16 ADDR 수정/삭제 답글

    R 구할 때, 왜 Rx(-90도)는 왜 곱해주는건지 궁금합니다!

    • BlogIcon 다크pgmr 2021.08.31 21:21 신고 수정/삭제

      그림 1을 보고 해당 변환을 월드 좌표축에 하나씩 적용해 보시면 됩니다. 일단, 월드 X축을 기준으로 -90도 회전시키야 카메라 좌표계와 Z축이 맞겠지요.

  • 이상범 2021.10.08 13:37 ADDR 수정/삭제 답글

    항상 빠른 답변 감사드립니다. 복받으실거에요. ^^
    Rz(p)Rx(t) <-> Rx(t)Rz(p)
    식으로보면 좌우 동일할것같은데 그럼 안되잖아요
    안되는 이유가 궁금합니다.

    • BlogIcon 다크pgmr 2021.10.08 13:42 신고 수정/삭제

      왠지 빨리 답변해야 할 것 같네요.^^
      그건 기준축이 같이 돌아가는 것이 아니라 원래의 축을 기준으로 회전이 이루어지기 때문입니다