{"id":26175191,"url":"https://github.com/progamergov/pytorch360convert","last_synced_at":"2025-04-14T20:43:54.431Z","repository":{"id":268436309,"uuid":"903937088","full_name":"ProGamerGov/pytorch360convert","owner":"ProGamerGov","description":"PyTorch based image conversions between equirectangular, cubemap, and perspective. Based on py360convert","archived":false,"fork":false,"pushed_at":"2025-03-23T18:19:23.000Z","size":2718,"stargazers_count":10,"open_issues_count":2,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-13T05:49:09.296Z","etag":null,"topics":["360","360-camera","360-degree","360-photo","360-view","cubemap","equirectangular","hdri","hdri-environment","pano","perspective","photo-sphere","photo-sphere-viewer","skybox","spherical-photo","virtual-reality","vr","vr-photography"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ProGamerGov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-15T23:33:37.000Z","updated_at":"2025-03-23T18:19:25.000Z","dependencies_parsed_at":"2024-12-16T19:34:43.952Z","dependency_job_id":"b1b3e898-151d-4cbb-a82a-6db22bc32364","html_url":"https://github.com/ProGamerGov/pytorch360convert","commit_stats":null,"previous_names":["progamergov/pytorch360convert"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProGamerGov%2Fpytorch360convert","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProGamerGov%2Fpytorch360convert/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProGamerGov%2Fpytorch360convert/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProGamerGov%2Fpytorch360convert/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ProGamerGov","download_url":"https://codeload.github.com/ProGamerGov/pytorch360convert/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248670501,"owners_count":21142901,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["360","360-camera","360-degree","360-photo","360-view","cubemap","equirectangular","hdri","hdri-environment","pano","perspective","photo-sphere","photo-sphere-viewer","skybox","spherical-photo","virtual-reality","vr","vr-photography"],"created_at":"2025-03-11T20:18:04.852Z","updated_at":"2025-04-14T20:43:54.414Z","avatar_url":"https://github.com/ProGamerGov.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 📷 PyTorch 360° Image Conversion Toolkit\n\n[![PyPI - Version](https://img.shields.io/pypi/v/pytorch360convert)](https://pypi.org/project/pytorch360convert/)\n\n\n## Overview\n\nThis PyTorch-based library provides powerful and differentiable image transformation utilities for converting between different panoramic image formats:\n\n- **Equirectangular (360°) Images** \n- **Cubemap Representations**\n- **Perspective Projections**\n\nBuilt as an improved PyTorch implementation of the original [py360convert](https://github.com/sunset1995/py360convert) project, this library offers flexible, CPU \u0026 GPU-accelerated functions.\n\n\n\u003cdiv align=\"left\"\u003e\n \u003cimg src=\"examples/basic_equirectangular.png\" width=\"710px\"\u003e\n\u003c/div\u003e\n\n* Equirectangular format\n\n\n\u003cdiv align=\"left\"\u003e\n \u003cimg src=\"examples/basic_dice_cubemap.png\" width=\"710px\"\u003e\n\u003c/div\u003e\n\n* Cubemap 'dice' format\n\n\n## 🔧 Requirements\n\n- Python 3.7+\n- [PyTorch](https://pytorch.org/)\n\n\n## 📦 Installation\n\nYou can easily install the library using pip:\n\n```bash\npip install pytorch360convert\n```\n\nOr you can install it from source like this:\n\n```bash\npip install torch\n```\n\nThen clone the repository:\n\n```bash\ngit clone https://github.com/ProGamerGov/pytorch360convert.git\ncd pytorch360convert\npip install .\n```\n\n\n## 🚀 Key Features\n\n- Lossless conversion between image formats.\n- Supports different cubemap input formats (horizon, list, stack, dict, dice).\n- Configurable sampling modes (bilinear, nearest).\n- Supports different dtypes (float16, float32, float64, bfloat16).\n- CPU support.\n- GPU acceleration.\n- Differentiable transformations for deep learning pipelines.\n- [TorchScript](https://pytorch.org/docs/stable/jit.html) (JIT) support.\n\n\n## 💡 Usage Examples\n\n\n### Helper Functions\n\nFirst we'll setup some helper functions:\n\n```bash\npip install torchvision pillow\n```\n\n\n```python\nimport torch\nfrom torchvision.transforms import ToTensor, ToPILImage\nfrom PIL import Image\n\ndef load_image_to_tensor(image_path: str) -\u003e torch.Tensor:\n    \"\"\"Load an image as a PyTorch tensor.\"\"\"\n    return ToTensor()(Image.open(image_path).convert('RGB'))\n\ndef save_tensor_as_image(tensor: torch.Tensor, save_path: str) -\u003e None:\n    \"\"\"Save a PyTorch tensor as an image.\"\"\"\n    ToPILImage()(tensor).save(save_path)\n\n```\n\n### Equirectangular to Cubemap Conversion\n\nConverting equirectangular images into cubemaps is easy. For simplicity, we'll use the 'dice' format, which places all cube faces into a single 4x3 grid image.\n\n```python\nfrom pytorch360convert import e2c\n\n# Load equirectangular image (3, 1376, 2752)\nequi_image = load_image_to_tensor(\"examples/example_world_map_equirectangular.png\")\nface_w = equi_image.shape[2] // 4  # 2752 / 4 = 688\n\n# Convert to cubemap (dice format)\ncubemap = e2c(\n    equi_image,                   # CHW format\n    face_w=face_w,                # Width of each cube face\n    mode='bilinear',              # Sampling interpolation\n    cube_format='dice'            # Output cubemap layout\n)\n\n# Save cubemap faces\nsave_tensor_as_image(cubemap, \"dice_cubemap.jpg\")\n```\n\n| Equirectangular Input | Cubemap 'Dice' Output |\n| :---: | :----: |\n| ![](examples/example_world_map_equirectangular.png) | ![](examples/example_world_map_dice_cubemap.png) |\n\n| Cubemap 'Horizon' Output |\n| :---: |\n| ![](examples/example_world_map_horizon_cubemap.png) |\n\n### Cubemap to Equirectangular Conversion\n\nWe can also convert cubemaps into equirectangular images, like so.\n\n```python\nfrom pytorch360convert import c2e\n\n# Load cubemap in 'dice' format\ncubemap = load_image_to_tensor(\"dice_cubemap.jpg\")\n\n# Convert cubemap back to equirectangular\nequirectangular = c2e(\n    cubemap,              # Cubemap tensor(s)\n    mode='bilinear',      # Sampling interpolation\n    cube_format='dice'    # Input cubemap layout\n)\n\nsave_tensor_as_image(equirectangular, \"equirectangular.jpg\")\n```\n\n### Equirectangular to Perspective Projection\n\n```python\nfrom pytorch360convert import e2p\n\n# Load equirectangular input\nequi_image = load_image_to_tensor(\"examples/example_world_map_equirectangular.png\")\n\n# Extract perspective view from equirectangular image\nperspective_view = e2p(\n    equi_image,                   # Equirectangular image\n    fov_deg=(70, 60),             # Horizontal and vertical FOV\n    h_deg=260,                    # Horizontal rotation\n    v_deg=50,                     # Vertical rotation\n    out_hw=(512, 768),            # Output image dimensions\n    mode='bilinear'               # Sampling interpolation\n)\n\nsave_tensor_as_image(perspective_view, \"perspective.jpg\")\n```\n\n| Equirectangular Input | Perspective Output |\n| :---: | :----: |\n| ![](examples/example_world_map_equirectangular.png) | ![](examples/example_world_map_perspective.png) |\n\n\n\n### Equirectangular to Equirectangular\n\n```python\nfrom pytorch360convert import e2e\n\n# Load equirectangular input\nequi_image = load_image_to_tensor(\"examples/example_world_map_equirectangular.png\")\n\n# Rotate an equirectangular image around one more axes\nrotated_equi = e2e(\n    equi_image,                   # Equirectangular image\n    h_deg=90.0,                   # Vertical rotation/shift\n    v_deg=200.0,                  # Horizontal rotation/shift\n    roll=45.0,                    # Clockwise/counter clockwise rotation\n    mode='bilinear'               # Sampling interpolation\n)\n\nsave_tensor_as_image(rotated_equi, \"rotated.jpg\")\n```\n\n| Equirectangular Input | Rotated Output |\n| :---: | :----: |\n| ![](examples/example_world_map_equirectangular.png) | ![](examples/example_world_map_equirectangular_rotated.png) |\n\n\n## 📚 Basic Functions\n\n### `e2c(e_img, face_w=256, mode='bilinear', cube_format='dice')`\nConverts an equirectangular image to a cubemap projection.\n\n- **Parameters**:\n  - `e_img` (torch.Tensor): Equirectangular CHW image tensor.\n  - `face_w` (int, optional): Cube face width. If set to None, then face_w will be calculated as `\u003ce_img_height\u003e // 2`. Default: `None`.\n  - `mode` (str, optional): Sampling interpolation mode. Options are `bilinear`, `bicubic`, and `nearest`. Default: `bilinear`\n  - `cube_format` (str, optional): The desired output cubemap format. Options are `dict`, `list`, `horizon`, `stack`, and `dice`. Default: `dice`\n    - `stack` (torch.Tensor): Stack of 6 faces, in the order of: ['Front', 'Right', 'Back', 'Left', 'Up', 'Down'].\n    - `list` (list of torch.Tensor): List of 6 faces, in the order of: ['Front', 'Right', 'Back', 'Left', 'Up', 'Down'].\n    - `dict` (dict of torch.Tensor): Dictionary with keys pointing to face tensors. Keys are: ['Front', 'Right', 'Back', 'Left', 'Up', 'Down'].\n    - `dice` (torch.Tensor): A cubemap in a 'dice' layout.\n    - `horizon` (torch.Tensor): A cubemap in a 'horizon' layout, a 1x6 grid in the order: ['Front', 'Right', 'Back', 'Left', 'Up', 'Down'].\n  - `channels_first` (bool, optional): Input cubemap channel format (CHW or HWC). Defaults to the PyTorch CHW standard of `True`.\n\n- **Returns**: Cubemap representation of the input image as a tensor, list of tensors, or dict or tensors.\n\n### `c2e(cubemap, h, w, mode='bilinear', cube_format='dice')`\nConverts a cubemap projection to an equirectangular image.\n\n- **Parameters**:\n  - `cubemap` (torch.Tensor, list of torch.Tensor, or dict of torch.Tensor): Cubemap image tensor, list of tensors, or dict of tensors. Note that tensors should be in the shape of: `CHW`, except for when `cube_format = 'stack'`, in which case a batch dimension is present. Inputs should match the corresponding `cube_format`.\n  - `h` (int, optional): Output image height. If set to None, `\u003ccube_face_width\u003e * 2` will be used. Default: `None`.\n  - `w` (int, optional): Output image width. If set to None, `\u003ccube_face_width\u003e * 4` will be used. Default: `None`.\n  - `mode` (str, optional): Sampling interpolation mode. Options are `bilinear`, `bicubic`, and `nearest`. Default: `bilinear`\n  - `cube_format` (str, optional): Input cubemap format. Options are `dict`, `list`, `horizon`, `stack`, and `dice`. Default: `dice`\n    - `stack` (torch.Tensor): Stack of 6 faces, in the order of: ['Front', 'Right', 'Back', 'Left', 'Up', 'Down'].\n    - `list` (list of torch.Tensor): List of 6 faces, in the order of: ['Front', 'Right', 'Back', 'Left', 'Up', 'Down'].\n    - `dict` (dict of torch.Tensor): Dictionary with keys pointing to face tensors. Keys are expected to be: ['Front', 'Right', 'Back', 'Left', 'Up', 'Down'].\n    - `dice` (torch.Tensor): A cubemap in a 'dice' layout.\n    - `horizon` (torch.Tensor): A cubemap in a 'horizon' layout, a 1x6 grid in the order of: ['Front', 'Right', 'Back', 'Left', 'Up', 'Down'].\n  - `channels_first` (bool, optional): Input cubemap channel format (CHW or HWC). Defaults to the PyTorch CHW standard of `True`.\n     \n- **Returns**: Equirectangular projection of the input cubemap as a tensor.\n\n### `e2p(e_img, fov_deg, h_deg, v_deg, out_hw, in_rot_deg=0, mode='bilinear')`\nExtracts a perspective view from an equirectangular image.\n\n- **Parameters**:\n  - `e_img` (torch.Tensor): Equirectangular CHW or NCHW image tensor.\n  - `fov_deg` (float or tuple of float): Field of view in degrees. If a single value is provided, it will be used for both horizontal and vertical degrees. If using a tuple, values are expected to be in following format: (h_fov_deg, v_fov_deg).\n  - `h_deg` (float, optional): Horizontal viewing angle in range [-pi, pi]. (-Left/+Right). Default: `0.0`\n  - `v_deg` (float, optional): Vertical viewing angle in range [-pi/2, pi/2]. (-Down/+Up). Default: `0.0`\n  - `out_hw` (float or tuple of float, optional): Output image dimensions in the shape of '(height, width)'. Default: `(512, 512)`\n  - `in_rot_deg` (float, optional): Inplane rotation angle. Default: `0`\n  - `mode` (str, optional): Sampling interpolation mode. Options are `bilinear`, `bicubic`, and `nearest`. Default: `bilinear`\n  - `channels_first` (bool, optional): Input cubemap channel format (CHW or HWC). Defaults to the PyTorch CHW standard of `True`.\n\n- **Returns**: Perspective view of the equirectangular image as a tensor.\n\n### `e2e(e_img, h_deg, v_deg, roll=0, mode='bilinear')`\n\nRotate an equirectangular image along one or more axes (roll, pitch, and yaw) to produce a horizontal shift, vertical shift, or to roll the image.\n\n- **Parameters**:\n  - `e_img` (torch.Tensor): Equirectangular CHW or NCHW image tensor.\n  - `roll` (float, optional): Roll angle in degrees (-Counter_Clockwise/+Clockwise). Rotates the image along the x-axis. Default: `0.0`\n  - `h_deg` (float, optional): Yaw angle in degrees (-Left/+Right). Rotates the image along the z-axis to produce a horizontal shift. Default: `0.0`\n  - `v_deg` (float, optional): Pitch angle in degrees (-Down/+Up). Rotates the image along the y-axis to produce a vertical shift. Default: `0.0` \n  - `mode` (str, optional): Sampling interpolation mode. Options are `bilinear`, `bicubic`, and `nearest`. Default: `bilinear`\n  - `channels_first` (bool, optional): Input cubemap channel format (CHW or HWC). Defaults to the PyTorch CHW standard of `True`.\n\n- **Returns**: A modified equirectangular image tensor.\n\n\n## 🤝 Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n\n## 🔬 Citation\n\nIf you use this library in your research or project, please refer to the included [CITATION.cff](CITATION.cff) file or cite it as follows:\n\n### BibTeX\n```bibtex\n@misc{egan2024pytorch360convert,\n  title={PyTorch 360° Image Conversion Toolkit},\n  author={Egan, Ben},\n  year={2024},\n  publisher={GitHub},\n  howpublished={\\url{https://github.com/ProGamerGov/pytorch360convert}}\n}\n```\n\n### APA Style\n```\nEgan, B. (2024). PyTorch 360° Image Conversion Toolkit [Computer software]. GitHub. https://github.com/ProGamerGov/pytorch360convert\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogamergov%2Fpytorch360convert","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprogamergov%2Fpytorch360convert","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogamergov%2Fpytorch360convert/lists"}