Spaces:
Running
on
Zero
Running
on
Zero
| import numpy as np | |
| import torch | |
| from shap_e.models.nn.camera import DifferentiableCameraBatch, DifferentiableProjectiveCamera | |
| from shap_e.util.collections import AttrDict | |
| def create_custom_cameras(size: int, device: torch.device, azimuths=None, elevations=None, fov_degrees=30, distance=3.0) -> DifferentiableCameraBatch: | |
| """ | |
| Create custom camera angles for rendering. | |
| Args: | |
| size: The width and height of the rendered image. | |
| device: The device to put the camera parameters on. | |
| azimuths: List of azimuth angles in degrees. | |
| elevations: List of elevation angles in degrees. | |
| fov_degrees: Field of view in degrees. | |
| distance: Distance from the origin. | |
| Returns: | |
| A DifferentiableCameraBatch containing the specified cameras. | |
| """ | |
| if azimuths is None: | |
| azimuths = [0] | |
| if elevations is None: | |
| elevations = [0] | |
| origins = [] | |
| xs = [] | |
| ys = [] | |
| zs = [] | |
| for azimuth, elevation in zip(azimuths, elevations): | |
| # Convert to radians | |
| azimuth_rad = np.deg2rad(azimuth) | |
| elevation_rad = np.deg2rad(elevation) | |
| # Calculate camera position | |
| x_pos = distance * np.cos(elevation_rad) * np.sin(azimuth_rad) | |
| y_pos = distance * np.cos(elevation_rad) * np.cos(azimuth_rad) | |
| z_pos = distance * np.sin(elevation_rad) | |
| # Camera origin (position) | |
| origin = np.array([x_pos, y_pos, z_pos]) | |
| # Camera z-axis (looking at the origin) | |
| z = -origin / np.linalg.norm(origin) | |
| # Camera x-axis (right) | |
| x = np.array([np.cos(azimuth_rad + np.pi/2), np.sin(azimuth_rad + np.pi/2), 0.0]) | |
| x = x - np.dot(x, z) * z # Make orthogonal to z | |
| x = x / np.linalg.norm(x) # Normalize | |
| # Camera y-axis (up, computed as z cross x) | |
| y = np.cross(z, x) | |
| y = y / np.linalg.norm(y) # Normalize | |
| origins.append(origin) | |
| xs.append(x) | |
| ys.append(y) | |
| zs.append(z) | |
| # Convert from radians to the appropriate x and y fov | |
| fov_rad = np.deg2rad(fov_degrees) | |
| return DifferentiableCameraBatch( | |
| shape=(1, len(origins)), | |
| flat_camera=DifferentiableProjectiveCamera( | |
| origin=torch.from_numpy(np.stack(origins, axis=0)).float().to(device), | |
| x=torch.from_numpy(np.stack(xs, axis=0)).float().to(device), | |
| y=torch.from_numpy(np.stack(ys, axis=0)).float().to(device), | |
| z=torch.from_numpy(np.stack(zs, axis=0)).float().to(device), | |
| width=size, | |
| height=size, | |
| x_fov=fov_rad, | |
| y_fov=fov_rad, | |
| ), | |
| ) |