5,337
edits
Line 53: | Line 53: | ||
To convert depth values to euclidean distance, you need to divide by \(\cos(\theta)\) where \(\theta\) is the angle to the center of the image. | To convert depth values to euclidean distance, you need to divide by \(\cos(\theta)\) where \(\theta\) is the angle to the center of the image. | ||
{{hidden | Z-depth to Euclidean depth | | |||
<syntaxhighlight lang="python"> | |||
theta, phi = np.meshgrid((np.arange(width) + 0.5) * (2 * np.pi / width), | |||
(np.arange(height) + 0.5) * (np.pi / height)) | |||
uvs, uv_sides = my_helpers.spherical_to_cubemap(theta.reshape(-1), | |||
phi.reshape(-1)) | |||
cubemap_uvs = uvs.reshape(height, width, 2) | |||
# cubemap_uv_sides = uv_sides.reshape(height, width) | |||
world_coords = my_helpers.spherical_to_cartesian( | |||
cubemap_uvs[:, :, 0] * np.pi / 2 + np.pi / 4, | |||
cubemap_uvs[:, :, 1] * np.pi / 2 + np.pi / 4) | |||
cos_angle = world_coords @ np.array([0, 0, 1], dtype=np.float32) | |||
return depth_image / cos_angle[np.newaxis, :, :, np.newaxis] | |||
</syntaxhighlight> | |||
* Here <code>cubemap_uvs</code> are the UVs of each equirectangular pixel within the cubemap. | |||
Spherical to cubemap is defined as follows: | |||
<syntaxhighlight lang="python"> | |||
def spherical_to_cubemap(theta, phi): | |||
"""Converts spherical coordinates to cubemap coordinates. | |||
Args: | |||
theta: Longitude (azimuthal angle) in radians. [0, 2pi] | |||
phi: Latitude (altitude angle) in radians. [0, pi] | |||
Returns: | |||
uv: UVS in channel_last format | |||
idx: Side of the cubemap | |||
""" | |||
u = np.zeros(theta.shape, dtype=np.float32) | |||
v = np.zeros(theta.shape, dtype=np.float32) | |||
side = np.zeros(theta.shape, dtype=np.float32) | |||
side[:] = -1 | |||
for i in range(0, 4): | |||
indices = np.logical_or( | |||
np.logical_and(theta >= i * np.pi / 2 - np.pi / 4, theta <= | |||
(i + 1) * np.pi / 2 - np.pi / 4), | |||
np.logical_and(theta >= i * np.pi / 2 - np.pi / 4 + 2 * np.pi, theta <= | |||
(i + 1) * np.pi / 2 - np.pi / 4 + 2 * np.pi)) | |||
u[indices] = np.tan(theta[indices] - i * np.pi / 2) | |||
v[indices] = 1 / ( | |||
np.tan(phi[indices]) * np.cos(theta[indices] - i * np.pi / 2)) | |||
side[indices] = i + 1 | |||
top_indices = np.logical_or(phi < np.pi / 4, v >= 1) | |||
u[top_indices] = -np.tan(phi[top_indices]) * np.sin(theta[top_indices] - | |||
np.pi) | |||
v[top_indices] = np.tan(phi[top_indices]) * np.cos(theta[top_indices] - np.pi) | |||
side[top_indices] = 0 | |||
bottom_indices = np.logical_or(phi >= 3 * np.pi / 4, v <= -1) | |||
u[bottom_indices] = -np.tan(phi[bottom_indices]) * np.sin( | |||
theta[bottom_indices]) | |||
v[bottom_indices] = -np.tan(phi[bottom_indices]) * np.cos( | |||
theta[bottom_indices]) | |||
side[bottom_indices] = 5 | |||
assert not np.any(side < 0), "Side less than 0" | |||
return np.stack(((u + 1) / 2, (-v + 1) / 2), axis=-1), side | |||
</syntaxhighlight> | |||
}} | |||
==Fixed time step== | ==Fixed time step== |