반응형
실제 카메라를 설치할 때 공간적 제약 혹은 화각의 문제로 카메라를 돌려서 설치하는 경우가 있다. 시계 방향으로 90도 혹은 반시계 방향으로 90도가 가장 흔한 경우인데 이 때 이미지는 또 똑바로 보고 싶을 때도 많다.
이미지만 사용할 경우에야 간단히 cv2.rotate를 쓰든 numpy를 쓰든 돌리면 끝이지만 만약 카메라 캘리브레이션 값도 같이 써야할 경우는 귀찮은 일이 많이 생긴다.
90도 돌린 경우에 intrinsic parameter는 focal length, fx, fy를 서로 스위칭해주어야 하고 principal point는 회전 방향에 따라 값을 재계산해주어야 한다. 또한 extrinsinc parameter 역시 yaw rotation을 가해주어야 한다.
계산하는 것이 어렵지는 않다만 귀찮고 제대로 됐는지 확인하는 과정에 시간 소모가 매번 적지 않게 들기 때문에 함수로 구현하여 정리했다.
def rotate_intrinsic(img_w, img_h, K, dist, direction="none"):
if direction == "none":
return K, dist
K_new = np.eye(3, dtype=np.float32)
fx, fy = K[0, 0], K[1, 1]
cx, cy = K[0, 2], K[1, 2]
if direction == "cw": # clockwise
fx_new = fy
fy_new = fx
cx_new = img_h - cy
cy_new = cx
img_w_new = img_h
img_h_new = img_w
elif direction == "ccw": # couter-clockwise
fx_new = fy
fy_new = fx
cx_new = cy
cy_new = img_w - cx
img_w_new = img_h
img_h_new = img_w
K_new[0, 0] = fx_new
K_new[1, 1] = fy_new
K_new[0, 2] = cx_new
K_new[1, 2] = cy_new
dist_new = dist
return img_w_new, img_h_new, K_new, dist_new
def rotate_extrinsic(SE3, direction="none"):
if direction == "none":
SE3_new = SE3
elif direction == "cw": #clockwise
Rz = np.eye(4, dtype=np.float32)
radian = -np.pi/2
Rz[0, 0] = np.cos(radian)
Rz[0, 1] = -np.sin(radian)
Rz[1, 0] = np.sin(radian)
Rz[1, 1] = np.cos(radian)
SE3_new = np.matmul(SE3, Rz)
elif direction == "ccw": #couter-clockwise
Rz = np.eye(4, dtype=np.float32)
radian = np.pi / 2
Rz[0, 0] = np.cos(radian)
Rz[0, 1] = -np.sin(radian)
Rz[1, 0] = np.sin(radian)
Rz[1, 1] = np.cos(radian)
SE3_new = np.matmul(SE3, Rz)
return SE3_new
def rotate_camera(img_w, img_h, K, dist, SE3, direction="none"):
img_w_new, img_h_new, K_new, dist_new = rotate_intrinsic(img_w, img_h, K, dist, direction)
SE3_new = rotate_extrinsic(SE3, direction)
return img_w_new, img_h_new, K_new, dist_new, SE3_new
'''
img = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)
img_w_new, img_h_new, K_new, dist_new, T_new = rotate_camera(img_w, img_h, K, dist, T, direction="ccw")
T denotes SE3 matrix that converts camera coordinates to global coordinates (a.k.a T_gc)
'''
위 코드를 이용해 이미지를 시계 방향으로 돌렸다면 기존 카메라 캘리브레이션 값을 시계 방향으로 돌린 버전을 얻을 수 있고 반시계도 마찬가지다. 하지만 추천하지는 않는다!
가독성과 유지 보수를 쉽게 하지 위해선 이미지도 그대로 카메라 자세도 캘리브레이션 상태 그대로 사용하는 것이 가장 좋다. 이미지를 돌려보는 행위는 사람이 보기 쉽게 하려는 행위 밖에 없는데 그냥 어렵게 보는게 차라리 낫다.
반응형
'Knowhow > Vision' 카테고리의 다른 글
Open3d를 이용한 디버깅용 camera, bbox, origin visualization (0) | 2023.12.06 |
---|---|
Sphere 상에서 normal vector uniform sampling (0) | 2023.11.07 |
Torch를 이용한 matrix inverse(+속도를 빠르게 만들 수 있는 경우) (0) | 2023.05.18 |
Epipolar line visualization (0) | 2023.03.24 |
Open3d manual registration (손으로 point cloud 정합하기) (0) | 2023.03.20 |