본문 바로가기
실습 & 활동/Computer vision

[Omniverse] Camera parameter 추출 및 시각화

by sim0609 2024. 5. 24.

이번 시간에는 Omniverse kaolin에서 얻은 camera matrix는 어떤 coordinate으로 표현되는지 확인해보고, camera 위치와 방향을 시각화하고자 한다.

 

일단, omniverse는 opengl coordinate을 따른다. 따라서, camera coordinate(world2camera) 기준의 extrinsic matrix는 opengl coordinate으로 표현된다. 

 

그리고 camera의 위치와 방향을 확인하기 위해 extrinsic matrix를 camera coordinate에서 world coordinate으로 변환했을 때 아래 그림과 같은 결과가 나온다. 

그리고 opencv coordinate으로도 camera의 위치와 방향을 확인할 수 있는데, 그 방법은 기존의 opengl coordinate에 해당하는 extrinsic matrix의 y, z 축을 -로 바꿔주면 된다. 그럼 아래와 같은 동일한 결과가 나온다.

추가적으로, opencv coordinate를 기준으로 3D obj의 point를 2D image에 투영하기 위해서 아래와 같은 과정을 거치면 된다. 

 

camera matrix = intrinsic matrix(3x4) @ extrinsic matrix(4x4) ← 3x4

points = camera matrix(3x4 - world) @ 3D obj vertices(4x1, homogeneous coordinate - world) ← 3x1

points = points / points[2] ← 3x1, (x/z, y/z, 1)

points = delete(img_points, -1) ← 2x1, (x/z, y/z)

extrinsic = np.load("sample/Scene_1/cam_param/1_extrinsic.npy")
intrinsic = np.load("sample/Scene_1/cam_param/1_intrinsic.npy")

extrinsic, intrinsic

(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
        [-0.        , -0.9781476 ,  0.20791169,  0.88033282],
        [-0.        , -0.20791169, -0.9781476 ,  3.13712052],
        [ 0.        ,  0.        ,  0.        ,  1.        ]]),
 array([[1.12145073e+03, 0.00000000e+00, 4.70000000e+02, 0.00000000e+00],
        [0.00000000e+00, 1.12145073e+03, 6.40000000e+02, 0.00000000e+00],
        [0.00000000e+00, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00],
        [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]))
        
intrinsic = np.delete(intrinsic, -1, axis=0) 
intrinsic # 3x4

array([[1.12145073e+03, 0.00000000e+00, 4.70000000e+02, 0.00000000e+00],
       [0.00000000e+00, 1.12145073e+03, 6.40000000e+02, 0.00000000e+00],
       [0.00000000e+00, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00]])
       
k = intrinsic @ extrinsic # 3x4
k

array([[ 1.12145073e+03, -9.77184947e+01, -4.59729372e+02,
         1.47444664e+03],
       [ 0.00000000e+00, -1.23000782e+03, -3.92851747e+02,
         2.99500701e+03],
       [ 0.00000000e+00, -2.07911691e-01, -9.78147601e-01,
         3.13712052e+00]])
         
scene = "Scene_1"
obj_base_path = f'C:\\Users\\user\\Downloads\\sample\\sample\\{scene}\\obj' # obj 폴더 경로 입력

obj_path = f'{obj_base_path}/{scene}.obj'
obj = pywavefront.Wavefront(obj_path, collect_faces=True)
obj.vertices

[(0.0924, 1.525, -0.144),
 (0.0933, 1.525, -0.1453),
 (0.0932, 1.523, -0.1449),
 (0.0924, 1.5234, -0.1437),
 (0.0923, 1.5221, -0.1431),
 (0.093, 1.5213, -0.1438),
 (0.0944, 1.5223, -0.1462),
 (0.0941, 1.5201, -0.1448),
 (0.0945, 1.525, -0.1468),
 (0.0925, 1.5201, -0.1422),
 (0.0919, 1.5215, -0.1419),
 (0.0935, 1.5186, -0.1426),
 (0.0915, 1.525, -0.1422),
 (0.0916, 1.5233, -0.1421),
 (0.0908, 1.5229, -0.1356),
 (0.0907, 1.5249, -0.1352),
 (0.0906, 1.5249, -0.1368),
 (0.0907, 1.5234, -0.1371),
 (0.0909, 1.5221, -0.1376),
 (0.0911, 1.5213, -0.1367),
 (0.0916, 1.5201, -0.1354),
 (0.0912, 1.5223, -0.1339),
 (0.0911, 1.525, -0.1334),
 (0.0915, 1.5201, -0.1384),
 (0.0911, 1.5215, -0.1389),
...
 (0.1031, 1.4649, -0.1292),
 (0.1103, 1.4645, -0.1301),
 (0.11, 1.4632, -0.1345),
 (0.092, 1.4605, -0.1246),
 ...]
 
ones = np.ones((obj.vertices.shape[0], 1))
vertex_homogeneous = np.hstack((obj.vertices, ones))
vertex_homogeneous # 5920x4

array([[ 0.0924,  1.525 , -0.144 ,  1.    ],
       [ 0.0933,  1.525 , -0.1453,  1.    ],
       [ 0.0932,  1.523 , -0.1449,  1.    ],
       ...,
       [-0.0461,  1.0339, -0.0851,  1.    ],
       [-0.0355,  1.0097, -0.0807,  1.    ],
       [-0.034 ,  1.0122, -0.0806,  1.    ]])
       
projected_points = np.zeros((vertex_homogeneous.shape[0], 2))
for i in range(vertex_homogeneous.shape[0]):
    p = k @ vertex_homogeneous[i]
    #print(p)
    p /= p[2] 
    #print(p)
    p = np.delete(p, -1)
    #print(p)
    projected_points[i] = p

projected_points # 5920x2

array([[504.99670781, 397.11316794],
       [505.32241527, 397.11510617],
       [505.2842637 , 397.88923233],
       ...,
       [452.79800963, 584.52553186],
       [456.75655424, 593.71087845],
       [457.31353008, 592.79668034]])
       
import matplotlib.pyplot as plt

# 각 점을 이미지에 그리기
for point in projected_points:
    x, y = point.ravel()
    cv2.circle(image, (int(x), int(y)), 5, (0, 255, 0), -1)

# 이미지를 표시
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title("Projected Points on Image")
plt.axis('on')  # 축을 표시하지 않음
plt.show()

 

3D에서 2D로 obj의 vertices를 투영하면, 다음과 같다.