karthikeya1212's picture
Upload 115 files
cda88e0 verified
import numpy as np
import math
from abc import ABC
import copy
class camera(ABC):
def __init__(self, hfov, h, w, height=100.0):
self.fov = hfov
self.h = h
self.w = w
self.ori_height = height
self.height = copy.deepcopy(self.ori_height)
self.O = np.array([0.0, self.height, 0.0]) # ray origianl
######################################################################################
""" Abstraction
"""
def align_horizon(self, cur_horizon):
raise NotImplementedError('Not implemented yet')
def C(self):
raise NotImplementedError('Not implemented yet')
def right(self):
raise NotImplementedError('Not implemented yet')
def up(self):
raise NotImplementedError('Not implemented yet')
######################################################################################
def deg2rad(self, d):
return d / 180.0 * 3.1415925
def rad2deg(self, d):
return d / 3.1415925 * 180.0
def get_ray(self, xy):
""" Assume the center is on the top-left corner
"""
u, v = xy
mat = self.get_ABC_mat()
r = np.dot(mat, np.array([u, v, 1.0]).T)
# r = r/np.sqrt(r @ r)
return r
def project(self, xyz):
relative = xyz - self.O
mat = self.get_ABC_mat()
pp = np.dot(np.linalg.inv(mat), relative)
pixel = np.array([pp[0]/pp[2], pp[1]/pp[2]])
return pixel
def xyh2w(self, xyh):
u, v, h = xyh
foot_xyh = np.copy(xyh)
foot_xyh[1] = foot_xyh[1] + foot_xyh[2]
foot_xyh[2] = 0.0
fu, fv, fh = foot_xyh
a = self.right()
b = -self.up()
c = self.C()
mat = self.get_ABC_mat()
w = -self.height/(a[1] * fu + b[1] * fv + c[1])
return w
def xyh2xyz(self, xyh):
u, v, h = xyh
foot_xyh = np.copy(xyh)
foot_xyh[1] = foot_xyh[1] + foot_xyh[2]
foot_xyh[2] = 0.0
fu, fv, fh = foot_xyh
a = self.right()
b = -self.up()
c = self.C()
mat = self.get_ABC_mat()
w = -self.height/(a[1] * fu + b[1] * fv + c[1])
# print('w: {} a*u + b * v + c: {}, b/c: {}/{}, fv: {}'.format(w, a[1] * fu + b[1] * fv + c[1], b, c, fv))
xyz = self.O + np.dot(mat, np.array([u, v, 1.0]).T) * w
# print('w: {}, -{}/{}'.format(w, self.height, a[1] * fu + b[1] * fv + c[1]))
return xyz
def xyz2xyh(self, xyz):
foot_xyz = np.copy(xyz)
foot_xyz[1] = 0.0
foot_xy = self.project(foot_xyz)
xy = self.project(xyz)
ret = np.copy(xyz)
ret[:2] = xy
ret[2] = foot_xy[1] - xy[1]
return ret
def get_ABC_mat(self):
a = self.right()
b = -self.up()
c = self.C()
mat = np.concatenate([a[:, None], b[:,None], c[:, None]], axis=1)
return mat
class pitch_camera(camera):
""" Picth alignment camera
"""
def __init__(self, hfov, h, w, height=100.0):
"""
alignment algorithm:
1. pitch alignment
2. axis alignment
"""
super().__init__(hfov, h, w, height)
self.ori_view = np.array([0.0, 0.0, -1.0])
self.cur_view = np.copy(self.ori_view)
def align_horizon(self, cur_horizon):
""" Given horizon, compute the camera pitch
"""
ref_horizon = self.h / 2
rel_distance = -(ref_horizon - cur_horizon)
focal = self.focal()
pitch = math.atan2(rel_distance, focal)
# construct a rotation matrix
c, s = np.cos(pitch), np.sin(pitch)
rot = np.array([[0, 0, 0], [0, c, -s], [0, s, c]])
# compute the new view vector
img_plane_view = self.ori_view * focal
img_plane_view = rot @ img_plane_view.T
self.cur_view = img_plane_view / math.sqrt(np.dot(img_plane_view, img_plane_view))
def C(self):
return self.view() * self.focal() - 0.5 * self.w * self.right() + 0.5 * self.h * self.up()
def right(self):
return np.array([1.0, 0.0, 0.0])
def up(self):
return np.cross(self.right(), self.view())
def focal(self):
focal = self.w * 0.5 / math.tan(self.deg2rad(self.fov * 0.5))
return focal
def view(self):
return self.cur_view
class axis_camera(camera):
""" Axis alignment camera
"""
def __init__(self, hfov, h, w, height=100.0):
super().__init__(hfov, h, w, height)
focal = self.w * 0.5 / math.tan(self.deg2rad(self.fov * 0.5))
self.up_vec = np.array([0.0, 1.0, 0.0])
self.right_vec = np.array([1.0, 0.0, 0.0])
self.ori_c = np.array([-0.5 * self.w, 0.5 * self.h, -focal])
self.c_vec = np.copy(self.ori_c)
def align_horizon(self, cur_horizon):
""" Given horizon, we move the axis to update the horizon
i.e. we need to change C
"""
ref_horizon = self.h // 2
delta_horizon = cur_horizon - ref_horizon
self.c_vec = self.ori_c + delta_horizon * self.up()
# self.height = self.ori_height + delta_horizon
# self.O = np.array([0.0, self.height, 0.0])
def C(self):
return self.c_vec
def right(self):
return self.right_vec
def up(self):
return self.up_vec
def test(ppc):
xyh = np.array([500, 500, 100.0])
proj_xyz = ppc.xyh2xyz(xyh)
proj_xyh = ppc.xyz2xyh(proj_xyz)
print('xyh: {}, proj xyz: {}, proj xyh: {}'.format(xyh, proj_xyz, proj_xyh))
# import pdb; pdb.set_trace()
new_horizon_list = [0, 100, 250, 400, 500]
new_horizon_list = [100, 250, 400, 500]
# import pdb; pdb.set_trace()
for cur_horizon in new_horizon_list:
ppc.align_horizon(cur_horizon)
test_xyh = np.array([500, cur_horizon, 0])
test_xyz = ppc.xyh2xyz(test_xyh)
# print('{} -> {} -> {}'.format(test_xyh, test_xyz, ppc.xyz2xyh(test_xyz)))
print('{} \t -> {} \t -> {}'.format(test_xyh, test_xyz, ppc.xyz2xyh(test_xyz)))
if __name__ == '__main__':
p_camera = pitch_camera(90.0, 500, 500)
a_camera = axis_camera(90.0, 500, 500)
test(p_camera)
test(a_camera)