티스토리 뷰

사람을 중심으로 camera 위치를 변형해 novel view synthesis를 하는 일을 하고 있다. 이 때 camera 위치 변화에 따라 camera parameter를 어떻게 바꿀지가 중요한데, 이 포스트는 코드와 함께 개념을 되짚어본다. 

 world coordinate, camera coordinate, 사람 위치, 카메라 위치에 대한 그림

 

 

ㄹ그림에서 보듯이 world coordinate 상에 사람이 저렇게 있을 때 camera의 위치를 높이는 안바꾸고 z축 기준으로만 회전시켜 novel view를 얻는 게 내 목표다. (왼쪽에 있는 빨간 점이 원래 카메라 위치, 오른쪽에 있는 빨간 점이 바뀐 카메라 위치) 카메라의 orientation은 당연히 z축이 사람을 향해 있고 (이건 가정이 아니고 사실), y축은 아래로, x 축은 오른쪽을 향해 있다고 가정하자. (내 가정이 본인 데이터셋과 맞는지는 본인이 확인해볼 것.) world coordinate system과 camera coordinate system 모두 나는 right-hand rule을 따르고 있다고 설정했다. 3d rotation의 기준을 잡아야되니까 그렇게 설정한 거지, left-hand rule을 따라도 상관은 없을 듯하다. 

카메라를 왼쪽의 빨간 점에서 오른 쪽의 빨간 점의 위치로 옮기기 위해서는, (현재 카메라 위치 - 사람의 중심 위치) vector를 z축을 기준으로 counter-clockwise 방향으로 𝝝만큼 회전 시킨 후, 사람의 중심위치에 회전된 vector를 더해야 한다. 참고로 바로 위의 그림에 있는 rotation matrix들이 right-hand rule에서 각 axis를 기준으로 counter-clockwise하게 𝝝만큼 회전시키는 것들이다. 위키에 위에 보면 clockwise라 되어있지만 밑의 하단의 설명을 보면 axis가 가리키는 방향에서 내려다봤을 때 counter-clockwise라고 쓰여있다. 밑은 30도 만큼 회전시키는 코드이다.

# R, t: 좌표값 변환행렬의 회전값과 위치변환값 / f, c: focal length, principal point
R, t, f, c = np.array(cam_data['R']), np.array(cam_data['t']), cam_data['f'], cam_data['c']

# 참고: https://redstarhong.tistory.com/107?category=328288
# camera orientation
cam_ori = R.transpose()
# camera center location
cam_loc = - np.matmul(R.transpose(), t)

root_joint = body_joint_world[0].cpu().numpy() * 1000  # m -> mm
root_cam_trans = cam_loc - root_joint

# counterclock-wise rotation around z axis
theta = np.pi / 6
sin, cos = np.sin(theta), np.cos(theta)
augR = np.eye(3)
augR[0,0], augR[1,1] = cos, cos
augR[0,1], augR[1,0] = -sin, sin
new_trans = np.matmul(augR, root_cam_trans)

new_cam_loc = root_joint + new_trans

이렇게 하면 new_cam_loc은 이제 맨 위 그림의 오른쪽 빨간 점의 위치가 된다. 하지만 끝난게 아닌게, 카메라가 사람을 향해 보고 있지 않아서 이미지에 사람이 안 보일 수 있다. 따라서 카메라의 방향을 보정해줘야 한다. 현재 카메라 좌표계의 y축이 아래를 향하고 있기 때문에 𝝝만큼 카메라를 y축 기준으로 clockwise (즉 아까와는 반대방향) 방향으로 회전시켜 줘야 한다. 근데 이게 좌표값이나 vector를 회전시키는게 아니라, 좌표축을 회전시키는 거라 3d rotation을 앞이 아니라 뒤에 곱해줘야한다. 왜냐면 엄밀히 말하면 cam_ori는 월드좌표축->카메라좌표축 변환 행렬이기 때문이다.

따라서 현재 camera orientation을  R.t, -𝝝 방향 회전을 -A라고 치면, 새로운 camera orientation 은 R.t x(-A)이다. 따라서 새로운 좌표'값' 변환행렬은 이것의 transpose인 (-A).t x R 이 된다.

# clock-wise rotation around y axis for camera orientation
theta = -np.pi / 6
sin, cos = np.sin(theta), np.cos(theta)
augR = np.eye(3)
augR[0,0], augR[2,2] = cos, cos
augR[0,2], augR[2,0] = sin, -sin

R = np.matmul(augR.transpose(), R)
# R = np.matmul(R, augR.transpose())

t = -np.matmul(R, new_cam_loc)

디버깅 코드

# visualize human body joints, camera locations
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib as mpl

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
vis_3d_pose(body_joint_world.cpu().numpy() * 1000, kps_line=human36_skeleton, joint_set_name='human36', ax_in=ax)
ax.scatter(cam_loc[None, 0], cam_loc[None, 1], cam_loc[None, 2], c='r')
ax.scatter(new_cam_loc[None, 0], new_cam_loc[None, 1], new_cam_loc[None, 2], c='b')

plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.waitKey(1)

plt.close(fig=fig)
import pdb;
pdb.set_trace()

빨간 점이 원래 카메라 위치, 파란 점이 새로운 카메라 위치

novel view synthesis 중 하나인 pixel-nerf의 input과 결과물. (왼쪽 것 말고도 2개 뷰를 추가로 src view로 썼다.)

'Research (연구 관련)' 카테고리의 다른 글

osmesa, pyrender, torch training bug  (0) 2021.08.13
ray & 3d bounding box intersection  (0) 2021.08.09
voxelnerf command 짜투리  (0) 2021.08.03
erosion, dilation  (0) 2021.08.01
flops  (0) 2021.07.20
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함