카메라/기하학

2D 영상에서 물체까지 3D 거리 구하기

dohyeon2 2022. 2. 19. 13:09

목차

    2022-02-18

    2D 영상 내에서 특정 물체까지의 3D 거리정보를 얻는 방법은 여러가지가 있었는데 

    나는 그중 3D 변환을 이용한 방법을 사용하였다. 


    <이론>

    3D 변환을 이용한 방법은 가장 일반적인 방법이며, 영상 기하학에서 좌표계에 대한 이해만 있으면 

    어렵지 않게 적용할 수 있다.

    이 방법을 사용하기 위해서는 카메라의 내부 파라미터(fx, fy, cx, cy)와 카메라 3D 자세정보(R, t)가 미리 구해져 있어야만 사용 가능하다. 

     

    카메라의 내부 파라미터(fx, fy, cx, cy) 및 3D 자세정보(R,t)는 앞선 글에서 구하였다.

     

    카메라 내부 파라미터(fx, fy, cx, cy) -  <참조: https://dohyeon.tistory.com/23 

     

    [영상처리] 카메라 캘리브레이션 (Camera Calibration)

    2022-02-18 실험실에서 진행하는 프로젝트에서 2D 이미지 내에서 카메라와 물체까지의 3차원 거리를 구하는 task가 주어졌다. 기하학적 계산에 앞서 2차원 이미지의 3차원 변환을 위해서는 camera의 내

    dohyeon.tistory.com

    카메라 3D 자세정보(R, t) - <참조: https://dohyeon.tistory.com/25?category=1056956 >

     

    [영상처리] 카메라의 위치 및 3D 자세정보

    2차원 영상 내에서 3차원 거리정보를 얻기 위해서는 카메라 내부 파라미터 뿐만 아니라 카메라의 위치 및 3D 자세정보가 필요하다. 지난 글에서 카메라 내부 파라미터를 구했으니 https://dohyeon.tist

    dohyeon.tistory.com

     

    구해진 내부 파라미터와 3D 자세정보를 이용하여 2D 영상 내 특정 픽셀의 3D 거리정보를 구하는 방법을 알아보자.

     

    아래 설명의 이해를 돕기위한 좌표계 그림

     

    어떤 3차원 공간상의 한 점 P에 대한 카메라좌표를 Pc, 월드좌표를 Pw라 하면 Pc와 Pw 사이의 변환은 다음 수식에 의해 진행된다.

     

    식 (1)

    입력 영상의 픽셀좌표를 p(x,y), 대응되는 지면좌표를 P(X, Y)라 하자.

     

    먼저 카메라의 내부파라미터에 대한 영향을 없애기 위해 픽셀좌표를 정규좌표로 변환한다 (영상에서 모든 기하학적 해석은 정규좌표를 통해 이루어진다).

    식 (2)

    이 때, 구한 정규좌표를 3차원 카메라좌표로 해석하면 (u, v, 1)이 된다. 정규이미지평면은 카메라 원점에서 초점거리가 1인 평면이므로 정규이미지 평면 상의 점 (u, v)의 카메라좌표계 좌표는 (u, v, 1)이 된다. 이 점을 Pc = (u, v, 1)라 하자.

     

    이제 카메라 원점과 Pc를 연결한 직선이 지면과 만나는 점을 구하면 최종 목표를 이루는 것이다.

    지면과의 교점을 구하기 위해서는 카메라좌표계가 아닌 월드좌표계에서 계산을 수행해야하는데, 

    카메라 원점의 카메라좌표를 Cc, 월드좌표를 Cw라 하고 점 Pc의 월드좌표를 Pw라 하자. 

    <카메라 원점의 카메라좌표는 항상 (0,0,0)임에 주의, 즉 Cc=(0,0,0)>

     

    대응되는 월드좌표는 식 (1)를 이용하여 다음과 같이 계산된다. 

     

    3D 좌표계 변환

    이제 월드 좌표계 상에서 Cw와 Pw를 잇는 직선이 지면과 만나는 점을 구해보자. 벡터의 개념을 이용하면 Cw와 Pw를 잇는 직선상의 임의의 점 P = Cw + k(Pw - Cw) 로 표현할 수 있다. (K는 임의의 상수)

     

    지면과 만나는 점 P

     그런데, 월드좌표계 상에서 지면은 Z =0 이므로 Cw + k(Pw - Cw)의 Z좌표가 0이 되도록 k의 값을 구하면 

    월드 좌표계에서 지면과 만나는 점 P를 구할 수 있다!!! 

    <여기서 구한 지면좌표는 월드좌표계를 어떻게 설정하느냐에 따라 달라지는 값임에 주의>

     


    <적용>

    나의 경우 ZED2i camera를 이용해 테스트하였다.(2개의 렌즈를 가진 streo camera지만 한쪽 렌즈에서 촬영한 2D 이미지 정보만 이용하였다.)

     

    앞서 구한 카메라 파라미터 및 3D 자세정보

    Fx = 1065.352

    Fy = 1064.480

    Cx = 960.127

    Cy = 569.483

    R =

    [[ 0.99833387,  0.05028667, -0.02829721],
    [ 0.0462584 , -0.99063762, -0.12844172],
    [-0.03449118,  0.12691873, -0.99131327]]

    t = (0.29921233, -1.35458807, 56.65101544)

    입력영상의 픽셀좌표 x ,y =(966,544) 

    픽셀좌료의 정규좌표 u = (x - Cx)/Fx = 0.005512731942

                                v = (y - Cy)/Fy = -0.02393938825

     

    정규이미지 평면상의 점의 카메라좌표 Pc = (0.005512731942, -0.02393938825, 1)^T

    카메라 원점의 카메라좌표 Cc = (0,0,0)^T

    점 Pc 의 월드좌표 Pw = R^T(Pc - t)

    = [[ 1.68781261]
       [-8.39611602]
       [55.00499017]]

    아래 코드 참조

    import numpy as np 
    
    Rt = np.array([[ 0.99833387,  0.05028667, -0.02829721],
           [ 0.0462584 , -0.99063762, -0.12844172],
           [-0.03449118,  0.12691873, -0.99131327]]).T
    
    
    
    Pc = np.array([[0.005512731942, -0.02393938825, 1]]).T
    t = np.array([[0.29921233, -1.35458807, 56.65101544]]).T
    
    a = Rt
    b = (Pc - t)
    
    # a행렬 b행렬 행렬곱
    print(np.dot(a,b))

     

     

    Cw = R^T(Cc - t) = -(R^T)t =

    [[ 1.71790764] 
     [-8.54702723] 
     [55.99338462]]

     

    아래코드 참조

    import numpy as np 
    
    Rt = np.array([[ 0.99833387,  0.05028667, -0.02829721],
           [ 0.0462584 , -0.99063762, -0.12844172],
           [-0.03449118,  0.12691873, -0.99131327]]).T
    
    
    
    Pc = np.array([[0.005512731942, -0.02393938825, 1]]).T
    t = np.array([[0.29921233, -1.35458807, 56.65101544]]).T
    
    a = Rt
    b = (Pc - t)
    
    #print(np.dot(a,b))
    
    c = (-t)
    
    print(np.dot(a,c))

     

    마지막으로 내가 최종적으로 구하려는 지면과의 교점

    위 공식에서 임의의 상수 k는 점 P의 z좌표가 0이라는 사실을 이용하여 구할 수 있다. 

     

    (Cw의 z 좌표) + k(Pw의 z좌표- Cw의 z 좌표) = 0 

    을 이용하면 결과적으로 

    k = 56.65084883 을 얻을 수 있다. 

     

    따라서 

    점 P = Cw + k(Pw-Cw) 이므로 

     

    최종코드 

    import numpy as np 
    
    Rt = np.array([[ 0.99833387,  0.05028667, -0.02829721],
           [ 0.0462584 , -0.99063762, -0.12844172],
           [-0.03449118,  0.12691873, -0.99131327]]).T
    
    
    
    Pc = np.array([[0.005512731942, -0.02393938825, 1]]).T
    t = np.array([[0.29921233, -1.35458807, 56.65101544]]).T
    
    a = Rt
    b = (Pc - t)
    c = (-t)
    Pw = np.dot(a,b)
    Cw = np.dot(a,c)
    k = 56.65084883
    # print(Pw)
    # print(Cw)
    
    P = Cw + k*(Pw-Cw)
    print(P)

    위 코드로 지면과의 교점 P의 3차원 좌표를 구할 수 있다. 

    '카메라 > 기하학' 카테고리의 다른 글

    [Depth camera] 이론  (0) 2022.04.25
    카메라의 위치 및 3D 자세정보  (2) 2022.02.18
    카메라 캘리브레이션 (Camera Calibration)  (2) 2022.02.18
    카메라 왜곡보정 - Camera Models  (0) 2021.06.27