109 Commits

Author SHA1 Message Date
Jeremy Reizenstein
0eac8299d4 MKL version fix in CI (#1820)
Summary:
Fix for "undefined symbol: iJIT_NotifyEvent" build issue,

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1820

Differential Revision: D58685326
2024-06-20 09:24:07 -07:00
vedrenne
b0462d8079 Allow indexing for classes inheriting Transform3d (#1801)
Summary:
Currently, it is not possible to access a sub-transform using an indexer for all 3d transforms inheriting the `Transforms3d` class.
For instance:

```python
from pytorch3d import transforms

N = 10
r = transforms.random_rotations(N)
T = transforms.Transform3d().rotate(R=r)
R = transforms.Rotate(r)

x = T[0]  # ok
x = R[0]  # TypeError: __init__() got an unexpected keyword argument 'matrix'
```

This is because all these classes (namely `Rotate`, `Translate`, `Scale`, `RotateAxisAngle`) inherit the `__getitem__()` method from `Transform3d` which has the [following code on line 201](https://github.com/facebookresearch/pytorch3d/blob/main/pytorch3d/transforms/transform3d.py#L201):

```python
return self.__class__(matrix=self.get_matrix()[index])
```

The four classes inheriting `Transform3d` are not initialized through a matrix argument, hence they error.
I propose to modify the `__getitem__()` method of the `Transform3d` class to fix this behavior. The least invasive way to do it I can think of consists of creating an empty instance of the current class, then setting the `_matrix` attribute manually. Thus, instead of
```python
return self.__class__(matrix=self.get_matrix()[index])
```
I propose to do:
```python
instance = self.__class__.__new__(self.__class__)
instance._matrix = self.get_matrix()[index]
return instance
```

As far as I can tell, this modification occurs no modification whatsoever for the user, except for the ability to index all 3d transforms.

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1801

Reviewed By: MichaelRamamonjisoa

Differential Revision: D58410389

Pulled By: bottler

fbshipit-source-id: f371e4c63d2ae4c927a7ad48c2de8862761078de
2024-06-17 07:48:18 -07:00
Jeremy Reizenstein
b66d17a324 Undo c10=>std optional rename
Summary: Undoes the pytorch3d changes in D57294278 because they break builds for for PyTorch<2.1 .

Reviewed By: MichaelRamamonjisoa

Differential Revision: D57379779

fbshipit-source-id: 47a12511abcec4c3f4e2f62eff5ba99deb2fab4c
2024-06-17 07:09:30 -07:00
Kyle Vedder
717493cb79 Fixed last dimension size check so that it doesn't trivially pass. (#1815)
Summary:
Currently, it checks that the `2`th dimension of `p2` is the same size as the `2`th dimension of `p2` instead of `p1`.

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1815

Reviewed By: MichaelRamamonjisoa

Differential Revision: D58586966

Pulled By: bottler

fbshipit-source-id: d4f723fa264f90fe368c10825c1acdfdc4c406dc
2024-06-17 06:00:13 -07:00
Jeremy Reizenstein
302da69461 builds for PyTorch 2.2.1 2.2.2 2.3.0 2.3.1
Summary: Build for new pytorch versions

Reviewed By: MichaelRamamonjisoa

Differential Revision: D58668956

fbshipit-source-id: 7fdfb377b370448d6147daded6a21b8db87586fb
2024-06-17 05:57:59 -07:00
Roman Shapovalov
4ae25bfce7 Moving ray bundle to float dtype
Summary: We can now move ray bundle to float dtype (e.g. from fp16 like types).

Reviewed By: bottler

Differential Revision: D57493109

fbshipit-source-id: 4e18a427e968b646fe5feafbff653811cd007981
2024-05-30 10:06:38 -07:00
Richard Barnes
bd52f4a408 c10::optional -> std::optional in tensorboard/adhoc/Adhoc.h +9
Summary: `c10::optional` was switched to be `std::optional` after PyTorch moved to C++17. Let's eliminate `c10::optional`, if we can.

Reviewed By: albanD

Differential Revision: D57294278

fbshipit-source-id: f6f26133c43f8d92a4588f59df7d689e7909a0cd
2024-05-13 16:40:34 -07:00
generatedunixname89002005307016
17117106e4 upgrade pyre version in fbcode/vision - batch 2
Differential Revision: D57183103

fbshipit-source-id: 7e2f42ddc6a1fa02abc27a451987d67a00264cbb
2024-05-10 01:18:43 -07:00
Richard Barnes
aec76bb4c8 Remove unused-but-set variables in vision/fair/pytorch3d/pytorch3d/csrc/pulsar/include/renderer.render.device.h +1
Summary:
This diff removes a variable that was set, but which was not used.

LLVM-15 has a warning `-Wunused-but-set-variable` which we treat as an error because it's so often diagnostic of a code issue. Unused but set variables often indicate a programming mistake, but can also just be unnecessary cruft that harms readability and performance.

Removing this variable will not change how your code works, but the unused variable may indicate your code isn't working the way you thought it was. I've gone through each of these by hand, but mistakes may have slipped through. If you feel the diff needs changes before landing, **please commandeer** and make appropriate changes: there are hundreds of these and responding to them individually is challenging.

For questions/comments, contact r-barnes.

 - If you approve of this diff, please use the "Accept & Ship" button :-)

Reviewed By: bottler

Differential Revision: D56886956

fbshipit-source-id: 0c515ed98b812b1c106a59e19ec90751ce32e8c0
2024-05-02 13:58:05 -07:00
Andres Suarez
47d5dc8824 Apply clang-format 18
Summary: Previously this code conformed from clang-format 12.

Reviewed By: igorsugak

Differential Revision: D56065247

fbshipit-source-id: f5a985dd8f8b84f2f9e1818b3719b43c5a1b05b3
2024-04-14 11:28:32 -07:00
generatedunixname89002005307016
fe0b1bae49 upgrade pyre version in fbcode/vision - batch 2
Differential Revision: D55650177

fbshipit-source-id: d5faa4d805bb40fe3dea70b0601e7a1382b09f3a
2024-04-02 18:11:50 -07:00
Ruishen Lyu
ccf22911d4 Optimize list_to_packed to avoid for loop (#1737)
Summary:
For larger N and Mi value (e.g. N=154, Mi=238) I notice list_to_packed() has become a bottleneck for my application. By removing the for loop and running on GPU, i see a 10-20 x speedup.

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1737

Reviewed By: MichaelRamamonjisoa

Differential Revision: D54187993

Pulled By: bottler

fbshipit-source-id: 16399a24cb63b48c30460c7d960abef603b115d0
2024-04-02 07:50:25 -07:00
Ashim Dahal
128be02fc0 feat: adjusted sample_nums (#1768)
Summary:
adjusted sample_nums to match the number of columns in the image grid. It originally produced image grid with 5 axes but only 3 images and after this fix, the block would work as intended.

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1768

Reviewed By: MichaelRamamonjisoa

Differential Revision: D55632872

Pulled By: bottler

fbshipit-source-id: 44d633a8068076889e49d49b8a7910dba0db37a7
2024-04-02 06:02:48 -07:00
Roeia Kishk
31e3488a51 Changed tutorials' pip searching
Summary:
### Generalise tutorials' pip searching:
## Required Information:
This diff contains changes to several PyTorch3D tutorials.

**Purpose of this diff:**
Replace the current installation code with a more streamlined approach that tries to install the wheel first and falls back to installing from source if the wheel is not found.

**Why this diff is required:**
This diff makes it easier to cope with new PyTorch releases and reduce the need for manual intervention, as the current process involves checking the version of PyTorch in Colab and building a new wheel if it doesn't match the expected version, which generates additional work each time there is a a new PyTorch version in Colab.

**Changes:**
Before:
```
    if torch.__version__.startswith("2.1.") and sys.platform.startswith("linux"):
        # We try to install PyTorch3D via a released wheel.
        pyt_version_str=torch.__version__.split("+")[0].replace(".", "")
        version_str="".join([
            f"py3{sys.version_info.minor}_cu",
            torch.version.cuda.replace(".",""),
            f"_pyt{pyt_version_str}"
        ])
        !pip install fvcore iopath
        !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html
    else:
        # We try to install PyTorch3D from source.
        !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'
```
After:
```
    pyt_version_str=torch.__version__.split("+")[0].replace(".", "")
    version_str="".join([
        f"py3{sys.version_info.minor}_cu",
        torch.version.cuda.replace(".",""),
        f"_pyt{pyt_version_str}"
    ])
    !pip install fvcore iopath
    if sys.platform.startswith("linux"):
      # We try to install PyTorch3D via a released wheel.
      !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html
      pip_list = !pip freeze
      need_pytorch3d = not any(i.startswith("pytorch3d==") for  i in pip_list)

    if need_pytorch3d:
        # We try to install PyTorch3D from source.
        !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'
```

Reviewed By: bottler

Differential Revision: D55431832

fbshipit-source-id: a8de9162470698320241ae8401427dcb1ce17c37
2024-03-28 11:24:43 -07:00
generatedunixname89002005307016
b215776f2d upgrade pyre version in fbcode/vision - batch 2
Differential Revision: D55395614

fbshipit-source-id: 71677892b5d6f219f6df25b4efb51fb0f6b1441b
2024-03-26 22:02:22 -07:00
Cijo Jose
38cf0dc1c5 TexturesUV multiple maps
Summary: Implements the  the TexturesUV with multiple map ids.

Reviewed By: bottler

Differential Revision: D53944063

fbshipit-source-id: 06c25eb6d69f72db0484f16566dd2ca32a560b82
2024-03-12 06:59:31 -07:00
Jaap Suter
7566530669 CUDA marching_cubes fix
Summary:
Fix an inclusive vs exclusive scan mix-up that was accidentally introduced when removing the Thrust dependency (`Thrust::exclusive_scan`) and reimplementing it using `at::cumsum` (which does an inclusive scan).

This fixes two Github reported issues:

 * https://github.com/facebookresearch/pytorch3d/issues/1731
 * https://github.com/facebookresearch/pytorch3d/issues/1751

Reviewed By: bottler

Differential Revision: D54605545

fbshipit-source-id: da9e92f3f8a9a35f7b7191428d0b9a9ca03e0d4d
2024-03-07 15:38:24 -08:00
Conner Nilsen
a27755db41 Pyre Configurationless migration for] [batch:85/112] [shard:6/N]
Reviewed By: inseokhwang

Differential Revision: D54438157

fbshipit-source-id: a6acfe146ed29fff82123b5e458906d4b4cee6a2
2024-03-04 18:30:37 -08:00
Amethyst Reese
3da7703c5a apply Black 2024 style in fbcode (4/16)
Summary:
Formats the covered files with pyfmt.

paintitblack

Reviewed By: aleivag

Differential Revision: D54447727

fbshipit-source-id: 8844b1caa08de94d04ac4df3c768dbf8c865fd2f
2024-03-02 17:31:19 -08:00
Jeremy Reizenstein
f34104cf6e version 0.7.6
Summary: New version

Reviewed By: cijose

Differential Revision: D53852987

fbshipit-source-id: 962ab9f61153883df9da0601356bd6b108dc5df7
2024-02-19 03:28:54 -08:00
Jeremy Reizenstein
f247c86dc0 Update tutorials for 0.7.6
Summary:
version number changed with
`sed -i "s/2.1\./2.2./" *b`

Reviewed By: cijose

Differential Revision: D53852986

fbshipit-source-id: 1662c8e6d671321887a3263bc3880d5c33d1f866
2024-02-19 03:28:54 -08:00
Cijo Jose
ae9d8787ce Support color in cubify
Summary: The diff support colors in cubify for align = "center"

Reviewed By: bottler

Differential Revision: D53777011

fbshipit-source-id: ccb2bd1e3d89be3d1ac943eff08f40e50b0540d9
2024-02-16 08:19:12 -08:00
Jeremy Reizenstein
8772fe0de8 Make OpenGL optional in tests
Summary: Add an option to run tests without the OpenGL Renderer.

Reviewed By: patricklabatut

Differential Revision: D53573400

fbshipit-source-id: 54a14e7b2f156d24e0c561fdb279f4a9af01b793
2024-02-13 07:43:42 -08:00
Ada Martin
c292c71c1a c++ marching cubes fix
Summary:
Fixes https://github.com/facebookresearch/pytorch3d/issues/1641. The bug was caused by the mistaken downcasting of an int64_t into int, causing issues only on inputs large enough to have hashes that escaped the bounds of an int32.

Also added a test case for this issue.

Reviewed By: bottler

Differential Revision: D53505370

fbshipit-source-id: 0fdd0efc6d259cc3b0263e7ff3a4ab2c648ec521
2024-02-08 11:13:15 -08:00
Jeremy Reizenstein
d0d9cae9cd builds for PyTorch 2.1.1 2.1.2 2.2.0
Summary: Build for new pytorch versions

Reviewed By: shapovalov

Differential Revision: D53266104

fbshipit-source-id: f7aaacaf39cab3839b24f45361c36f087d0ea7c9
2024-02-07 11:56:52 -08:00
generatedunixname89002005287564
1f92c4e9d2 vision/fair
Reviewed By: zsol

Differential Revision: D53258682

fbshipit-source-id: 3f006b5f31a2b1ffdc6323d3a3b08ac46c3162ce
2024-01-31 07:43:49 -08:00
generatedunixname89002005307016
9b981f2c7e suppress errors in vision/fair/pytorch3d
Differential Revision: D53152021

fbshipit-source-id: 78be99b00abe4d992db844ff5877a89d42d468af
2024-01-26 19:10:37 -08:00
generatedunixname89002005307016
85eccbbf77 suppress errors in vision/fair/pytorch3d
Differential Revision: D53111480

fbshipit-source-id: 0f506bf29cf908e40b058ae72f51e828cd597825
2024-01-25 21:13:30 -08:00
generatedunixname89002005307016
b80ab0caf0 upgrade pyre version in fbcode/vision - batch 1
Differential Revision: D53059851

fbshipit-source-id: f5d0951186c858f90ddf550323a163e4b6d42b68
2024-01-24 23:56:06 -08:00
Dimitris Prountzos
1e817914b3 Fix compiler warning in knn.ku
Summary: This change updates the type of p2_idx from size_t to int64_t to address compiler warnings related to signed/unsigned comparison.

Reviewed By: bottler

Differential Revision: D52879393

fbshipit-source-id: de5484d78a907fccdaae3ce036b5e4a1a0a4de70
2024-01-18 12:27:16 -08:00
Ido Zachevsky
799c1cd21b Allow get_rgbd_point_cloud to take any #channels
Summary: Fixed `get_rgbd_point_cloud` to take any number of image input channels.

Reviewed By: bottler

Differential Revision: D52796276

fbshipit-source-id: 3ddc0d1e337a6cc53fc86c40a6ddb136f036f9bc
2024-01-16 03:38:26 -08:00
Abdelrahman Selim
292acc71a3 Update so3 operations for numerical stability
Summary: Replace implementations of `so3_exp_map` and `so3_log_map` in so3.py with existing more-stable implementations.

Reviewed By: bottler

Differential Revision: D52513319

fbshipit-source-id: fbfc039643fef284d8baa11bab61651964077afe
2024-01-04 02:26:56 -08:00
Jeremy Reizenstein
3621a36494 mac build fix
Summary: Fix for https://github.com/facebookresearch/pytorch3d/issues/1708

Reviewed By: patricklabatut

Differential Revision: D52480756

fbshipit-source-id: 530c0f9413970fba042eec354e28318c96e35f42
2024-01-03 07:46:54 -08:00
Abdelrahman Selim
3087ab7f62 Standardize matrix_to_quaternion output
Summary:
An OSS user has pointed out in https://github.com/facebookresearch/pytorch3d/issues/1703 that the output of matrix_to_quaternion (in that file) can be non standardized.

This diff solves the issue by adding a line of standardize at the end of the function

Reviewed By: bottler

Differential Revision: D52368721

fbshipit-source-id: c8d0426307fcdb7fd165e032572382d5ae360cde
2023-12-21 13:43:29 -08:00
Tony Tan
e46ab49a34 Submeshing TexturesAtlas for PyTorch3D 3D Rendering
Summary: Implement submeshing for TexturesAtlas and add associated test

Reviewed By: bottler

Differential Revision: D52334053

fbshipit-source-id: d54080e9af1f0c01551702736e858e3bd439ac58
2023-12-21 11:08:01 -08:00
Hassan Lotfi
8a27590c5f Submeshing TexturesUV
Summary: Implement `submeshes` for TexturesUV. Fix what Meshes.submeshes passes to the texture's submeshes function to make this possible.

Reviewed By: bottler

Differential Revision: D52192060

fbshipit-source-id: 526734962e3376aaf75654200164cdcebfff6997
2023-12-19 06:48:06 -08:00
Eric Young
06cdc313a7 PyTorch3D - Avoid flip in TexturesAtlas
Summary: Performance improvement: Use torch.lerp to map uv coordinates to the range needed for grid_sample (i.e. map [0, 1] to [-1, 1] and invert the y-axis)

Reviewed By: bottler

Differential Revision: D51961728

fbshipit-source-id: db19a5e3f482e9af7b96b20f88a1e5d0076dac43
2023-12-11 12:49:17 -08:00
Roman Shapovalov
94da8841af Align_corners switch in Volumes
Summary:
Porting this commit by davnov134 .
93a3a62800 (diff-a8e107ebe039de52ca112ac6ddfba6ebccd53b4f53030b986e13f019fe57a378)

Capability to interpret world/local coordinates with various align_corners semantics.

Reviewed By: bottler

Differential Revision: D51855420

fbshipit-source-id: 834cd220c25d7f0143d8a55ba880da5977099dd6
2023-12-07 03:07:41 -08:00
generatedunixname89002005307016
fbc6725f03 upgrade pyre version in fbcode/vision - batch 2
Differential Revision: D51902460

fbshipit-source-id: 3ffc5d7d2da5c5d4e971ee8275bd999c709e0b12
2023-12-06 20:53:53 -08:00
Jeremy Reizenstein
6b8766080d Use cuda's make_float3 in pulsar
Summary: Fixes github.com/facebookresearch/pytorch3d/issues/1680

Reviewed By: MichaelRamamonjisoa

Differential Revision: D51587889

fbshipit-source-id: e68ae32d7041fb9ea3e981cf2bde47f947a41ca2
2023-12-05 03:15:02 -08:00
sewon.jeon
c373a84400 Use updated naming to remove warning (#1687)
Summary:
diag_suppress is  deprecated from cuda

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1687

Reviewed By: MichaelRamamonjisoa

Differential Revision: D51495875

Pulled By: bottler

fbshipit-source-id: 6543a15e666238365719117bfcf5f7dac532aec1
2023-12-05 03:15:02 -08:00
sewon.jeon
7606854ff7 Fix windows build (#1689)
Summary:
Change the data type usage in the code to ensure cross-platform compatibility
long -> int64_t

<img width="628" alt="image" src="https://github.com/facebookresearch/pytorch3d/assets/6214316/40041f7f-3c09-4571-b9ff-676c625802e9">

Tested under
Win 11 and Ubuntu 22.04
with
CUDA 12.1.1 torch 2.1.1

Related issues & PR

https://github.com/facebookresearch/pytorch3d/pull/9

https://github.com/facebookresearch/pytorch3d/issues/1679

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1689

Reviewed By: MichaelRamamonjisoa

Differential Revision: D51521562

Pulled By: bottler

fbshipit-source-id: d8ea81e223c642e0e9fb283f5d7efc9d6ac00d93
2023-12-05 03:14:06 -08:00
Jeremy Reizenstein
83bacda8fb lint
Summary: Fix recent flake complaints

Reviewed By: MichaelRamamonjisoa

Differential Revision: D51811912

fbshipit-source-id: 65183f5bc7058da910e4d5a63b2250ce8637f1cc
2023-12-04 13:43:34 -08:00
generatedunixname89002005307016
f74fc450e8 suppress errors in vision/fair/pytorch3d
Differential Revision: D51645956

fbshipit-source-id: 1ae7279efa0a27bb9bc5255527bafebb84fdafd0
2023-11-28 19:10:06 -08:00
Dan Johnson
3b4f8a4980 Adding reference and context to PointsRenderer
Summary: User confusion (https://github.com/facebookresearch/pytorch3d/issues/1579) about how zbuf is used for alpha compositing. Added small description and reference to paper to help give some context.

Reviewed By: bottler

Differential Revision: D51374933

fbshipit-source-id: 8c489a5b5d0a81f0d936c1348b9ade6787c39c9a
2023-11-16 08:58:08 -08:00
Aleksandrs Ecins
79b46734cb Fix lint in test_render_points
Summary: Fixes lint in test_render_points in the PyTorch3D library.

Differential Revision: D51289841

fbshipit-source-id: 1eae621eb8e87b0fe5979f35acd878944f574a6a
2023-11-14 11:07:28 -08:00
YangHai
55638f3bae Support reading uv and uv map for ply format if texture_uv exists in ply file (#1100)
Summary:
When the ply format looks as follows:
  ```
comment TextureFile ***.png
element vertex 892
property double x
property double y
property double z
property double nx
property double ny
property double nz
property double texture_u
property double texture_v
```
`MeshPlyFormat` class will read uv from the ply file and read the uv map as commented as TextureFile.

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1100

Reviewed By: MichaelRamamonjisoa

Differential Revision: D50885176

Pulled By: bottler

fbshipit-source-id: be75b1ec9a17a1ed87dbcf846a9072ea967aec37
2023-11-14 07:44:14 -08:00
Jeremy Reizenstein
f4f2209271 Fix for mask_points=False
Summary: Remove unused argument `mask_points` from `get_rgbd_point_cloud` and fix `get_implicitron_sequence_pointcloud`, which assumed it was used.

Reviewed By: MichaelRamamonjisoa

Differential Revision: D50885848

fbshipit-source-id: c0b834764ad5ef560107bd8eab04952d000489b8
2023-11-14 07:42:18 -08:00
Jeremy Reizenstein
f613682551 marching_cubes type fix
Summary: fixes https://github.com/facebookresearch/pytorch3d/issues/1679

Reviewed By: MichaelRamamonjisoa

Differential Revision: D50949933

fbshipit-source-id: 5c467de8bf84dd2a3d61748b3846678582d24ea3
2023-11-14 07:38:54 -08:00
Jeremy Reizenstein
2f11ddc5ee version 0.7.5
Summary: update

Reviewed By: MichaelRamamonjisoa

Differential Revision: D50806966

fbshipit-source-id: 95fd341c9e5e4e07b689eb71b3a729baff3b8192
2023-10-31 09:27:49 -07:00
Jeremy Reizenstein
650cc09d22 update notebooks for 0.7.5
Summary:
```
sed -i 's/startswith((\"1.13.\", \"2.0.\"))/startswith\(\"2.1.\"\)/' *b
```

Reviewed By: shapovalov

Differential Revision: D50806967

fbshipit-source-id: df19462564edb1f840753efeae96b516c7a9f764
2023-10-31 09:27:49 -07:00
Jeremy Reizenstein
8c15afe71d fix warning from cross
Summary: Don't call tensor.cross() without dim, to avoid new warning.

Reviewed By: MichaelRamamonjisoa

Differential Revision: D49879590

fbshipit-source-id: e9ba83923b6dc3bcface6782b8b26729ab5b0a4c
2023-10-30 11:50:23 -07:00
Jeremy Reizenstein
6b437e21a6 CI fixes (#1676)
Summary:
Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1676

Remove CUDA 10.2 build, remove sm35 from cuda12.

Reviewed By: MichaelRamamonjisoa

Differential Revision: D50790929

fbshipit-source-id: 2b8cd34493b633a97b4066e0fd61aff077f7ce0c
2023-10-30 09:50:04 -07:00
Jeremy Reizenstein
03f17ca1ea missing cudaGetLastError
Summary: Investigating a reported problem.

Reviewed By: MichaelRamamonjisoa

Differential Revision: D50791296

fbshipit-source-id: 8dc162b87d02debf05d16c2b4816fcd57234d7e0
2023-10-30 09:35:08 -07:00
Aniket Patil
a8c70161a1 Fixed typo in cameras.py (#1656)
Summary:
coodinates -> coordinates

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1656

Reviewed By: MichaelRamamonjisoa

Differential Revision: D50325515

Pulled By: bottler

fbshipit-source-id: 406d2e286ead4fa5e9080092b4918a748495ee23
2023-10-17 06:07:02 -07:00
Jeremy Reizenstein
28f914bf3b pytorch 2.1, drop mac builds
Summary: Build updates for PyTorch 2.1

Reviewed By: MichaelRamamonjisoa

Differential Revision: D50345762

fbshipit-source-id: 89bf4edf1c21566aa86a3abca9b4df7c4d1d17a2
2023-10-17 06:04:06 -07:00
generatedunixname89002005307016
eaf0709d6a suppress errors in vision/fair/pytorch3d
Differential Revision: D49531589

fbshipit-source-id: 61c28ae33d2e5f75fd1695f35dc99931a3aaf7d3
2023-09-22 03:33:05 -07:00
Tristan Rice
b7f4ba097c VolumeSampler: expose padding_mode for inside out rendering (#1638)
Summary:
This exposes a setting on VolumeSampler so you can change the padding_mode. This is very useful when using cameras inside a volume that doesn't cover the entire world. By setting the value to `border` you can get much better behavior than `zeros` which causes edge effects for things like the sky. Border emulates infinitely tall buildings instead.

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1638

Test Plan:
Tested with torchdrive

Example before:
![image](https://github.com/facebookresearch/pytorch3d/assets/909104/e99ffb7c-c4ba-40f8-b15c-ad5d1b53f0df)

Example after:
![image](https://github.com/facebookresearch/pytorch3d/assets/909104/f8d9821b-93d5-44b5-b9d4-c1670711ddce)

Reviewed By: MichaelRamamonjisoa

Differential Revision: D49384383

Pulled By: bottler

fbshipit-source-id: 202b526e07320a18944c39a148beec94c0f5d68c
2023-09-20 08:00:02 -07:00
Jeremy Reizenstein
6f2212da46 use less thrust, maybe help Windows
Summary: I think we include more thrust than needed, and maybe removing it will help things like  https://github.com/facebookresearch/pytorch3d/issues/1610 with DebugSyncStream errors on Windows.

Reviewed By: shapovalov

Differential Revision: D48949888

fbshipit-source-id: add889c0acf730a039dc9ffd6bbcc24ded20ef27
2023-09-05 04:40:24 -07:00
Richard Barnes
a3d99cab6b Del (object) from 200 inc vision/fair/mae_st/util/meters.py
Summary: Python3 makes the use of `(object)` in class inheritance unnecessary. Let's modernize our code by eliminating this.

Reviewed By: itamaro

Differential Revision: D48673863

fbshipit-source-id: 032d6028371f0350252e6b731c74f0f5933c83cd
2023-08-26 13:55:56 -07:00
Haritha Jayasinghe
d84f274a08 add None option for chamfer distance point reduction (#1605)
Summary:
The `chamfer_distance` function currently allows `"sum"` or `"mean"` reduction, but does not support returning unreduced (per-point) loss terms. Unreduced losses could be useful if the user wishes to inspect individual losses, or perform additional modifications to loss terms before reduction. One example would be implementing a robust kernel over the loss.

This PR adds a `None` option to the `point_reduction` parameter, similar to `batch_reduction`. In case of bi-directional chamfer loss, both the forward and backward distances are returned (a tuple of Tensors of shape `[D, N]` is returned). If normals are provided, similar logic applies to normals as well.

This PR addresses issue https://github.com/facebookresearch/pytorch3d/issues/622.

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1605

Reviewed By: jcjohnson

Differential Revision: D48313857

Pulled By: bottler

fbshipit-source-id: 35c824827a143649b04166c4817449e1341b7fd9
2023-08-15 10:36:06 -07:00
generatedunixname89002005307016
099fc069fb suppress errors in vision/fair/pytorch3d
Differential Revision: D47643182

fbshipit-source-id: 598de1526e0c717f2f7038c3f4873ac119c65bba
2023-07-20 12:37:46 -07:00
Jeremy Reizenstein
57f6e79280 attempt to fix readthedocs
Summary:
Something's wrong with recommonmark/CommonMark/six, let's see if this fixes it.

https://readthedocs.org/projects/pytorch3d/builds/21292632/

```
  File "/home/docs/checkouts/readthedocs.org/user_builds/pytorch3d/envs/latest/lib/python3.11/site-packages/sphinx/config.py", line 368, in eval_config_file
    execfile_(filename, namespace)
  File "/home/docs/checkouts/readthedocs.org/user_builds/pytorch3d/envs/latest/lib/python3.11/site-packages/sphinx/util/pycompat.py", line 150, in execfile_
    exec_(code, _globals)
  File "/home/docs/checkouts/readthedocs.org/user_builds/pytorch3d/checkouts/latest/docs/conf.py", line 25, in <module>
    from recommonmark.parser import CommonMarkParser
  File "/home/docs/checkouts/readthedocs.org/user_builds/pytorch3d/envs/latest/lib/python3.11/site-packages/recommonmark/parser.py", line 6, in <module>
    from CommonMark import DocParser, HTMLRenderer
  File "/home/docs/checkouts/readthedocs.org/user_builds/pytorch3d/envs/latest/lib/python3.11/site-packages/CommonMark/__init__.py", line 3, in <module>
    from CommonMark.CommonMark import HTMLRenderer
  File "/home/docs/checkouts/readthedocs.org/user_builds/pytorch3d/envs/latest/lib/python3.11/site-packages/CommonMark/CommonMark.py", line 18, in <module>
    HTMLunescape = html.parser.HTMLParser().unescape
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'HTMLParser' object has no attribute 'unescape'
```

Reviewed By: shapovalov

Differential Revision: D47471545

fbshipit-source-id: 48e121e20da535b3cc46b6bd2393d28869067b8b
2023-07-14 09:49:09 -07:00
Jeremy Reizenstein
2883a07bfe update wheel scripts
Summary: New versions of cuda etc. I haven't committed recent changes to this for a while

Reviewed By: shapovalov

Differential Revision: D47396136

fbshipit-source-id: d6c27f5056fa8f4a74a628fa1d831159000acf55
2023-07-14 09:09:46 -07:00
Jeremy Reizenstein
6462aa60ea switch to readthedocs.yaml
Summary: This is needed from september 2023. As a side effect, implicitron docs should build better because typing.get_args exists etc.

Reviewed By: shapovalov

Differential Revision: D47363855

fbshipit-source-id: a954c5b81b1e5a4435fca146a11aea0d2ca96f45
2023-07-13 06:56:19 -07:00
Roman Shapovalov
d851bc3173 Read depth maps from OpenXR files
Summary:
Blender uses OpenEXR to dump depth maps, so we have to support it.
OpenCV requires to explicitly accepth the vulnerabilities by setting the env var before exporting.
We can set it but I think it should be user’s responsibility.
OpenCV error reporting is adequate, so I don’t handle the error on our side.

Reviewed By: bottler

Differential Revision: D47403884

fbshipit-source-id: 2fcadd1df9d0efa0aea563bcfb2e3180b3c4d1d7
2023-07-13 04:50:03 -07:00
Roman Shapovalov
8164ac4081 Fix: tensor vs array type correctness
Summary:
For fg-masking depth, we assumed np.array but passed a Tensor; for defining the default depth_mask, vice versa.

Note that we change the intended behaviour for the latter, assuming that 0s are areas with empty depth. When loading depth masks, we replace NaNs with zeros, so it is sensible. It is not a BC change as that branch would crash if executed. Since there was no reports, I assume no one cared.

Reviewed By: bottler

Differential Revision: D47403588

fbshipit-source-id: 1094104176d7d767a5657b5bbc9f5a0cc9da0ede
2023-07-13 04:50:03 -07:00
Emilien Garreau
9446d91fae Avoid to keep in memory lengths and bins for ImplicitronRayBundle
Summary:
Convert ImplicitronRayBundle to a "classic" class instead of a dataclass. This change is introduced as a way to preserve the ImplicitronRayBundle interface while allowing two outcomes:
- init lengths arguments is now a Optional[torch.Tensor] instead of torch.Tensor
- lengths is now a property which returns a `torch.Tensor`. The lengths property will either recompute lengths from bins or return the stored _lengths. `_lenghts` is None if bins is set. It saves us a bit of memory.

Reviewed By: shapovalov

Differential Revision: D46686094

fbshipit-source-id: 3c75c0947216476ebff542b6f552d311024a679b
2023-07-06 02:41:15 -07:00
Emilien Garreau
3d011a9198 Adapt RayPointRefiner and RayMarcher to support bins.
Summary:
## Context

Bins are used in mipnerf to allow to manipulate easily intervals. For example, by doing the following, `bins[..., :-1]` you will obtain all the left coordinates of your intervals, while doing `bins[..., 1:]` is equals to the right coordinates of your intervals.

We introduce here the support of bins like in MipNerf implementation.

## RayPointRefiner

Small changes have been made to modify RayPointRefiner.
- If bins is None

```
mids = torch.lerp(ray_bundle.lengths[..., 1:], ray_bundle.lengths[…, :-1], 0.5)
z_samples = sample_pdf(
		mids, # [..., npt]
		weights[..., 1:-1], # [..., npt - 1]
               ….
            )
```

- If bins is not None
In the MipNerf implementation the sampling is done on all the bins. It allows us to use the full weights tensor without slashing it.

```
z_samples = sample_pdf(
		ray_bundle.bins, # [..., npt + 1]
		weights, # [..., npt]
               ...
            )
```

## RayMarcher

Add a ray_deltas optional argument. If None, keep the same deltas computation from ray_lengths.

Reviewed By: shapovalov

Differential Revision: D46389092

fbshipit-source-id: d4f1963310065bd31c1c7fac1adfe11cbeaba606
2023-07-06 02:41:15 -07:00
Emilien Garreau
5910d81b7b Add blurpool following MIPNerf paper.
Summary:
Add blurpool has defined in [MIP-NeRF](https://arxiv.org/abs/2103.13415).
It has been added has an option for RayPointRefiner.

Reviewed By: shapovalov

Differential Revision: D46356189

fbshipit-source-id: ad841bad86d2b591a68e1cb885d4f781cf26c111
2023-07-06 02:20:53 -07:00
Emilien Garreau
ccf860f1db Add integrated position encoding based on MIPNerf implementation.
Summary: Add a new implicit module Integral Position Encoding based on [MIP-NeRF](https://arxiv.org/abs/2103.13415).

Reviewed By: shapovalov

Differential Revision: D46352730

fbshipit-source-id: c6a56134c975d80052b3a11f5e92fd7d95cbff1e
2023-07-06 02:20:53 -07:00
Emilien Garreau
29b8ebd802 Add utils to approximate the conical frustums as multivariate gaussians.
Summary:
Introduce methods to approximate the radii of conical frustums along rays as described in [MipNerf](https://arxiv.org/abs/2103.13415):

- Two new attributes are added to ImplicitronRayBundle: bins and radii. Bins is of size n_pts_per_ray + 1. It allows us to manipulate easily and n_pts_per_ray intervals. For example we need the intervals coordinates in the radii computation for \(t_{\mu}, t_{\delta}\). Radii are used to store the radii of the conical frustums.

- Add 3 new methods to compute the radii:
   - approximate_conical_frustum_as_gaussians: It computes the mean along the ray direction, the variance of the
      conical frustum  with respect to t and variance of the conical frustum with respect to its radius. This
      implementation follows the stable computation defined in the paper.
   - compute_3d_diagonal_covariance_gaussian: Will leverage the two previously computed variances to find the
     diagonal covariance of the Gaussian.
   - conical_frustum_to_gaussian: Mix everything together to compute the means and the diagonal covariances along
     the ray of the Gaussians.

- In AbstractMaskRaySampler, introduces the attribute `cast_ray_bundle_as_cone`. If False it won't change the previous behaviour of the RaySampler. However if True, the samplers will sample `n_pts_per_ray +1` instead of `n_pts_per_ray`. This points are then used to set the bins attribute of ImplicitronRayBundle. The support of HeterogeneousRayBundle has not been added since the current code does not allow it. A safeguard has been added to avoid a silent bug in the future.

Reviewed By: shapovalov

Differential Revision: D45269190

fbshipit-source-id: bf22fad12d71d55392f054e3f680013aa0d59b78
2023-07-06 01:55:41 -07:00
Emilien Garreau
4e7715ce66 Remove unused pyre-ignore or pyre-fixme
Reviewed By: bottler

Differential Revision: D47223471

fbshipit-source-id: 8bdabf2a69dd7aec7202141122a9c69220ba7ef1
2023-07-05 02:58:47 -07:00
Jeremy Reizenstein
f68371d398 lints
Summary: simple

Reviewed By: shapovalov

Differential Revision: D46438865

fbshipit-source-id: 0f41cb3ddd7e7aca4513267d33299531f7e8d373
2023-06-16 06:48:04 -07:00
Jeremy Reizenstein
dc2c7e489f docs build remove mock after D45600232
Summary: We now use unittest.mock

Reviewed By: shapovalov

Differential Revision: D45868799

fbshipit-source-id: cd1042dc2c49c82c7b9e024f761c496049a31beb
2023-06-16 04:50:30 -07:00
Jeremy Reizenstein
42e7de418c fix test_build internal
Summary: Make test work in isolation, and when run internally make it not try the sqlalchemy files.

Reviewed By: shapovalov

Differential Revision: D46352513

fbshipit-source-id: 7417a25d7a5347d937631c9f56ae4e3242dd622e
2023-06-16 04:49:02 -07:00
Richard Higgins
88429853b9 1-line tutorial notebook plotting change to fix blank figure problem (#1549)
Summary:
Hi,

Not sure this is the best fix. But while running this notebook, I only ever saw a blank canvas when trying to visualize the dolphin. It might be that I have a broken dependency, like plotly. I also don't know what the visualization is "supposed" to look like.

But incase other people have this issue, this one line change solved the whole problem for me. Now I have a happy, rotatable dolphin.

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1549

Reviewed By: shapovalov

Differential Revision: D46350930

Pulled By: bottler

fbshipit-source-id: e19aa71eb05a93e2955262a2c90d1f0d09576228
2023-06-16 04:35:15 -07:00
Jeremy Reizenstein
009a3d3b3c projects/nerf subsampling fix for newish pytorch #1441
Summary: Fix for https://github.com/facebookresearch/pytorch3d/issues/1441 where we were indexing with a tensor on the wrong device.

Reviewed By: shapovalov

Differential Revision: D46276449

fbshipit-source-id: 7750ed45ffecefa5d291fd1eadfe515310c2cf0d
2023-06-16 04:33:24 -07:00
Roman Shapovalov
cd5db076d5 Adding SQL dataset classes to ImplicitronDataSource imports
Summary: Making it easier for the clients to use these datasets.

Reviewed By: bottler

Differential Revision: D46727179

fbshipit-source-id: cf619aee4c4c0222a74b30ea590cf37f08f014cc
2023-06-14 10:51:47 -07:00
Roman Shapovalov
3d886c32d5 Fix: subset filter in DatasetBase implementation
Summary: In D42739669, I forgot to update the API of existing implementations of DatasetBase to take `subset_filter`. Looks like only one was missing.

Reviewed By: bottler

Differential Revision: D46724488

fbshipit-source-id: 13ab7a457f853278cf06955aad0cc2bab5fbcce6
2023-06-14 08:48:14 -07:00
Roman Shapovalov
5592d25f68 Fix: changed deprecated matplotlib parameter
Summary:
The parameter was renamed in MPL 3.5.0 in 2021, and the deprecated version is no longer supported.

https://matplotlib.org/stable/api/prev_api_changes/api_changes_3.5.0.html#the-first-parameter-of-axes-grid-and-axis-grid-has-been-renamed-to-visible

Reviewed By: bottler

Differential Revision: D46724242

fbshipit-source-id: 04e2ab6d63369d939ea4f0ce7d64693e0b95ee91
2023-06-14 08:48:14 -07:00
Roman Shapovalov
09a99f2e6d Support limiting num sequences per category.
Summary:
Adds stratified sampling of sequences within categories applied after category / sequence filters but before the num sequence limit.
It respects the insertion order into the sequence_annots table, i.e. takes top N sequences within each category.

Reviewed By: bottler

Differential Revision: D46724002

fbshipit-source-id: 597cb2a795c3f3bc07f838fc51b4e95a4f981ad3
2023-06-14 07:12:02 -07:00
Norman Mueller
5ffeb4d580 Single directional chamfer distance and non-absolute cosine similarity
Summary: Single directional chamfer distance and option to use non-absolute cosine similarity

Reviewed By: bottler

Differential Revision: D46593980

fbshipit-source-id: b2e591706a0cdde1c2d361614cecebb84a581433
2023-06-13 09:09:15 -07:00
generatedunixname89002005307016
573a42cd5f suppress errors in vision/fair/pytorch3d
Differential Revision: D46685078

fbshipit-source-id: daf2e75f24b68d2eab74cddca8ab9446e96951e7
2023-06-13 07:14:48 -07:00
Jeremy Reizenstein
928efdd640 fix camera plot for new matplotlib
Summary: fixes https://github.com/facebookresearch/pytorch3d/issues/1554 , needed for Matplotlib 3.6+

Reviewed By: patricklabatut

Differential Revision: D46438822

fbshipit-source-id: f3c06ad5d8e881a635edd14f96d498dca73c169f
2023-06-07 05:10:10 -07:00
Emilien Garreau
35badc0892 Fix inversion between fine and coarse implicit_functions
Summary: Fine implicit function was called before the coarse implicit function.

Reviewed By: shapovalov

Differential Revision: D46224224

fbshipit-source-id: 6b1cc00cc823d3ea7a5b42774c9ec3b73a69edb5
2023-05-26 08:33:54 -07:00
generatedunixname89002005307016
e0c3ca97ff upgrade pyre version in fbcode/vision - batch 2
Differential Revision: D46119066

fbshipit-source-id: b766118b9dcc07075d328fba73f272419dc9fc38
2023-05-23 20:34:54 -07:00
Roman Shapovalov
d2119c285f Serialising dynamic arrays in SQL; read-only SQLite connection in SQL Dataset
Summary:
1. We may need to store arrays of unknown shape in the database. It implements and tests serialisation.

2. Previously, when an inexisting metadata file was passed to SqlIndexDataset, it would try to open it and create an empty file, then crash. We now open the file in a read-only mode, so the error message is more intuitive. Note that the implementation is SQLite specific.

Reviewed By: bottler

Differential Revision: D46047857

fbshipit-source-id: 3064ae4f8122b4fc24ad3d6ab696572ebe8d0c26
2023-05-22 02:24:49 -07:00
Jeremy Reizenstein
ff80183fdb resources fix
Summary: I don't know why RE tests sometimes fail here, but maybe it's a race condition. If that's right, this should fix it.

Reviewed By: shapovalov

Differential Revision: D46020054

fbshipit-source-id: 20b746b09ad9bd77c2601ac681047ccc6cc27ed9
2023-05-19 06:41:33 -07:00
Roman Shapovalov
b0462598ac Refactor: FrameDataBuilder is more extensible.
Summary:
This is mostly a refactoring diff to reduce friction in extending the frame data.

Slight functional changes: dataset getitem now accepts (seq_name, frame_number_as_singleton_tensor) as a non-advertised feature. Otherwise this code crashes:
```
item = dataset[0]
dataset[item.sequence_name, item.frame_number]
```

Reviewed By: bottler

Differential Revision: D45780175

fbshipit-source-id: 75b8e8d3dabed954a804310abdbd8ab44a8dea29
2023-05-17 10:38:34 -07:00
Virendra Kumar Pathak
d08fe6d45a Softly deprecate the get_str=False flag.
Summary: We don't want to use print directly in stats.print() method. Instead this method will return the output string to the caller.

Reviewed By: shapovalov

Differential Revision: D45356240

fbshipit-source-id: 2cabe3cdfb9206bf09aa7b3cdd2263148a5ba145
2023-05-14 01:24:31 -07:00
Jeremy Reizenstein
297020a4b1 version 0.7.4
Summary: version number

Reviewed By: shapovalov

Differential Revision: D45704549

fbshipit-source-id: d63867f305b07c30ed9ea104f1494d23710fdbb7
2023-05-10 04:42:58 -07:00
Jeremy Reizenstein
062e6c54ae builds for PyTorch 2.0.1; drop 1.9
Summary: Drop support for PyTorch 1.9.0 and 1.9.1.

Reviewed By: shapovalov

Differential Revision: D45704329

fbshipit-source-id: c0fe3ecf6a1eb9bcd4163785c0cb4bf4f5060f50
2023-05-10 02:38:47 -07:00
Roman Shapovalov
c80180c96e Fix: FrameDataBuilder working with PathManager
Summary: In refactoring, we lost path manager here, which broke manifold storage. Fixing this.

Reviewed By: bottler

Differential Revision: D45574940

fbshipit-source-id: 579349eaa654215a09e057be57b56b46769c986a
2023-05-09 04:56:39 -07:00
Jason Fried
23cd19fbc7 typing.NamedTuple.field_types removed in favor of __annotations__
Summary:
typing.NamedTuple was simplified in 3.10
These two fields were the same in 3.8,  so this should be a no-op

#buildmore

Reviewed By: bottler

Differential Revision: D45373526

fbshipit-source-id: 2b26156f5f65b7be335133e9e705730f7254260d
2023-05-08 13:53:16 -07:00
dhb
092400f1e7 allow saving vertex normal in save_obj (#1511)
Summary:
Although we can load per-vertex normals in `load_obj`, saving per-vertex normals is not supported in `save_obj`.

This patch fixes this by allowing passing per-vertex normal data in `save_obj`:
``` python
def save_obj(
    f: PathOrStr,
    verts,
    faces,
    decimal_places: Optional[int] = None,
    path_manager: Optional[PathManager] = None,
    *,
    verts_normals: Optional[torch.Tensor] = None,
    faces_normals: Optional[torch.Tensor] = None,
    verts_uvs: Optional[torch.Tensor] = None,
    faces_uvs: Optional[torch.Tensor] = None,
    texture_map: Optional[torch.Tensor] = None,
) -> None:
    """
    Save a mesh to an .obj file.

    Args:
        f: File (str or path) to which the mesh should be written.
        verts: FloatTensor of shape (V, 3) giving vertex coordinates.
        faces: LongTensor of shape (F, 3) giving faces.
        decimal_places: Number of decimal places for saving.
        path_manager: Optional PathManager for interpreting f if
            it is a str.
        verts_normals: FloatTensor of shape (V, 3) giving the normal per vertex.
        faces_normals: LongTensor of shape (F, 3) giving the index into verts_normals
            for each vertex in the face.
        verts_uvs: FloatTensor of shape (V, 2) giving the uv coordinate per vertex.
        faces_uvs: LongTensor of shape (F, 3) giving the index into verts_uvs for
            each vertex in the face.
        texture_map: FloatTensor of shape (H, W, 3) representing the texture map
            for the mesh which will be saved as an image. The values are expected
            to be in the range [0, 1],
    """
```

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1511

Reviewed By: shapovalov

Differential Revision: D45086045

Pulled By: bottler

fbshipit-source-id: 666efb0d2c302df6cf9f2f6601d83a07856bf32f
2023-05-07 06:32:02 -07:00
generatedunixname89002005287564
ec87284c4b Replace third-party mock with unittest.mock] vision/fair
Reviewed By: bottler

Differential Revision: D45600232

fbshipit-source-id: f41b95c6fca86d241666b54755a128cd33f6dd32
2023-05-05 09:36:30 -07:00
Xiao Xuan
f5a117c74b fix: correct typo in cameras.md (#1501)
Summary:
If my understanding is right, prp_screen[1] should be 32 rather than 48.

Pull Request resolved: https://github.com/facebookresearch/pytorch3d/pull/1501

Reviewed By: shapovalov

Differential Revision: D45044406

Pulled By: bottler

fbshipit-source-id: 7dd93312db4986f4701e642ba82d94333466b921
2023-05-05 08:13:39 -07:00
Jeremy Reizenstein
b921efae3e CUB usage fix for sample_farthest_points
Summary: Fix for https://github.com/facebookresearch/pytorch3d/issues/1529

Reviewed By: shapovalov

Differential Revision: D45569211

fbshipit-source-id: 8c485f26cd409cafac53d4d982a03cde81a1d853
2023-05-05 05:59:14 -07:00
Roman Shapovalov
c8d6cd427e Fix test_data_source in OSS.
Summary: Import generic path; avoiding incorrect path patching.

Reviewed By: bottler

Differential Revision: D45573976

fbshipit-source-id: e6ff4d759deb936e3b636defa1e0851fb0127b46
2023-05-05 02:05:50 -07:00
Jeremy Reizenstein
ef5f620263 nondeterminism warnings
Summary: do like xformers.

Reviewed By: shapovalov

Differential Revision: D44541873

fbshipit-source-id: 2c23160591cd9026fcd4972998d1bc90adba1356
2023-05-04 12:50:41 -07:00
Roman Shapovalov
3e3644e534 More tests for SQL Dataset
Summary:
I forgot to include these tests to D45086611 when transferring code from pixar_replay repo.

They test the new ORM types used in SQL dataset and are SQL Alchemy 2.0 specific.

An important test for extending types is a proof of concept for generality of SQL Dataset. The idea is to extend FrameAnnotation and FrameData in parallel.

Reviewed By: bottler

Differential Revision: D45529284

fbshipit-source-id: 2a634e518f580c312602107c85fc320db43abcf5
2023-05-04 03:32:27 -07:00
Ilia Vitsnudel
178a7774d4 Adding save mesh into glb file in TexturesVertex format
Summary:
Added a suit of functions and code additions to experimental_gltf_io.py file to enable saving Meshes in TexturesVertex format into .glb file.
Also added a test to tets_io_gltf.py to check the functionality with the test described in Test Plane.

Reviewed By: bottler

Differential Revision: D44969144

fbshipit-source-id: 9ce815a1584b510442fa36cc4dbc8d41cc3786d5
2023-05-01 00:41:47 -07:00
Emilien Garreau
823ab75d27 Simplify _xy_grid computation in raysampling
Summary: Remove the need of tuple and reversed in the raysampling xy_grid computation

Reviewed By: bottler

Differential Revision: D45269342

fbshipit-source-id: d0e4c0923b9a2cca674b35e8d64862043a0eab3b
2023-04-27 03:07:37 -07:00
Roman Shapovalov
32e1992924 SQL Index Dataset
Summary:
Moving SQL dataset to PyTorch3D. It has been extensively tested in pixar_replay.

It requires SQLAlchemy 2.0, which is not supported in fbcode. So I exclude the sources and tests that depend on it from buck TARGETS.

Reviewed By: bottler

Differential Revision: D45086611

fbshipit-source-id: 0285f03e5824c0478c70ad13731525bb5ec7deef
2023-04-25 09:56:15 -07:00
Roman Shapovalov
7aeedd17a4 When bounding boxes are cached in metadata, don’t crash on load_masks=False
Summary:
We currently support caching bounding boxes in MaskAnnotation. If present, they are not re-computed from the mask. However, the masks need to be loaded for the bbox to be set.

This diff fixes that. Even if load_masks / load_blobs are unset, the bounding box can be picked up from the metadata.

Reviewed By: bottler

Differential Revision: D45144918

fbshipit-source-id: 8a2e2c115e96070b6fcdc29cbe57e1cee606ddcd
2023-04-20 07:28:45 -07:00
Roman Shapovalov
0e3138eca8 Optional ground-truth depth maps in visualiser
Summary: The code does not crash if depth map/mask are not given.

Reviewed By: bottler

Differential Revision: D45082985

fbshipit-source-id: 3610d8beb4ac897fbbe52f56a6dd012a6365b89b
2023-04-18 07:00:17 -07:00
Richard Barnes
1af6bf4768 Replace hasattr with getattr in vision/fair/pytorch3d/pytorch3d/renderer/cameras.py
Summary:
The pattern
```
X.Y if hasattr(X, "Y") else Z
```
can be replaced with
```
getattr(X, "Y", Z)
```

The [getattr](https://www.w3schools.com/python/ref_func_getattr.asp) function gives more succinct code than the [hasattr](https://www.w3schools.com/python/ref_func_hasattr.asp) function. Please use it when appropriate.

**This diff is very low risk. Green tests indicate that you can safely Accept & Ship.**

Reviewed By: bottler

Differential Revision: D44886893

fbshipit-source-id: 86ba23e837217e1ebd64bf8e27d286257894839e
2023-04-14 04:24:54 -07:00
generatedunixname89002005307016
355d6332cb upgrade pyre version in fbcode/vision - batch 2
Differential Revision: D44881859

fbshipit-source-id: 4ed410724a14d580f811c1288f51a71ce8fb0c9a
2023-04-11 17:15:12 -07:00
309 changed files with 8153 additions and 1638 deletions

View File

@@ -64,7 +64,7 @@ jobs:
CUDA_VERSION: "11.3"
resource_class: gpu.nvidia.small.multi
machine:
image: ubuntu-2004:202101-01
image: linux-cuda-11:default
steps:
- checkout
- <<: *setupcuda
@@ -116,7 +116,7 @@ jobs:
# so we aren't running the tests.
- run:
name: build
no_output_timeout: 20m
no_output_timeout: 40m
command: MAX_JOBS=15 TEST_FLAG=--no-test python3 packaging/build_conda.py
- store_artifacts:
path: /opt/conda/conda-bld/linux-64
@@ -128,7 +128,7 @@ jobs:
binary_linux_conda_cuda:
<<: *binary_common
machine:
image: ubuntu-1604-cuda-10.2:202012-01
image: linux-cuda-11:default
resource_class: gpu.nvidia.small.multi
steps:
- checkout
@@ -145,7 +145,7 @@ jobs:
docker pull $TESTRUN_DOCKER_IMAGE
- run:
name: Build and run tests
no_output_timeout: 20m
no_output_timeout: 40m
command: |
set -e
@@ -156,24 +156,6 @@ jobs:
docker run --gpus all --ipc=host -v $(pwd):/remote -w /remote ${VARS_TO_PASS} ${TESTRUN_DOCKER_IMAGE} python3 ./packaging/build_conda.py
binary_macos_wheel:
<<: *binary_common
macos:
xcode: "13.4.1"
steps:
- checkout
- run:
# Cannot easily deduplicate this as source'ing activate
# will set environment variables which we need to propagate
# to build_wheel.sh
command: |
curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
sh conda.sh -b
source $HOME/miniconda3/bin/activate
packaging/build_wheel.sh
- store_artifacts:
path: dist
workflows:
version: 2
build_and_test:
@@ -182,23 +164,8 @@ workflows:
# context: DOCKERHUB_TOKEN
{{workflows()}}
- binary_linux_conda_cuda:
name: testrun_conda_cuda_py38_cu102_pyt190
name: testrun_conda_cuda_py310_cu117_pyt201
context: DOCKERHUB_TOKEN
python_version: "3.8"
pytorch_version: '1.9.0'
cu_version: "cu102"
- binary_macos_wheel:
cu_version: cpu
name: macos_wheel_py3.8_cpu
python_version: '3.8'
pytorch_version: '1.13.0'
- binary_macos_wheel:
cu_version: cpu
name: macos_wheel_py3.9_cpu
python_version: '3.9'
pytorch_version: '1.13.0'
- binary_macos_wheel:
cu_version: cpu
name: macos_wheel_py3.10_cpu
python_version: '3.10'
pytorch_version: '1.13.0'
python_version: "3.10"
pytorch_version: '2.0.1'
cu_version: "cu117"

View File

@@ -64,7 +64,7 @@ jobs:
CUDA_VERSION: "11.3"
resource_class: gpu.nvidia.small.multi
machine:
image: ubuntu-2004:202101-01
image: linux-cuda-11:default
steps:
- checkout
- <<: *setupcuda
@@ -116,7 +116,7 @@ jobs:
# so we aren't running the tests.
- run:
name: build
no_output_timeout: 20m
no_output_timeout: 40m
command: MAX_JOBS=15 TEST_FLAG=--no-test python3 packaging/build_conda.py
- store_artifacts:
path: /opt/conda/conda-bld/linux-64
@@ -128,7 +128,7 @@ jobs:
binary_linux_conda_cuda:
<<: *binary_common
machine:
image: ubuntu-1604-cuda-10.2:202012-01
image: linux-cuda-11:default
resource_class: gpu.nvidia.small.multi
steps:
- checkout
@@ -145,7 +145,7 @@ jobs:
docker pull $TESTRUN_DOCKER_IMAGE
- run:
name: Build and run tests
no_output_timeout: 20m
no_output_timeout: 40m
command: |
set -e
@@ -156,143 +156,12 @@ jobs:
docker run --gpus all --ipc=host -v $(pwd):/remote -w /remote ${VARS_TO_PASS} ${TESTRUN_DOCKER_IMAGE} python3 ./packaging/build_conda.py
binary_macos_wheel:
<<: *binary_common
macos:
xcode: "13.4.1"
steps:
- checkout
- run:
# Cannot easily deduplicate this as source'ing activate
# will set environment variables which we need to propagate
# to build_wheel.sh
command: |
curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
sh conda.sh -b
source $HOME/miniconda3/bin/activate
packaging/build_wheel.sh
- store_artifacts:
path: dist
workflows:
version: 2
build_and_test:
jobs:
# - main:
# context: DOCKERHUB_TOKEN
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py38_cu102_pyt190
python_version: '3.8'
pytorch_version: 1.9.0
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu111
name: linux_conda_py38_cu111_pyt190
python_version: '3.8'
pytorch_version: 1.9.0
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py38_cu102_pyt191
python_version: '3.8'
pytorch_version: 1.9.1
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu111
name: linux_conda_py38_cu111_pyt191
python_version: '3.8'
pytorch_version: 1.9.1
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py38_cu102_pyt1100
python_version: '3.8'
pytorch_version: 1.10.0
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu111
name: linux_conda_py38_cu111_pyt1100
python_version: '3.8'
pytorch_version: 1.10.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
context: DOCKERHUB_TOKEN
cu_version: cu113
name: linux_conda_py38_cu113_pyt1100
python_version: '3.8'
pytorch_version: 1.10.0
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py38_cu102_pyt1101
python_version: '3.8'
pytorch_version: 1.10.1
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu111
name: linux_conda_py38_cu111_pyt1101
python_version: '3.8'
pytorch_version: 1.10.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
context: DOCKERHUB_TOKEN
cu_version: cu113
name: linux_conda_py38_cu113_pyt1101
python_version: '3.8'
pytorch_version: 1.10.1
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py38_cu102_pyt1102
python_version: '3.8'
pytorch_version: 1.10.2
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu111
name: linux_conda_py38_cu111_pyt1102
python_version: '3.8'
pytorch_version: 1.10.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
context: DOCKERHUB_TOKEN
cu_version: cu113
name: linux_conda_py38_cu113_pyt1102
python_version: '3.8'
pytorch_version: 1.10.2
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py38_cu102_pyt1110
python_version: '3.8'
pytorch_version: 1.11.0
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu111
name: linux_conda_py38_cu111_pyt1110
python_version: '3.8'
pytorch_version: 1.11.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
context: DOCKERHUB_TOKEN
cu_version: cu113
name: linux_conda_py38_cu113_pyt1110
python_version: '3.8'
pytorch_version: 1.11.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda115
context: DOCKERHUB_TOKEN
cu_version: cu115
name: linux_conda_py38_cu115_pyt1110
python_version: '3.8'
pytorch_version: 1.11.0
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py38_cu102_pyt1120
python_version: '3.8'
pytorch_version: 1.12.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
context: DOCKERHUB_TOKEN
@@ -307,12 +176,6 @@ workflows:
name: linux_conda_py38_cu116_pyt1120
python_version: '3.8'
pytorch_version: 1.12.0
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py38_cu102_pyt1121
python_version: '3.8'
pytorch_version: 1.12.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
context: DOCKERHUB_TOKEN
@@ -370,118 +233,103 @@ workflows:
python_version: '3.8'
pytorch_version: 2.0.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda117
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py39_cu102_pyt190
python_version: '3.9'
pytorch_version: 1.9.0
cu_version: cu117
name: linux_conda_py38_cu117_pyt201
python_version: '3.8'
pytorch_version: 2.0.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu111
name: linux_conda_py39_cu111_pyt190
python_version: '3.9'
pytorch_version: 1.9.0
cu_version: cu118
name: linux_conda_py38_cu118_pyt201
python_version: '3.8'
pytorch_version: 2.0.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py39_cu102_pyt191
python_version: '3.9'
pytorch_version: 1.9.1
cu_version: cu118
name: linux_conda_py38_cu118_pyt210
python_version: '3.8'
pytorch_version: 2.1.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu111
name: linux_conda_py39_cu111_pyt191
python_version: '3.9'
pytorch_version: 1.9.1
cu_version: cu121
name: linux_conda_py38_cu121_pyt210
python_version: '3.8'
pytorch_version: 2.1.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py39_cu102_pyt1100
python_version: '3.9'
pytorch_version: 1.10.0
cu_version: cu118
name: linux_conda_py38_cu118_pyt211
python_version: '3.8'
pytorch_version: 2.1.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu111
name: linux_conda_py39_cu111_pyt1100
python_version: '3.9'
pytorch_version: 1.10.0
cu_version: cu121
name: linux_conda_py38_cu121_pyt211
python_version: '3.8'
pytorch_version: 2.1.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu113
name: linux_conda_py39_cu113_pyt1100
python_version: '3.9'
pytorch_version: 1.10.0
cu_version: cu118
name: linux_conda_py38_cu118_pyt212
python_version: '3.8'
pytorch_version: 2.1.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py39_cu102_pyt1101
python_version: '3.9'
pytorch_version: 1.10.1
cu_version: cu121
name: linux_conda_py38_cu121_pyt212
python_version: '3.8'
pytorch_version: 2.1.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu111
name: linux_conda_py39_cu111_pyt1101
python_version: '3.9'
pytorch_version: 1.10.1
cu_version: cu118
name: linux_conda_py38_cu118_pyt220
python_version: '3.8'
pytorch_version: 2.2.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu113
name: linux_conda_py39_cu113_pyt1101
python_version: '3.9'
pytorch_version: 1.10.1
cu_version: cu121
name: linux_conda_py38_cu121_pyt220
python_version: '3.8'
pytorch_version: 2.2.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py39_cu102_pyt1102
python_version: '3.9'
pytorch_version: 1.10.2
cu_version: cu118
name: linux_conda_py38_cu118_pyt222
python_version: '3.8'
pytorch_version: 2.2.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu111
name: linux_conda_py39_cu111_pyt1102
python_version: '3.9'
pytorch_version: 1.10.2
cu_version: cu121
name: linux_conda_py38_cu121_pyt222
python_version: '3.8'
pytorch_version: 2.2.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu113
name: linux_conda_py39_cu113_pyt1102
python_version: '3.9'
pytorch_version: 1.10.2
cu_version: cu118
name: linux_conda_py38_cu118_pyt231
python_version: '3.8'
pytorch_version: 2.3.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py39_cu102_pyt1110
python_version: '3.9'
pytorch_version: 1.11.0
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu111
name: linux_conda_py39_cu111_pyt1110
python_version: '3.9'
pytorch_version: 1.11.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
context: DOCKERHUB_TOKEN
cu_version: cu113
name: linux_conda_py39_cu113_pyt1110
python_version: '3.9'
pytorch_version: 1.11.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda115
context: DOCKERHUB_TOKEN
cu_version: cu115
name: linux_conda_py39_cu115_pyt1110
python_version: '3.9'
pytorch_version: 1.11.0
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py39_cu102_pyt1120
python_version: '3.9'
pytorch_version: 1.12.0
cu_version: cu121
name: linux_conda_py38_cu121_pyt231
python_version: '3.8'
pytorch_version: 2.3.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
context: DOCKERHUB_TOKEN
@@ -496,12 +344,6 @@ workflows:
name: linux_conda_py39_cu116_pyt1120
python_version: '3.9'
pytorch_version: 1.12.0
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py39_cu102_pyt1121
python_version: '3.9'
pytorch_version: 1.12.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
context: DOCKERHUB_TOKEN
@@ -559,37 +401,103 @@ workflows:
python_version: '3.9'
pytorch_version: 2.0.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda117
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py310_cu102_pyt1110
python_version: '3.10'
pytorch_version: 1.11.0
cu_version: cu117
name: linux_conda_py39_cu117_pyt201
python_version: '3.9'
pytorch_version: 2.0.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu111
name: linux_conda_py310_cu111_pyt1110
python_version: '3.10'
pytorch_version: 1.11.0
cu_version: cu118
name: linux_conda_py39_cu118_pyt201
python_version: '3.9'
pytorch_version: 2.0.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu113
name: linux_conda_py310_cu113_pyt1110
python_version: '3.10'
pytorch_version: 1.11.0
cu_version: cu118
name: linux_conda_py39_cu118_pyt210
python_version: '3.9'
pytorch_version: 2.1.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda115
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu115
name: linux_conda_py310_cu115_pyt1110
python_version: '3.10'
pytorch_version: 1.11.0
cu_version: cu121
name: linux_conda_py39_cu121_pyt210
python_version: '3.9'
pytorch_version: 2.1.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py310_cu102_pyt1120
python_version: '3.10'
pytorch_version: 1.12.0
cu_version: cu118
name: linux_conda_py39_cu118_pyt211
python_version: '3.9'
pytorch_version: 2.1.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py39_cu121_pyt211
python_version: '3.9'
pytorch_version: 2.1.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py39_cu118_pyt212
python_version: '3.9'
pytorch_version: 2.1.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py39_cu121_pyt212
python_version: '3.9'
pytorch_version: 2.1.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py39_cu118_pyt220
python_version: '3.9'
pytorch_version: 2.2.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py39_cu121_pyt220
python_version: '3.9'
pytorch_version: 2.2.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py39_cu118_pyt222
python_version: '3.9'
pytorch_version: 2.2.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py39_cu121_pyt222
python_version: '3.9'
pytorch_version: 2.2.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py39_cu118_pyt231
python_version: '3.9'
pytorch_version: 2.3.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py39_cu121_pyt231
python_version: '3.9'
pytorch_version: 2.3.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
context: DOCKERHUB_TOKEN
@@ -604,12 +512,6 @@ workflows:
name: linux_conda_py310_cu116_pyt1120
python_version: '3.10'
pytorch_version: 1.12.0
- binary_linux_conda:
context: DOCKERHUB_TOKEN
cu_version: cu102
name: linux_conda_py310_cu102_pyt1121
python_version: '3.10'
pytorch_version: 1.12.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda113
context: DOCKERHUB_TOKEN
@@ -666,24 +568,233 @@ workflows:
name: linux_conda_py310_cu118_pyt200
python_version: '3.10'
pytorch_version: 2.0.0
- binary_linux_conda_cuda:
name: testrun_conda_cuda_py38_cu102_pyt190
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda117
context: DOCKERHUB_TOKEN
python_version: "3.8"
pytorch_version: '1.9.0'
cu_version: "cu102"
- binary_macos_wheel:
cu_version: cpu
name: macos_wheel_py3.8_cpu
python_version: '3.8'
pytorch_version: '1.13.0'
- binary_macos_wheel:
cu_version: cpu
name: macos_wheel_py3.9_cpu
python_version: '3.9'
pytorch_version: '1.13.0'
- binary_macos_wheel:
cu_version: cpu
name: macos_wheel_py3.10_cpu
cu_version: cu117
name: linux_conda_py310_cu117_pyt201
python_version: '3.10'
pytorch_version: '1.13.0'
pytorch_version: 2.0.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py310_cu118_pyt201
python_version: '3.10'
pytorch_version: 2.0.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py310_cu118_pyt210
python_version: '3.10'
pytorch_version: 2.1.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py310_cu121_pyt210
python_version: '3.10'
pytorch_version: 2.1.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py310_cu118_pyt211
python_version: '3.10'
pytorch_version: 2.1.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py310_cu121_pyt211
python_version: '3.10'
pytorch_version: 2.1.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py310_cu118_pyt212
python_version: '3.10'
pytorch_version: 2.1.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py310_cu121_pyt212
python_version: '3.10'
pytorch_version: 2.1.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py310_cu118_pyt220
python_version: '3.10'
pytorch_version: 2.2.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py310_cu121_pyt220
python_version: '3.10'
pytorch_version: 2.2.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py310_cu118_pyt222
python_version: '3.10'
pytorch_version: 2.2.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py310_cu121_pyt222
python_version: '3.10'
pytorch_version: 2.2.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py310_cu118_pyt231
python_version: '3.10'
pytorch_version: 2.3.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py310_cu121_pyt231
python_version: '3.10'
pytorch_version: 2.3.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py311_cu118_pyt210
python_version: '3.11'
pytorch_version: 2.1.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py311_cu121_pyt210
python_version: '3.11'
pytorch_version: 2.1.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py311_cu118_pyt211
python_version: '3.11'
pytorch_version: 2.1.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py311_cu121_pyt211
python_version: '3.11'
pytorch_version: 2.1.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py311_cu118_pyt212
python_version: '3.11'
pytorch_version: 2.1.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py311_cu121_pyt212
python_version: '3.11'
pytorch_version: 2.1.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py311_cu118_pyt220
python_version: '3.11'
pytorch_version: 2.2.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py311_cu121_pyt220
python_version: '3.11'
pytorch_version: 2.2.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py311_cu118_pyt222
python_version: '3.11'
pytorch_version: 2.2.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py311_cu121_pyt222
python_version: '3.11'
pytorch_version: 2.2.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py311_cu118_pyt231
python_version: '3.11'
pytorch_version: 2.3.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py311_cu121_pyt231
python_version: '3.11'
pytorch_version: 2.3.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py312_cu118_pyt220
python_version: '3.12'
pytorch_version: 2.2.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py312_cu121_pyt220
python_version: '3.12'
pytorch_version: 2.2.0
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py312_cu118_pyt222
python_version: '3.12'
pytorch_version: 2.2.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py312_cu121_pyt222
python_version: '3.12'
pytorch_version: 2.2.2
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda118
context: DOCKERHUB_TOKEN
cu_version: cu118
name: linux_conda_py312_cu118_pyt231
python_version: '3.12'
pytorch_version: 2.3.1
- binary_linux_conda:
conda_docker_image: pytorch/conda-builder:cuda121
context: DOCKERHUB_TOKEN
cu_version: cu121
name: linux_conda_py312_cu121_pyt231
python_version: '3.12'
pytorch_version: 2.3.1
- binary_linux_conda_cuda:
name: testrun_conda_cuda_py310_cu117_pyt201
context: DOCKERHUB_TOKEN
python_version: "3.10"
pytorch_version: '2.0.1'
cu_version: "cu117"

View File

@@ -18,25 +18,23 @@ from packaging import version
# The CUDA versions which have pytorch conda packages available for linux for each
# version of pytorch.
# Pytorch 1.4 also supports cuda 10.0 but we no longer build for cuda 10.0 at all.
CONDA_CUDA_VERSIONS = {
"1.9.0": ["cu102", "cu111"],
"1.9.1": ["cu102", "cu111"],
"1.10.0": ["cu102", "cu111", "cu113"],
"1.10.1": ["cu102", "cu111", "cu113"],
"1.10.2": ["cu102", "cu111", "cu113"],
"1.11.0": ["cu102", "cu111", "cu113", "cu115"],
"1.12.0": ["cu102", "cu113", "cu116"],
"1.12.1": ["cu102", "cu113", "cu116"],
"1.12.0": ["cu113", "cu116"],
"1.12.1": ["cu113", "cu116"],
"1.13.0": ["cu116", "cu117"],
"1.13.1": ["cu116", "cu117"],
"2.0.0": ["cu117", "cu118"],
"2.0.1": ["cu117", "cu118"],
"2.1.0": ["cu118", "cu121"],
"2.1.1": ["cu118", "cu121"],
"2.1.2": ["cu118", "cu121"],
"2.2.0": ["cu118", "cu121"],
"2.2.2": ["cu118", "cu121"],
"2.3.1": ["cu118", "cu121"],
}
def conda_docker_image_for_cuda(cuda_version):
if cuda_version in ("cu101", "cu102", "cu111"):
return None
if len(cuda_version) != 5:
raise ValueError("Unknown cuda version")
return "pytorch/conda-builder:cuda" + cuda_version[2:]
@@ -51,12 +49,24 @@ def pytorch_versions_for_python(python_version):
for i in CONDA_CUDA_VERSIONS
if version.Version(i) >= version.Version("1.11.0")
]
if python_version == "3.11":
return [
i
for i in CONDA_CUDA_VERSIONS
if version.Version(i) >= version.Version("2.1.0")
]
if python_version == "3.12":
return [
i
for i in CONDA_CUDA_VERSIONS
if version.Version(i) >= version.Version("2.2.0")
]
def workflows(prefix="", filter_branch=None, upload=False, indentation=6):
w = []
for btype in ["conda"]:
for python_version in ["3.8", "3.9", "3.10"]:
for python_version in ["3.8", "3.9", "3.10", "3.11", "3.12"]:
for pytorch_version in pytorch_versions_for_python(python_version):
for cu_version in CONDA_CUDA_VERSIONS[pytorch_version]:
w += workflow_pair(

View File

@@ -1,5 +1,8 @@
[flake8]
ignore = E203, E266, E501, W503, E221
# B028 No explicit stacklevel argument found.
# B907 'foo' is manually surrounded by quotes, consider using the `!r` conversion flag.
# B905 `zip()` without an explicit `strict=` parameter.
ignore = E203, E266, E501, W503, E221, B028, B905, B907
max-line-length = 88
max-complexity = 18
select = B,C,E,F,W,T4,B9

View File

@@ -9,7 +9,7 @@ The core library is written in PyTorch. Several components have underlying imple
- Linux or macOS or Windows
- Python 3.8, 3.9 or 3.10
- PyTorch 1.9.0, 1.9.1, 1.10.0, 1.10.1, 1.10.2, 1.11.0, 1.12.0, 1.12.1, 1.13.0 or 2.0.0.
- PyTorch 1.12.0, 1.12.1, 1.13.0, 2.0.0, 2.0.1, 2.1.0, 2.1.1, 2.1.2, 2.2.0, 2.2.1, 2.2.2, 2.3.0 or 2.3.1.
- torchvision that matches the PyTorch installation. You can install them together as explained at pytorch.org to make sure of this.
- gcc & g++ ≥ 4.9
- [fvcore](https://github.com/facebookresearch/fvcore)
@@ -77,13 +77,8 @@ Or, to install a nightly (non-official, alpha) build:
# Anaconda Cloud
conda install pytorch3d -c pytorch3d-nightly
```
### 2. Install from PyPI, on Mac only.
This works with pytorch 1.13.0 only. The build is CPU only.
```
pip install pytorch3d
```
### 3. Install wheels for Linux
### 2. Install wheels for Linux
We have prebuilt wheels with CUDA for Linux for PyTorch 1.11.0, for each of the supported CUDA versions,
for Python 3.8 and 3.9. This is for ease of use on Google Colab.
These are installed in a special way.

View File

@@ -146,6 +146,12 @@ If you are using the pulsar backend for sphere-rendering (the `PulsarPointRender
Please see below for a timeline of the codebase updates in reverse chronological order. We are sharing updates on the releases as well as research projects which are built with PyTorch3D. The changelogs for the releases are available under [`Releases`](https://github.com/facebookresearch/pytorch3d/releases), and the builds can be installed using `conda` as per the instructions in [INSTALL.md](INSTALL.md).
**[Oct 31st 2023]:** PyTorch3D [v0.7.5](https://github.com/facebookresearch/pytorch3d/releases/tag/v0.7.5) released.
**[May 10th 2023]:** PyTorch3D [v0.7.4](https://github.com/facebookresearch/pytorch3d/releases/tag/v0.7.4) released.
**[Apr 5th 2023]:** PyTorch3D [v0.7.3](https://github.com/facebookresearch/pytorch3d/releases/tag/v0.7.3) released.
**[Dec 19th 2022]:** PyTorch3D [v0.7.2](https://github.com/facebookresearch/pytorch3d/releases/tag/v0.7.2) released.
**[Oct 23rd 2022]:** PyTorch3D [v0.7.1](https://github.com/facebookresearch/pytorch3d/releases/tag/v0.7.1) released.

27
docs/.readthedocs.yaml Normal file
View File

@@ -0,0 +1,27 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the version of Python and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py
# We recommend specifying your dependencies to enable reproducible builds:
# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: docs/requirements.txt

View File

@@ -3,7 +3,7 @@
### Install dependencies
```
pip install -U recommonmark mock sphinx sphinx_rtd_theme sphinx_markdown_tables
pip install -U recommonmark sphinx sphinx_rtd_theme sphinx_markdown_tables
```
### Add symlink to the root README.md

View File

@@ -20,7 +20,8 @@
import os
import sys
import mock
import unittest.mock as mock
from recommonmark.parser import CommonMarkParser
from recommonmark.states import DummyStateMachine
from sphinx.builders.html import StandaloneHTMLBuilder

View File

@@ -85,7 +85,7 @@ cameras_ndc = PerspectiveCameras(focal_length=fcl_ndc, principal_point=prp_ndc)
# Screen space camera
image_size = ((128, 256),) # (h, w)
fcl_screen = (76.8,) # fcl_ndc * min(image_size) / 2
prp_screen = ((115.2, 48), ) # w / 2 - px_ndc * min(image_size) / 2, h / 2 - py_ndc * min(image_size) / 2
prp_screen = ((115.2, 32), ) # w / 2 - px_ndc * min(image_size) / 2, h / 2 - py_ndc * min(image_size) / 2
cameras_screen = PerspectiveCameras(focal_length=fcl_screen, principal_point=prp_screen, in_ndc=False, image_size=image_size)
```

View File

@@ -1,12 +1,11 @@
docutils>=0.14
Sphinx>=1.7
recommonmark==0.4.0
recommonmark
sphinx_rtd_theme
sphinx_markdown_tables
mock
numpy
iopath
fvcore
https://download.pytorch.org/whl/cpu/torchvision-0.8.2%2Bcpu-cp37-cp37m-linux_x86_64.whl
https://download.pytorch.org/whl/cpu/torch-1.7.1%2Bcpu-cp37-cp37m-linux_x86_64.whl
https://download.pytorch.org/whl/cpu/torchvision-0.15.2%2Bcpu-cp311-cp311-linux_x86_64.whl
https://download.pytorch.org/whl/cpu/torch-2.0.1%2Bcpu-cp311-cp311-linux_x86_64.whl
omegaconf

View File

@@ -83,25 +83,31 @@
"import os\n",
"import sys\n",
"import torch\n",
"import subprocess\n",
"need_pytorch3d=False\n",
"try:\n",
" import pytorch3d\n",
"except ModuleNotFoundError:\n",
" need_pytorch3d=True\n",
"if need_pytorch3d:\n",
" if torch.__version__.startswith((\"1.13.\", \"2.0.\")) and sys.platform.startswith(\"linux\"):\n",
" # We try to install PyTorch3D via a released wheel.\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" if sys.platform.startswith(\"linux\"):\n",
" print(\"Trying to install wheel for PyTorch3D\")\n",
" !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html\n",
" else:\n",
" # We try to install PyTorch3D from source.\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
" pip_list = !pip freeze\n",
" need_pytorch3d = not any(i.startswith(\"pytorch3d==\") for i in pip_list)\n",
" if need_pytorch3d:\n",
" print(f\"failed to find/install wheel for {version_str}\")\n",
"if need_pytorch3d:\n",
" print(\"Installing PyTorch3D from source\")\n",
" !pip install ninja\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
]
},
{

View File

@@ -70,25 +70,31 @@
"import os\n",
"import sys\n",
"import torch\n",
"import subprocess\n",
"need_pytorch3d=False\n",
"try:\n",
" import pytorch3d\n",
"except ModuleNotFoundError:\n",
" need_pytorch3d=True\n",
"if need_pytorch3d:\n",
" if torch.__version__.startswith((\"1.13.\", \"2.0.\")) and sys.platform.startswith(\"linux\"):\n",
" # We try to install PyTorch3D via a released wheel.\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" if sys.platform.startswith(\"linux\"):\n",
" print(\"Trying to install wheel for PyTorch3D\")\n",
" !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html\n",
" else:\n",
" # We try to install PyTorch3D from source.\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
" pip_list = !pip freeze\n",
" need_pytorch3d = not any(i.startswith(\"pytorch3d==\") for i in pip_list)\n",
" if need_pytorch3d:\n",
" print(f\"failed to find/install wheel for {version_str}\")\n",
"if need_pytorch3d:\n",
" print(\"Installing PyTorch3D from source\")\n",
" !pip install ninja\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
]
},
{

View File

@@ -45,25 +45,31 @@
"import os\n",
"import sys\n",
"import torch\n",
"import subprocess\n",
"need_pytorch3d=False\n",
"try:\n",
" import pytorch3d\n",
"except ModuleNotFoundError:\n",
" need_pytorch3d=True\n",
"if need_pytorch3d:\n",
" if torch.__version__.startswith((\"1.13.\", \"2.0.\")) and sys.platform.startswith(\"linux\"):\n",
" # We try to install PyTorch3D via a released wheel.\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" if sys.platform.startswith(\"linux\"):\n",
" print(\"Trying to install wheel for PyTorch3D\")\n",
" !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html\n",
" else:\n",
" # We try to install PyTorch3D from source.\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
" pip_list = !pip freeze\n",
" need_pytorch3d = not any(i.startswith(\"pytorch3d==\") for i in pip_list)\n",
" if need_pytorch3d:\n",
" print(f\"failed to find/install wheel for {version_str}\")\n",
"if need_pytorch3d:\n",
" print(\"Installing PyTorch3D from source\")\n",
" !pip install ninja\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
]
},
{
@@ -405,7 +411,7 @@
"outputs": [],
"source": [
"random_model_images = shapenet_dataset.render(\n",
" sample_nums=[3],\n",
" sample_nums=[5],\n",
" device=device,\n",
" cameras=cameras,\n",
" raster_settings=raster_settings,\n",

View File

@@ -84,25 +84,31 @@
"import os\n",
"import sys\n",
"import torch\n",
"import subprocess\n",
"need_pytorch3d=False\n",
"try:\n",
" import pytorch3d\n",
"except ModuleNotFoundError:\n",
" need_pytorch3d=True\n",
"if need_pytorch3d:\n",
" if torch.__version__.startswith((\"1.13.\", \"2.0.\")) and sys.platform.startswith(\"linux\"):\n",
" # We try to install PyTorch3D via a released wheel.\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" if sys.platform.startswith(\"linux\"):\n",
" print(\"Trying to install wheel for PyTorch3D\")\n",
" !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html\n",
" else:\n",
" # We try to install PyTorch3D from source.\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
" pip_list = !pip freeze\n",
" need_pytorch3d = not any(i.startswith(\"pytorch3d==\") for i in pip_list)\n",
" if need_pytorch3d:\n",
" print(f\"failed to find/install wheel for {version_str}\")\n",
"if need_pytorch3d:\n",
" print(\"Installing PyTorch3D from source\")\n",
" !pip install ninja\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
]
},
{
@@ -262,7 +268,7 @@
" points = sample_points_from_meshes(mesh, 5000)\n",
" x, y, z = points.clone().detach().cpu().squeeze().unbind(1) \n",
" fig = plt.figure(figsize=(5, 5))\n",
" ax = Axes3D(fig)\n",
" ax = fig.add_subplot(111, projection='3d')\n",
" ax.scatter3D(x, z, -y)\n",
" ax.set_xlabel('x')\n",
" ax.set_ylabel('z')\n",

View File

@@ -50,25 +50,31 @@
"import os\n",
"import sys\n",
"import torch\n",
"import subprocess\n",
"need_pytorch3d=False\n",
"try:\n",
" import pytorch3d\n",
"except ModuleNotFoundError:\n",
" need_pytorch3d=True\n",
"if need_pytorch3d:\n",
" if torch.__version__.startswith((\"1.13.\", \"2.0.\")) and sys.platform.startswith(\"linux\"):\n",
" # We try to install PyTorch3D via a released wheel.\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" if sys.platform.startswith(\"linux\"):\n",
" print(\"Trying to install wheel for PyTorch3D\")\n",
" !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html\n",
" else:\n",
" # We try to install PyTorch3D from source.\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
" pip_list = !pip freeze\n",
" need_pytorch3d = not any(i.startswith(\"pytorch3d==\") for i in pip_list)\n",
" if need_pytorch3d:\n",
" print(f\"failed to find/install wheel for {version_str}\")\n",
"if need_pytorch3d:\n",
" print(\"Installing PyTorch3D from source\")\n",
" !pip install ninja\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
]
},
{

View File

@@ -62,25 +62,31 @@
"import os\n",
"import sys\n",
"import torch\n",
"import subprocess\n",
"need_pytorch3d=False\n",
"try:\n",
" import pytorch3d\n",
"except ModuleNotFoundError:\n",
" need_pytorch3d=True\n",
"if need_pytorch3d:\n",
" if torch.__version__.startswith((\"1.13.\", \"2.0.\")) and sys.platform.startswith(\"linux\"):\n",
" # We try to install PyTorch3D via a released wheel.\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" if sys.platform.startswith(\"linux\"):\n",
" print(\"Trying to install wheel for PyTorch3D\")\n",
" !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html\n",
" else:\n",
" # We try to install PyTorch3D from source.\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
" pip_list = !pip freeze\n",
" need_pytorch3d = not any(i.startswith(\"pytorch3d==\") for i in pip_list)\n",
" if need_pytorch3d:\n",
" print(f\"failed to find/install wheel for {version_str}\")\n",
"if need_pytorch3d:\n",
" print(\"Installing PyTorch3D from source\")\n",
" !pip install ninja\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
]
},
{

View File

@@ -41,25 +41,31 @@
"import os\n",
"import sys\n",
"import torch\n",
"import subprocess\n",
"need_pytorch3d=False\n",
"try:\n",
" import pytorch3d\n",
"except ModuleNotFoundError:\n",
" need_pytorch3d=True\n",
"if need_pytorch3d:\n",
" if torch.__version__.startswith((\"1.13.\", \"2.0.\")) and sys.platform.startswith(\"linux\"):\n",
" # We try to install PyTorch3D via a released wheel.\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" if sys.platform.startswith(\"linux\"):\n",
" print(\"Trying to install wheel for PyTorch3D\")\n",
" !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html\n",
" else:\n",
" # We try to install PyTorch3D from source.\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
" pip_list = !pip freeze\n",
" need_pytorch3d = not any(i.startswith(\"pytorch3d==\") for i in pip_list)\n",
" if need_pytorch3d:\n",
" print(f\"failed to find/install wheel for {version_str}\")\n",
"if need_pytorch3d:\n",
" print(\"Installing PyTorch3D from source\")\n",
" !pip install ninja\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
]
},
{

View File

@@ -72,25 +72,31 @@
"import os\n",
"import sys\n",
"import torch\n",
"import subprocess\n",
"need_pytorch3d=False\n",
"try:\n",
" import pytorch3d\n",
"except ModuleNotFoundError:\n",
" need_pytorch3d=True\n",
"if need_pytorch3d:\n",
" if torch.__version__.startswith((\"1.13.\", \"2.0.\")) and sys.platform.startswith(\"linux\"):\n",
" # We try to install PyTorch3D via a released wheel.\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" if sys.platform.startswith(\"linux\"):\n",
" print(\"Trying to install wheel for PyTorch3D\")\n",
" !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html\n",
" else:\n",
" # We try to install PyTorch3D from source.\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
" pip_list = !pip freeze\n",
" need_pytorch3d = not any(i.startswith(\"pytorch3d==\") for i in pip_list)\n",
" if need_pytorch3d:\n",
" print(f\"failed to find/install wheel for {version_str}\")\n",
"if need_pytorch3d:\n",
" print(\"Installing PyTorch3D from source\")\n",
" !pip install ninja\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
]
},
{

View File

@@ -66,25 +66,31 @@
"import os\n",
"import sys\n",
"import torch\n",
"import subprocess\n",
"need_pytorch3d=False\n",
"try:\n",
" import pytorch3d\n",
"except ModuleNotFoundError:\n",
" need_pytorch3d=True\n",
"if need_pytorch3d:\n",
" if torch.__version__.startswith((\"1.13.\", \"2.0.\")) and sys.platform.startswith(\"linux\"):\n",
" # We try to install PyTorch3D via a released wheel.\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" if sys.platform.startswith(\"linux\"):\n",
" print(\"Trying to install wheel for PyTorch3D\")\n",
" !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html\n",
" else:\n",
" # We try to install PyTorch3D from source.\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
" pip_list = !pip freeze\n",
" need_pytorch3d = not any(i.startswith(\"pytorch3d==\") for i in pip_list)\n",
" if need_pytorch3d:\n",
" print(f\"failed to find/install wheel for {version_str}\")\n",
"if need_pytorch3d:\n",
" print(\"Installing PyTorch3D from source\")\n",
" !pip install ninja\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
]
},
{

View File

@@ -44,25 +44,31 @@
"import os\n",
"import sys\n",
"import torch\n",
"import subprocess\n",
"need_pytorch3d=False\n",
"try:\n",
" import pytorch3d\n",
"except ModuleNotFoundError:\n",
" need_pytorch3d=True\n",
"if need_pytorch3d:\n",
" if torch.__version__.startswith((\"1.13.\", \"2.0.\")) and sys.platform.startswith(\"linux\"):\n",
" # We try to install PyTorch3D via a released wheel.\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" if sys.platform.startswith(\"linux\"):\n",
" print(\"Trying to install wheel for PyTorch3D\")\n",
" !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html\n",
" else:\n",
" # We try to install PyTorch3D from source.\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
" pip_list = !pip freeze\n",
" need_pytorch3d = not any(i.startswith(\"pytorch3d==\") for i in pip_list)\n",
" if need_pytorch3d:\n",
" print(f\"failed to find/install wheel for {version_str}\")\n",
"if need_pytorch3d:\n",
" print(\"Installing PyTorch3D from source\")\n",
" !pip install ninja\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
]
},
{

View File

@@ -51,25 +51,31 @@
"import os\n",
"import sys\n",
"import torch\n",
"import subprocess\n",
"need_pytorch3d=False\n",
"try:\n",
" import pytorch3d\n",
"except ModuleNotFoundError:\n",
" need_pytorch3d=True\n",
"if need_pytorch3d:\n",
" if torch.__version__.startswith((\"1.13.\", \"2.0.\")) and sys.platform.startswith(\"linux\"):\n",
" # We try to install PyTorch3D via a released wheel.\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" if sys.platform.startswith(\"linux\"):\n",
" print(\"Trying to install wheel for PyTorch3D\")\n",
" !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html\n",
" else:\n",
" # We try to install PyTorch3D from source.\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
" pip_list = !pip freeze\n",
" need_pytorch3d = not any(i.startswith(\"pytorch3d==\") for i in pip_list)\n",
" if need_pytorch3d:\n",
" print(f\"failed to find/install wheel for {version_str}\")\n",
"if need_pytorch3d:\n",
" print(\"Installing PyTorch3D from source\")\n",
" !pip install ninja\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
]
},
{

View File

@@ -67,25 +67,31 @@
"import os\n",
"import sys\n",
"import torch\n",
"import subprocess\n",
"need_pytorch3d=False\n",
"try:\n",
" import pytorch3d\n",
"except ModuleNotFoundError:\n",
" need_pytorch3d=True\n",
"if need_pytorch3d:\n",
" if torch.__version__.startswith((\"1.13.\", \"2.0.\")) and sys.platform.startswith(\"linux\"):\n",
" # We try to install PyTorch3D via a released wheel.\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" pyt_version_str=torch.__version__.split(\"+\")[0].replace(\".\", \"\")\n",
" version_str=\"\".join([\n",
" f\"py3{sys.version_info.minor}_cu\",\n",
" torch.version.cuda.replace(\".\",\"\"),\n",
" f\"_pyt{pyt_version_str}\"\n",
" ])\n",
" !pip install fvcore iopath\n",
" if sys.platform.startswith(\"linux\"):\n",
" print(\"Trying to install wheel for PyTorch3D\")\n",
" !pip install --no-index --no-cache-dir pytorch3d -f https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/{version_str}/download.html\n",
" else:\n",
" # We try to install PyTorch3D from source.\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
" pip_list = !pip freeze\n",
" need_pytorch3d = not any(i.startswith(\"pytorch3d==\") for i in pip_list)\n",
" if need_pytorch3d:\n",
" print(f\"failed to find/install wheel for {version_str}\")\n",
"if need_pytorch3d:\n",
" print(\"Installing PyTorch3D from source\")\n",
" !pip install ninja\n",
" !pip install 'git+https://github.com/facebookresearch/pytorch3d.git@stable'"
]
},
{

View File

@@ -33,7 +33,7 @@ def plot_camera_scene(cameras, cameras_gt, status: str):
a string passed inside the `status` argument.
"""
fig = plt.figure()
ax = fig.gca(projection="3d")
ax = fig.add_subplot(projection="3d")
ax.clear()
ax.set_title(status)
handle_cam = plot_cameras(ax, cameras, color="#FF7D1E")

View File

@@ -50,7 +50,6 @@ def setup_cuda():
os.environ["FORCE_CUDA"] = "1"
basic_nvcc_flags = (
"-gencode=arch=compute_35,code=sm_35 "
"-gencode=arch=compute_50,code=sm_50 "
"-gencode=arch=compute_60,code=sm_60 "
"-gencode=arch=compute_70,code=sm_70 "
@@ -58,13 +57,19 @@ def setup_cuda():
"-gencode=arch=compute_50,code=compute_50"
)
if CU_VERSION == "cu102":
nvcc_flags = basic_nvcc_flags
elif CU_VERSION == "cu110":
nvcc_flags = "-gencode=arch=compute_80,code=sm_80 " + basic_nvcc_flags
nvcc_flags = "-gencode=arch=compute_35,code=sm_35 " + basic_nvcc_flags
elif CU_VERSION < ("cu118"):
nvcc_flags = (
"-gencode=arch=compute_35,code=sm_35 "
+ "-gencode=arch=compute_80,code=sm_80 "
+ "-gencode=arch=compute_86,code=sm_86 "
+ basic_nvcc_flags
)
else:
nvcc_flags = (
"-gencode=arch=compute_80,code=sm_80 "
+ "-gencode=arch=compute_86,code=sm_86 "
+ "-gencode=arch=compute_90,code=sm_90 "
+ basic_nvcc_flags
)
@@ -75,6 +80,12 @@ def setup_cuda():
def setup_conda_pytorch_constraint() -> List[str]:
pytorch_constraint = f"- pytorch=={PYTORCH_VERSION}"
os.environ["CONDA_PYTORCH_CONSTRAINT"] = pytorch_constraint
if pytorch_major_minor < (2, 2):
os.environ["CONDA_PYTORCH_MKL_CONSTRAINT"] = "- mkl!=2024.1.0"
os.environ["SETUPTOOLS_CONSTRAINT"] = "- setuptools<70"
else:
os.environ["CONDA_PYTORCH_MKL_CONSTRAINT"] = ""
os.environ["SETUPTOOLS_CONSTRAINT"] = "- setuptools"
os.environ["CONDA_PYTORCH_BUILD_CONSTRAINT"] = pytorch_constraint
os.environ["PYTORCH_VERSION_NODOT"] = PYTORCH_VERSION.replace(".", "")

View File

@@ -5,7 +5,13 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
sudo docker run --rm -v "$PWD/../../:/inside" pytorch/conda-cuda bash inside/packaging/linux_wheels/inside.sh
sudo docker run --rm -v "$PWD/../../:/inside" -e SELECTED_CUDA=cu113 pytorch/conda-builder:cuda113 bash inside/packaging/linux_wheels/inside.sh
sudo docker run --rm -v "$PWD/../../:/inside" -e SELECTED_CUDA=cu115 pytorch/conda-builder:cuda115 bash inside/packaging/linux_wheels/inside.sh
sudo docker run --rm -v "$PWD/../../:/inside" -e SELECTED_CUDA=cu116 pytorch/conda-builder:cuda116 bash inside/packaging/linux_wheels/inside.sh
# Some directory to persist downloaded conda packages
conda_cache=/raid/$USER/building_conda_cache
mkdir -p "$conda_cache"
sudo docker run --rm -v "$conda_cache:/conda_cache" -v "$PWD/../../:/inside" -e SELECTED_CUDA=cu113 pytorch/conda-builder:cuda113 bash inside/packaging/linux_wheels/inside.sh
sudo docker run --rm -v "$conda_cache:/conda_cache" -v "$PWD/../../:/inside" -e SELECTED_CUDA=cu115 pytorch/conda-builder:cuda115 bash inside/packaging/linux_wheels/inside.sh
sudo docker run --rm -v "$conda_cache:/conda_cache" -v "$PWD/../../:/inside" -e SELECTED_CUDA=cu116 pytorch/conda-builder:cuda116 bash inside/packaging/linux_wheels/inside.sh
sudo docker run --rm -v "$conda_cache:/conda_cache" -v "$PWD/../../:/inside" -e SELECTED_CUDA=cu117 pytorch/conda-builder:cuda117 bash inside/packaging/linux_wheels/inside.sh
sudo docker run --rm -v "$conda_cache:/conda_cache" -v "$PWD/../../:/inside" -e SELECTED_CUDA=cu118 pytorch/conda-builder:cuda118 bash inside/packaging/linux_wheels/inside.sh

View File

@@ -16,23 +16,32 @@ VERSION=$(python -c "exec(open('pytorch3d/__init__.py').read()); print(__version
export BUILD_VERSION=$VERSION
export FORCE_CUDA=1
export MAX_JOBS=8
export CONDA_PKGS_DIRS=/conda_cache
wget --no-verbose https://github.com/NVIDIA/cub/archive/1.10.0.tar.gz
tar xzf 1.10.0.tar.gz
CUB_HOME=$(realpath ./cub-1.10.0)
export CUB_HOME
echo "CUB_HOME is now $CUB_HOME"
if false
then
# We used to have to do this for old versions of CUDA
wget --no-verbose https://github.com/NVIDIA/cub/archive/1.10.0.tar.gz
tar xzf 1.10.0.tar.gz
CUB_HOME=$(realpath ./cub-1.10.0)
export CUB_HOME
echo "CUB_HOME is now $CUB_HOME"
fi
# As a rule, we want to build for any combination of dependencies which is supported by
# PyTorch3D and not older than the current Google Colab set up.
PYTHON_VERSIONS="3.7 3.8 3.9 3.10"
PYTHON_VERSIONS="3.8 3.9 3.10"
# the keys are pytorch versions
declare -A CONDA_CUDA_VERSIONS=(
["1.10.1"]="cu111 cu113"
["1.10.2"]="cu111 cu113"
["1.10.0"]="cu111 cu113"
["1.11.0"]="cu111 cu113 cu115"
# ["1.11.0"]="cu113"
# ["1.12.0"]="cu113"
# ["1.12.1"]="cu113"
# ["1.13.0"]="cu116"
# ["1.13.1"]="cu116 cu117"
# ["2.0.0"]="cu117 cu118"
["2.0.1"]="cu117 cu118"
)
@@ -41,39 +50,43 @@ for python_version in $PYTHON_VERSIONS
do
for pytorch_version in "${!CONDA_CUDA_VERSIONS[@]}"
do
if [[ "3.7 3.8" != *$python_version* ]] && [[ "1.7.0" == *$pytorch_version* ]]
then
#python 3.9 and later not supported by pytorch 1.7.0 and before
continue
fi
if [[ "3.7 3.8 3.9" != *$python_version* ]] && [[ "1.7.0 1.7.1 1.8.0 1.8.1 1.9.0 1.9.1 1.10.0 1.10.1 1.10.2" == *$pytorch_version* ]]
then
#python 3.10 and later not supported by pytorch 1.10.2 and before
continue
fi
extra_channel="-c conda-forge"
extra_channel="-c nvidia"
cudatools="pytorch-cuda"
if [[ "1.11.0" == "$pytorch_version" ]]
then
extra_channel=""
cudatools="cudatoolkit"
fi
if [[ "1.12.0" == "$pytorch_version" ]] || [[ "1.12.1" == "$pytorch_version" ]]
then
extra_channel="-c conda-forge"
cudatools="cudatoolkit"
fi
for cu_version in ${CONDA_CUDA_VERSIONS[$pytorch_version]}
do
if [[ "cu113 cu115 cu116" == *$cu_version* ]]
# ^^^ CUDA versions listed here have to be built
# in their own containers.
then
if [[ $SELECTED_CUDA != "$cu_version" ]]
then
continue
fi
elif [[ $SELECTED_CUDA != "" ]]
then
continue
fi
case "$cu_version" in
cu118)
export CUDA_HOME=/usr/local/cuda-11.8/
export CUDA_TAG=11.8
export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_80,code=sm_80 -gencode=arch=compute_86,code=sm_86 -gencode=arch=compute_50,code=compute_50"
;;
cu117)
export CUDA_HOME=/usr/local/cuda-11.7/
export CUDA_TAG=11.7
export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_80,code=sm_80 -gencode=arch=compute_86,code=sm_86 -gencode=arch=compute_50,code=compute_50"
;;
cu116)
export CUDA_HOME=/usr/local/cuda-11.6/
export CUDA_TAG=11.6
@@ -130,7 +143,7 @@ do
conda create -y -n "$tag" "python=$python_version"
conda activate "$tag"
# shellcheck disable=SC2086
conda install -y -c pytorch $extra_channel "pytorch=$pytorch_version" "cudatoolkit=$CUDA_TAG" torchvision
conda install -y -c pytorch $extra_channel "pytorch=$pytorch_version" "$cudatools=$CUDA_TAG"
pip install fvcore iopath
echo "python version" "$python_version" "pytorch version" "$pytorch_version" "cuda version" "$cu_version" "tag" "$tag"

View File

@@ -12,8 +12,9 @@ requirements:
host:
- python
- setuptools
{{ environ.get('SETUPTOOLS_CONSTRAINT') }}
{{ environ.get('CONDA_PYTORCH_BUILD_CONSTRAINT') }}
{{ environ.get('CONDA_PYTORCH_MKL_CONSTRAINT') }}
{{ environ.get('CONDA_CUDATOOLKIT_CONSTRAINT') }}
{{ environ.get('CONDA_CPUONLY_FEATURE') }}

View File

@@ -3,3 +3,5 @@
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe

View File

@@ -5,6 +5,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
""""
This file is the entry point for launching experiments with Implicitron.

View File

@@ -3,3 +3,5 @@
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import logging
import os
from typing import Optional

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import inspect
import logging
import os
@@ -121,7 +123,6 @@ class ImplicitronOptimizerFactory(OptimizerFactoryBase):
"""
# Get the parameters to optimize
if hasattr(model, "_get_param_groups"): # use the model function
# pyre-ignore[29]
p_groups = model._get_param_groups(self.lr, wd=self.weight_decay)
else:
p_groups = [

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import logging
import os
import time
@@ -21,7 +23,6 @@ from pytorch3d.implicitron.tools.config import (
run_auto_creation,
)
from pytorch3d.implicitron.tools.stats import Stats
from pytorch3d.renderer.cameras import CamerasBase
from torch.utils.data import DataLoader, Dataset
from .utils import seed_all_random_engines
@@ -111,6 +112,8 @@ class ImplicitronTrainingLoop(TrainingLoopBase):
def __post_init__(self):
run_auto_creation(self)
# pyre-fixme[14]: `run` overrides method defined in `TrainingLoopBase`
# inconsistently.
def run(
self,
*,
@@ -256,7 +259,6 @@ class ImplicitronTrainingLoop(TrainingLoopBase):
list(log_vars),
plot_file=os.path.join(exp_dir, "train_stats.pdf"),
visdom_env=visdom_env_charts,
verbose=False,
visdom_server=self.visdom_server,
visdom_port=self.visdom_port,
)
@@ -382,7 +384,8 @@ class ImplicitronTrainingLoop(TrainingLoopBase):
# print textual status update
if it % self.metric_print_interval == 0 or last_iter:
stats.print(stat_set=trainmode, max_it=n_batches)
std_out = stats.get_status_string(stat_set=trainmode, max_it=n_batches)
logger.info(std_out)
# visualize results
if (
@@ -392,7 +395,6 @@ class ImplicitronTrainingLoop(TrainingLoopBase):
):
prefix = f"e{stats.epoch}_it{stats.it[trainmode]}"
if hasattr(model, "visualize"):
# pyre-ignore [29]
model.visualize(
viz,
visdom_env_imgs,

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import random

View File

@@ -3,3 +3,5 @@
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe

View File

@@ -129,6 +129,19 @@ data_source_ImplicitronDataSource_args:
dataset_length_train: 0
dataset_length_val: 0
dataset_length_test: 0
data_loader_map_provider_TrainEvalDataLoaderMapProvider_args:
batch_size: 1
num_workers: 0
dataset_length_train: 0
dataset_length_val: 0
dataset_length_test: 0
train_conditioning_type: SAME
val_conditioning_type: SAME
test_conditioning_type: KNOWN
images_per_seq_options: []
sample_consecutive_frames: false
consecutive_frames_max_gap: 0
consecutive_frames_max_gap_seconds: 0.1
model_factory_ImplicitronModelFactory_args:
resume: true
model_class_type: GenericModel
@@ -203,6 +216,7 @@ model_factory_ImplicitronModelFactory_args:
n_rays_total_training: null
stratified_point_sampling_training: true
stratified_point_sampling_evaluation: false
cast_ray_bundle_as_cone: false
scene_extent: 8.0
scene_center:
- 0.0
@@ -215,6 +229,7 @@ model_factory_ImplicitronModelFactory_args:
n_rays_total_training: null
stratified_point_sampling_training: true
stratified_point_sampling_evaluation: false
cast_ray_bundle_as_cone: false
min_depth: 0.1
max_depth: 8.0
renderer_LSTMRenderer_args:
@@ -234,6 +249,8 @@ model_factory_ImplicitronModelFactory_args:
append_coarse_samples_to_fine: true
density_noise_std_train: 0.0
return_weights: false
blurpool_weights: false
sample_pdf_eps: 1.0e-05
raymarcher_CumsumRaymarcher_args:
surface_thickness: 1
bg_color:
@@ -346,6 +363,7 @@ model_factory_ImplicitronModelFactory_args:
n_hidden_neurons_dir: 128
input_xyz: true
xyz_ray_dir_in_camera_coords: false
use_integrated_positional_encoding: false
transformer_dim_down_factor: 2.0
n_hidden_neurons_xyz: 80
n_layers_xyz: 2
@@ -357,6 +375,7 @@ model_factory_ImplicitronModelFactory_args:
n_hidden_neurons_dir: 128
input_xyz: true
xyz_ray_dir_in_camera_coords: false
use_integrated_positional_encoding: false
transformer_dim_down_factor: 1.0
n_hidden_neurons_xyz: 256
n_layers_xyz: 8
@@ -629,6 +648,7 @@ model_factory_ImplicitronModelFactory_args:
n_rays_total_training: null
stratified_point_sampling_training: true
stratified_point_sampling_evaluation: false
cast_ray_bundle_as_cone: false
scene_extent: 8.0
scene_center:
- 0.0
@@ -641,6 +661,7 @@ model_factory_ImplicitronModelFactory_args:
n_rays_total_training: null
stratified_point_sampling_training: true
stratified_point_sampling_evaluation: false
cast_ray_bundle_as_cone: false
min_depth: 0.1
max_depth: 8.0
renderer_LSTMRenderer_args:
@@ -660,6 +681,8 @@ model_factory_ImplicitronModelFactory_args:
append_coarse_samples_to_fine: true
density_noise_std_train: 0.0
return_weights: false
blurpool_weights: false
sample_pdf_eps: 1.0e-05
raymarcher_CumsumRaymarcher_args:
surface_thickness: 1
bg_color:
@@ -724,6 +747,7 @@ model_factory_ImplicitronModelFactory_args:
n_hidden_neurons_dir: 128
input_xyz: true
xyz_ray_dir_in_camera_coords: false
use_integrated_positional_encoding: false
transformer_dim_down_factor: 2.0
n_hidden_neurons_xyz: 80
n_layers_xyz: 2
@@ -735,6 +759,7 @@ model_factory_ImplicitronModelFactory_args:
n_hidden_neurons_dir: 128
input_xyz: true
xyz_ray_dir_in_camera_coords: false
use_integrated_positional_encoding: false
transformer_dim_down_factor: 1.0
n_hidden_neurons_xyz: 256
n_layers_xyz: 8
@@ -962,6 +987,7 @@ model_factory_ImplicitronModelFactory_args:
n_hidden_neurons_dir: 128
input_xyz: true
xyz_ray_dir_in_camera_coords: false
use_integrated_positional_encoding: false
transformer_dim_down_factor: 2.0
n_hidden_neurons_xyz: 80
n_layers_xyz: 2
@@ -973,6 +999,7 @@ model_factory_ImplicitronModelFactory_args:
n_hidden_neurons_dir: 128
input_xyz: true
xyz_ray_dir_in_camera_coords: false
use_integrated_positional_encoding: false
transformer_dim_down_factor: 1.0
n_hidden_neurons_xyz: 256
n_layers_xyz: 8

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import os
import tempfile
import unittest
@@ -132,6 +134,13 @@ class TestExperiment(unittest.TestCase):
# Check that the default config values, defined by Experiment and its
# members, is what we expect it to be.
cfg = OmegaConf.structured(experiment.Experiment)
# the following removes the possible effect of env variables
ds_arg = cfg.data_source_ImplicitronDataSource_args
ds_arg.dataset_map_provider_JsonIndexDatasetMapProvider_args.dataset_root = ""
ds_arg.dataset_map_provider_JsonIndexDatasetMapProviderV2_args.dataset_root = ""
if "dataset_map_provider_SqlIndexDatasetMapProvider_args" in ds_arg:
del ds_arg.dataset_map_provider_SqlIndexDatasetMapProvider_args
cfg.training_loop_ImplicitronTrainingLoop_args.visdom_port = 8097
yaml = OmegaConf.to_yaml(cfg, sort_keys=False)
if DEBUG:
(DATA_DIR / "experiment.yaml").write_text(yaml)

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import logging
import os
import unittest

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import os
import unittest

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import contextlib
import logging
import os

View File

@@ -5,6 +5,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
"""
Script to visualize a previously trained model. Example call:

View File

@@ -343,12 +343,14 @@ class RadianceFieldRenderer(torch.nn.Module):
# For a full render pass concatenate the output chunks,
# and reshape to image size.
out = {
k: torch.cat(
[ch_o[k] for ch_o in chunk_outputs],
dim=1,
).view(-1, *self._image_size, 3)
if chunk_outputs[0][k] is not None
else None
k: (
torch.cat(
[ch_o[k] for ch_o in chunk_outputs],
dim=1,
).view(-1, *self._image_size, 3)
if chunk_outputs[0][k] is not None
else None
)
for k in ("rgb_fine", "rgb_coarse", "rgb_gt")
}
else:

View File

@@ -330,9 +330,9 @@ class NeRFRaysampler(torch.nn.Module):
if self.training:
# During training we randomly subsample rays.
sel_rays = torch.randperm(n_pixels, device=device)[
: self._mc_raysampler._n_rays_per_image
]
sel_rays = torch.randperm(
n_pixels, device=full_ray_bundle.lengths.device
)[: self._mc_raysampler._n_rays_per_image]
else:
# In case we test, we take only the requested chunk.
if chunksize is None:

View File

@@ -4,4 +4,6 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
__version__ = "0.7.3"
# pyre-unsafe
__version__ = "0.7.6"

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
from .datatypes import Device, get_device, make_device

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
from typing import Sequence, Tuple, Union
import torch

View File

@@ -4,7 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
import sys
# pyre-unsafe
from typing import Optional, Union
import torch

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import math
from typing import Tuple

View File

@@ -4,5 +4,7 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
from .symeig3x3 import symeig3x3
from .utils import _safe_det_3x3

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import math
from typing import Optional, Tuple

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import torch

View File

@@ -266,6 +266,8 @@ at::Tensor FaceAreasNormalsBackwardCuda(
grad_normals_t{grad_normals, "grad_normals", 4};
at::CheckedFrom c = "FaceAreasNormalsBackwardCuda";
at::checkAllSameGPU(c, {verts_t, faces_t, grad_areas_t, grad_normals_t});
// This is nondeterministic because atomicAdd
at::globalContext().alertNotDeterministic("FaceAreasNormalsBackwardCuda");
// Set the device for the kernel launch based on the device of verts
at::cuda::CUDAGuard device_guard(verts.device());

View File

@@ -130,6 +130,9 @@ std::tuple<at::Tensor, at::Tensor> InterpFaceAttrsBackwardCuda(
at::checkAllSameType(
c, {barycentric_coords_t, face_attrs_t, grad_pix_attrs_t});
// This is nondeterministic because atomicAdd
at::globalContext().alertNotDeterministic("InterpFaceAttrsBackwardCuda");
// Set the device for the kernel launch based on the input
at::cuda::CUDAGuard device_guard(pix_to_face.device());
cudaStream_t stream = at::cuda::getCurrentCUDAStream();

View File

@@ -12,8 +12,6 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <thrust/device_vector.h>
#include <thrust/tuple.h>
#include "iou_box3d/iou_utils.cuh"
// Parallelize over N*M computations which can each be done

View File

@@ -8,7 +8,6 @@
#include <float.h>
#include <math.h>
#include <thrust/device_vector.h>
#include <cstdio>
#include "utils/float_math.cuh"

View File

@@ -338,7 +338,7 @@ std::tuple<at::Tensor, at::Tensor> KNearestNeighborIdxCuda(
TORCH_CHECK((norm == 1) || (norm == 2), "Norm must be 1 or 2.");
TORCH_CHECK(p2.size(2) == D, "Point sets must have the same last dimension");
TORCH_CHECK(p1.size(2) == D, "Point sets must have the same last dimension");
auto long_dtype = lengths1.options().dtype(at::kLong);
auto idxs = at::zeros({N, P1, K}, long_dtype);
auto dists = at::zeros({N, P1, K}, p1.options());
@@ -495,7 +495,7 @@ __global__ void KNearestNeighborBackwardKernel(
if ((p1_idx < num1) && (k < num2)) {
const float grad_dist = grad_dists[n * P1 * K + p1_idx * K + k];
// index of point in p2 corresponding to the k-th nearest neighbor
const size_t p2_idx = idxs[n * P1 * K + p1_idx * K + k];
const int64_t p2_idx = idxs[n * P1 * K + p1_idx * K + k];
// If the index is the pad value of -1 then ignore it
if (p2_idx == -1) {
continue;
@@ -534,6 +534,9 @@ std::tuple<at::Tensor, at::Tensor> KNearestNeighborBackwardCuda(
c, {p1_t, p2_t, lengths1_t, lengths2_t, idxs_t, grad_dists_t});
at::checkAllSameType(c, {p1_t, p2_t, grad_dists_t});
// This is nondeterministic because atomicAdd
at::globalContext().alertNotDeterministic("KNearestNeighborBackwardCuda");
// Set the device for the kernel launch based on the device of the input
at::cuda::CUDAGuard device_guard(p1.device());
cudaStream_t stream = at::cuda::getCurrentCUDAStream();

View File

@@ -9,8 +9,6 @@
#include <ATen/ATen.h>
#include <ATen/cuda/CUDAContext.h>
#include <c10/cuda/CUDAGuard.h>
#include <thrust/device_vector.h>
#include <thrust/scan.h>
#include <cstdio>
#include "marching_cubes/tables.h"
@@ -40,20 +38,6 @@ through" each cube in the grid.
// EPS: Used to indicate if two float values are close
__constant__ const float EPSILON = 1e-5;
// Thrust wrapper for exclusive scan
//
// Args:
// output: pointer to on-device output array
// input: pointer to on-device input array, where scan is performed
// numElements: number of elements for the input array
//
void ThrustScanWrapper(int* output, int* input, int numElements) {
thrust::exclusive_scan(
thrust::device_ptr<int>(input),
thrust::device_ptr<int>(input + numElements),
thrust::device_ptr<int>(output));
}
// Linearly interpolate the position where an isosurface cuts an edge
// between two vertices, based on their scalar values
//
@@ -239,7 +223,7 @@ __global__ void CompactVoxelsKernel(
compactedVoxelArray,
const at::PackedTensorAccessor32<int, 1, at::RestrictPtrTraits>
voxelOccupied,
const at::PackedTensorAccessor32<int, 1, at::RestrictPtrTraits>
const at::PackedTensorAccessor32<int64_t, 1, at::RestrictPtrTraits>
voxelOccupiedScan,
uint numVoxels) {
uint id = blockIdx.x * blockDim.x + threadIdx.x;
@@ -271,7 +255,8 @@ __global__ void GenerateFacesKernel(
at::PackedTensorAccessor<int64_t, 1, at::RestrictPtrTraits> ids,
at::PackedTensorAccessor32<int, 1, at::RestrictPtrTraits>
compactedVoxelArray,
at::PackedTensorAccessor32<int, 1, at::RestrictPtrTraits> numVertsScanned,
at::PackedTensorAccessor32<int64_t, 1, at::RestrictPtrTraits>
numVertsScanned,
const uint activeVoxels,
const at::PackedTensorAccessor32<float, 3, at::RestrictPtrTraits> vol,
const at::PackedTensorAccessor32<int, 2, at::RestrictPtrTraits> faceTable,
@@ -397,6 +382,44 @@ __global__ void GenerateFacesKernel(
} // end for grid-strided kernel
}
// ATen/Torch does not have an exclusive-scan operator. Additionally, in the
// code below we need to get the "total number of items to work on" after
// a scan, which with an inclusive-scan would simply be the value of the last
// element in the tensor.
//
// This utility function hits two birds with one stone, by running
// an inclusive-scan into a right-shifted view of a tensor that's
// allocated to be one element bigger than the input tensor.
//
// Note; return tensor is `int64_t` per element, even if the input
// tensor is only 32-bit. Also, the return tensor is one element bigger
// than the input one.
//
// Secondary optional argument is an output argument that gets the
// value of the last element of the return tensor (because you almost
// always need this CPU-side right after this function anyway).
static at::Tensor ExclusiveScanAndTotal(
const at::Tensor& inTensor,
int64_t* optTotal = nullptr) {
const auto inSize = inTensor.sizes()[0];
auto retTensor = at::zeros({inSize + 1}, at::kLong).to(inTensor.device());
using at::indexing::None;
using at::indexing::Slice;
auto rightShiftedView = retTensor.index({Slice(1, None)});
// Do an (inclusive-scan) cumulative sum in to the view that's
// shifted one element to the right...
at::cumsum_out(rightShiftedView, inTensor, 0, at::kLong);
if (optTotal) {
*optTotal = retTensor[inSize].cpu().item<int64_t>();
}
// ...so that the not-shifted tensor holds the exclusive-scan
return retTensor;
}
// Entrance for marching cubes cuda extension. Marching Cubes is an algorithm to
// create triangle meshes from an implicit function (one of the form f(x, y, z)
// = 0). It works by iteratively checking a grid of cubes superimposed over a
@@ -455,6 +478,9 @@ std::tuple<at::Tensor, at::Tensor, at::Tensor> MarchingCubesCuda(
grid.x = 65535;
}
using at::indexing::None;
using at::indexing::Slice;
auto d_voxelVerts =
at::zeros({numVoxels}, at::TensorOptions().dtype(at::kInt))
.to(vol.device());
@@ -477,18 +503,9 @@ std::tuple<at::Tensor, at::Tensor, at::Tensor> MarchingCubesCuda(
// count for voxels in the grid and compute the number of active voxels.
// If the number of active voxels is 0, return zero tensor for verts and
// faces.
int64_t activeVoxels = 0;
auto d_voxelOccupiedScan =
at::zeros({numVoxels}, at::TensorOptions().dtype(at::kInt))
.to(vol.device());
ThrustScanWrapper(
d_voxelOccupiedScan.data_ptr<int>(),
d_voxelOccupied.data_ptr<int>(),
numVoxels);
// number of active voxels
int lastElement = d_voxelVerts[numVoxels - 1].cpu().item<int>();
int lastScan = d_voxelOccupiedScan[numVoxels - 1].cpu().item<int>();
int activeVoxels = lastElement + lastScan;
ExclusiveScanAndTotal(d_voxelOccupied, &activeVoxels);
const int device_id = vol.device().index();
auto opt = at::TensorOptions().dtype(at::kInt).device(at::kCUDA, device_id);
@@ -503,28 +520,21 @@ std::tuple<at::Tensor, at::Tensor, at::Tensor> MarchingCubesCuda(
return std::make_tuple(verts, faces, ids);
}
// Execute "CompactVoxelsKernel" kernel to compress voxels for accleration.
// Execute "CompactVoxelsKernel" kernel to compress voxels for acceleration.
// This allows us to run triangle generation on only the occupied voxels.
auto d_compVoxelArray = at::zeros({activeVoxels}, opt);
CompactVoxelsKernel<<<grid, threads, 0, stream>>>(
d_compVoxelArray.packed_accessor32<int, 1, at::RestrictPtrTraits>(),
d_voxelOccupied.packed_accessor32<int, 1, at::RestrictPtrTraits>(),
d_voxelOccupiedScan.packed_accessor32<int, 1, at::RestrictPtrTraits>(),
d_voxelOccupiedScan
.packed_accessor32<int64_t, 1, at::RestrictPtrTraits>(),
numVoxels);
AT_CUDA_CHECK(cudaGetLastError());
cudaDeviceSynchronize();
// Scan d_voxelVerts array to generate offsets of vertices for each voxel
auto d_voxelVertsScan = at::zeros({numVoxels}, opt);
ThrustScanWrapper(
d_voxelVertsScan.data_ptr<int>(),
d_voxelVerts.data_ptr<int>(),
numVoxels);
// total number of vertices
lastElement = d_voxelVerts[numVoxels - 1].cpu().item<int>();
lastScan = d_voxelVertsScan[numVoxels - 1].cpu().item<int>();
int totalVerts = lastElement + lastScan;
int64_t totalVerts = 0;
auto d_voxelVertsScan = ExclusiveScanAndTotal(d_voxelVerts, &totalVerts);
// Execute "GenerateFacesKernel" kernel
// This runs only on the occupied voxels.
@@ -544,7 +554,7 @@ std::tuple<at::Tensor, at::Tensor, at::Tensor> MarchingCubesCuda(
faces.packed_accessor<int64_t, 2, at::RestrictPtrTraits>(),
ids.packed_accessor<int64_t, 1, at::RestrictPtrTraits>(),
d_compVoxelArray.packed_accessor32<int, 1, at::RestrictPtrTraits>(),
d_voxelVertsScan.packed_accessor32<int, 1, at::RestrictPtrTraits>(),
d_voxelVertsScan.packed_accessor32<int64_t, 1, at::RestrictPtrTraits>(),
activeVoxels,
vol.packed_accessor32<float, 3, at::RestrictPtrTraits>(),
faceTable.packed_accessor32<int, 2, at::RestrictPtrTraits>(),

View File

@@ -71,8 +71,8 @@ std::tuple<at::Tensor, at::Tensor, at::Tensor> MarchingCubesCpu(
if ((j + 1) % 3 == 0 && ps[0] != ps[1] && ps[1] != ps[2] &&
ps[2] != ps[0]) {
for (int k = 0; k < 3; k++) {
int v = tri[k];
edge_id_to_v[tri.at(k)] = ps.at(k);
int64_t v = tri.at(k);
edge_id_to_v[v] = ps.at(k);
if (!uniq_edge_id.count(v)) {
uniq_edge_id[v] = verts.size();
verts.push_back(edge_id_to_v[v]);

View File

@@ -305,6 +305,8 @@ std::tuple<at::Tensor, at::Tensor> DistanceBackwardCuda(
at::CheckedFrom c = "DistanceBackwardCuda";
at::checkAllSameGPU(c, {objects_t, targets_t, idx_objects_t, grad_dists_t});
at::checkAllSameType(c, {objects_t, targets_t, grad_dists_t});
// This is nondeterministic because atomicAdd
at::globalContext().alertNotDeterministic("DistanceBackwardCuda");
// Set the device for the kernel launch based on the device of the input
at::cuda::CUDAGuard device_guard(objects.device());
@@ -624,6 +626,9 @@ std::tuple<at::Tensor, at::Tensor> PointFaceArrayDistanceBackwardCuda(
at::CheckedFrom c = "PointFaceArrayDistanceBackwardCuda";
at::checkAllSameGPU(c, {points_t, tris_t, grad_dists_t});
at::checkAllSameType(c, {points_t, tris_t, grad_dists_t});
// This is nondeterministic because atomicAdd
at::globalContext().alertNotDeterministic(
"PointFaceArrayDistanceBackwardCuda");
// Set the device for the kernel launch based on the device of the input
at::cuda::CUDAGuard device_guard(points.device());
@@ -787,6 +792,9 @@ std::tuple<at::Tensor, at::Tensor> PointEdgeArrayDistanceBackwardCuda(
at::CheckedFrom c = "PointEdgeArrayDistanceBackwardCuda";
at::checkAllSameGPU(c, {points_t, segms_t, grad_dists_t});
at::checkAllSameType(c, {points_t, segms_t, grad_dists_t});
// This is nondeterministic because atomicAdd
at::globalContext().alertNotDeterministic(
"PointEdgeArrayDistanceBackwardCuda");
// Set the device for the kernel launch based on the device of the input
at::cuda::CUDAGuard device_guard(points.device());

View File

@@ -141,6 +141,9 @@ void PointsToVolumesForwardCuda(
grid_sizes_t,
mask_t});
// This is nondeterministic because atomicAdd
at::globalContext().alertNotDeterministic("PointsToVolumesForwardCuda");
// Set the device for the kernel launch based on the device of the input
at::cuda::CUDAGuard device_guard(points_3d.device());
cudaStream_t stream = at::cuda::getCurrentCUDAStream();

View File

@@ -30,11 +30,18 @@
#define GLOBAL __global__
#define RESTRICT __restrict__
#define DEBUGBREAK()
#ifdef __NVCC_DIAG_PRAGMA_SUPPORT__
#pragma nv_diag_suppress 1866
#pragma nv_diag_suppress 2941
#pragma nv_diag_suppress 2951
#pragma nv_diag_suppress 2967
#else
#pragma diag_suppress = attribute_not_allowed
#pragma diag_suppress = 1866
#pragma diag_suppress = 2941
#pragma diag_suppress = 2951
#pragma diag_suppress = 2967
#endif
#else // __CUDACC__
#define INLINE inline
#define HOST
@@ -49,6 +56,7 @@
#pragma clang diagnostic pop
#ifdef WITH_CUDA
#include <ATen/cuda/CUDAContext.h>
#include <vector_functions.h>
#else
#ifndef cudaStream_t
typedef void* cudaStream_t;
@@ -65,8 +73,6 @@ struct float2 {
struct float3 {
float x, y, z;
};
#endif
namespace py = pybind11;
inline float3 make_float3(const float& x, const float& y, const float& z) {
float3 res;
res.x = x;
@@ -74,6 +80,8 @@ inline float3 make_float3(const float& x, const float& y, const float& z) {
res.z = z;
return res;
}
#endif
namespace py = pybind11;
inline bool operator==(const float3& a, const float3& b) {
return a.x == b.x && a.y == b.y && a.z == b.z;

View File

@@ -357,11 +357,11 @@ void MAX_WS(
//
//
#define END_PARALLEL() \
end_parallel:; \
end_parallel :; \
}
#define END_PARALLEL_NORET() }
#define END_PARALLEL_2D() \
end_parallel:; \
end_parallel :; \
} \
}
#define END_PARALLEL_2D_NORET() \

View File

@@ -93,7 +93,7 @@ HOST void construct(
MALLOC(self->di_sorted_d, DrawInfo, max_num_balls);
MALLOC(self->region_flags_d, char, max_num_balls);
MALLOC(self->num_selected_d, size_t, 1);
MALLOC(self->forw_info_d, float, width* height*(3 + 2 * n_track));
MALLOC(self->forw_info_d, float, width* height * (3 + 2 * n_track));
MALLOC(self->min_max_pixels_d, IntersectInfo, 1);
MALLOC(self->grad_pos_d, float3, max_num_balls);
MALLOC(self->grad_col_d, float, max_num_balls* n_channels);

View File

@@ -102,6 +102,7 @@ void forward(
self->workspace_d,
self->workspace_size,
stream);
CHECKLAUNCH();
SORT_ASCENDING_WS(
self->min_depth_d,
self->min_depth_sorted_d,
@@ -111,6 +112,7 @@ void forward(
self->workspace_d,
self->workspace_size,
stream);
CHECKLAUNCH();
SORT_ASCENDING_WS(
self->min_depth_d,
self->min_depth_sorted_d,

View File

@@ -99,7 +99,7 @@ GLOBAL void render(
/** Whether loading of balls is completed. */
SHARED bool loading_done;
/** The number of balls loaded overall (just for statistics). */
SHARED int n_balls_loaded;
[[maybe_unused]] SHARED int n_balls_loaded;
/** The area this thread block covers. */
SHARED IntersectInfo block_area;
if (thread_block.thread_rank() == 0) {

View File

@@ -37,7 +37,7 @@ inline void fill_cam_vecs(
res->pixel_dir_y.x = pixel_dir_y.data_ptr<float>()[0];
res->pixel_dir_y.y = pixel_dir_y.data_ptr<float>()[1];
res->pixel_dir_y.z = pixel_dir_y.data_ptr<float>()[2];
auto sensor_dir_z = pixel_dir_y.cross(pixel_dir_x);
auto sensor_dir_z = pixel_dir_y.cross(pixel_dir_x, -1);
sensor_dir_z /= sensor_dir_z.norm();
if (right_handed) {
sensor_dir_z *= -1.f;

View File

@@ -244,8 +244,7 @@ at::Tensor RasterizeCoarseCuda(
if (num_bins_y >= kMaxItemsPerBin || num_bins_x >= kMaxItemsPerBin) {
std::stringstream ss;
ss << "In RasterizeCoarseCuda got num_bins_y: " << num_bins_y
<< ", num_bins_x: " << num_bins_x << ", "
<< "; that's too many!";
<< ", num_bins_x: " << num_bins_x << ", " << "; that's too many!";
AT_ERROR(ss.str());
}
auto opts = elems_per_batch.options().dtype(at::kInt);

View File

@@ -583,6 +583,9 @@ at::Tensor RasterizeMeshesBackwardCuda(
at::checkAllSameType(
c, {face_verts_t, grad_zbuf_t, grad_bary_t, grad_dists_t});
// This is nondeterministic because atomicAdd
at::globalContext().alertNotDeterministic("RasterizeMeshesBackwardCuda");
// Set the device for the kernel launch based on the device of the input
at::cuda::CUDAGuard device_guard(face_verts.device());
cudaStream_t stream = at::cuda::getCurrentCUDAStream();

View File

@@ -423,7 +423,8 @@ at::Tensor RasterizePointsBackwardCuda(
at::CheckedFrom c = "RasterizePointsBackwardCuda";
at::checkAllSameGPU(c, {points_t, idxs_t, grad_zbuf_t, grad_dists_t});
at::checkAllSameType(c, {points_t, grad_zbuf_t, grad_dists_t});
// This is nondeterministic because atomicAdd
at::globalContext().alertNotDeterministic("RasterizePointsBackwardCuda");
// Set the device for the kernel launch based on the device of the input
at::cuda::CUDAGuard device_guard(points.device());
cudaStream_t stream = at::cuda::getCurrentCUDAStream();

View File

@@ -155,7 +155,7 @@ at::Tensor FarthestPointSamplingCuda(
// Max possible threads per block
const int MAX_THREADS_PER_BLOCK = 1024;
const size_t threads = max(min(1 << points_pow_2, MAX_THREADS_PER_BLOCK), 1);
const size_t threads = max(min(1 << points_pow_2, MAX_THREADS_PER_BLOCK), 2);
// Create the accessors
auto points_a = points.packed_accessor64<float, 3, at::RestrictPtrTraits>();
@@ -215,10 +215,6 @@ at::Tensor FarthestPointSamplingCuda(
FarthestPointSamplingKernel<2><<<threads, threads, shared_mem, stream>>>(
points_a, lengths_a, K_a, idxs_a, min_point_dist_a, start_idxs_a);
break;
case 1:
FarthestPointSamplingKernel<1><<<threads, threads, shared_mem, stream>>>(
points_a, lengths_a, K_a, idxs_a, min_point_dist_a, start_idxs_a);
break;
default:
FarthestPointSamplingKernel<1024>
<<<blocks, threads, shared_mem, stream>>>(

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
from .r2n2 import BlenderCamera, collate_batched_R2N2, R2N2, render_cubified_voxels
from .shapenet import ShapeNetCore
from .utils import collate_batched_meshes

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
from .r2n2 import R2N2
from .utils import BlenderCamera, collate_batched_R2N2, render_cubified_voxels

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import json
import warnings
from os import path

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import math
from typing import Dict, List

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
from .shapenet_core import ShapeNetCore

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import json
import os
import warnings

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import warnings
from typing import Dict, List, Optional, Tuple

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
from typing import Dict, List
from pytorch3d.renderer.mesh import TexturesAtlas

View File

@@ -3,3 +3,5 @@
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe

View File

@@ -3,3 +3,5 @@
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import torch
from pytorch3d.implicitron.tools.config import registry

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
from dataclasses import dataclass
from enum import Enum
from typing import Iterator, List, Optional, Tuple

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
from typing import Optional, Tuple
from pytorch3d.implicitron.tools.config import (
@@ -72,6 +74,16 @@ class ImplicitronDataSource(DataSourceBase): # pyre-ignore[13]
from .rendered_mesh_dataset_map_provider import ( # noqa: F401
RenderedMeshDatasetMapProvider,
)
from .train_eval_data_loader_provider import ( # noqa: F401
TrainEvalDataLoaderMapProvider,
)
try:
from .sql_dataset_provider import ( # noqa: F401 # pyre-ignore
SqlIndexDatasetMapProvider,
)
except ModuleNotFoundError:
pass # environment without SQL dataset
finally:
pass

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
from collections import defaultdict
from dataclasses import dataclass
from typing import (

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import logging
import os
from dataclasses import dataclass

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import os
from abc import ABC, abstractmethod
from collections import defaultdict
@@ -203,7 +205,10 @@ class FrameData(Mapping[str, Any]):
when no image has been loaded)
"""
if self.bbox_xywh is None:
raise ValueError("Attempted cropping by metadata with empty bounding box")
raise ValueError(
"Attempted cropping by metadata with empty bounding box. Consider either"
" to remove_empty_masks or turn off box_crop in the dataset config."
)
if not self._uncropped:
raise ValueError(
@@ -450,6 +455,9 @@ class FrameDataBuilderBase(ReplaceableBase, Generic[FrameDataSubtype], ABC):
self,
frame_annotation: types.FrameAnnotation,
sequence_annotation: types.SequenceAnnotation,
*,
load_blobs: bool = True,
**kwargs,
) -> FrameDataSubtype:
"""An abstract method to build the frame data based on raw frame/sequence
annotations, load the binary data and adjust them according to the metadata.
@@ -465,8 +473,9 @@ class GenericFrameDataBuilder(FrameDataBuilderBase[FrameDataSubtype], ABC):
Beware that modifications of frame data are done in-place.
Args:
dataset_root: The root folder of the dataset; all the paths in jsons are
specified relative to this root (but not json paths themselves).
dataset_root: The root folder of the dataset; all paths in frame / sequence
annotations are defined w.r.t. this root. Has to be set if any of the
load_* flabs below is true.
load_images: Enable loading the frame RGB data.
load_depths: Enable loading the frame depth maps.
load_depth_masks: Enable loading the frame depth map masks denoting the
@@ -494,7 +503,7 @@ class GenericFrameDataBuilder(FrameDataBuilderBase[FrameDataSubtype], ABC):
path_manager: Optionally a PathManager for interpreting paths in a special way.
"""
dataset_root: str = ""
dataset_root: Optional[str] = None
load_images: bool = True
load_depths: bool = True
load_depth_masks: bool = True
@@ -510,11 +519,32 @@ class GenericFrameDataBuilder(FrameDataBuilderBase[FrameDataSubtype], ABC):
box_crop_context: float = 0.3
path_manager: Any = None
def __post_init__(self) -> None:
load_any_blob = (
self.load_images
or self.load_depths
or self.load_depth_masks
or self.load_masks
or self.load_point_clouds
)
if load_any_blob and self.dataset_root is None:
raise ValueError(
"dataset_root must be set to load any blob data. "
"Make sure it is set in either FrameDataBuilder or Dataset params."
)
if load_any_blob and not self._exists_in_dataset_root(""):
raise ValueError(
f"dataset_root is passed but {self.dataset_root} does not exist."
)
def build(
self,
frame_annotation: types.FrameAnnotation,
sequence_annotation: types.SequenceAnnotation,
*,
load_blobs: bool = True,
**kwargs,
) -> FrameDataSubtype:
"""Builds the frame data based on raw frame/sequence annotations, loads the
binary data and adjust them according to the metadata. The processing includes:
@@ -548,38 +578,58 @@ class GenericFrameDataBuilder(FrameDataBuilderBase[FrameDataSubtype], ABC):
camera_quality_score=safe_as_tensor(
sequence_annotation.viewpoint_quality_score, torch.float
),
point_cloud_quality_score=safe_as_tensor(
point_cloud.quality_score, torch.float
)
if point_cloud is not None
else None,
point_cloud_quality_score=(
safe_as_tensor(point_cloud.quality_score, torch.float)
if point_cloud is not None
else None
),
)
if load_blobs and self.load_masks and frame_annotation.mask is not None:
(
frame_data.fg_probability,
frame_data.mask_path,
frame_data.bbox_xywh,
) = self._load_fg_probability(frame_annotation)
fg_mask_np: Optional[np.ndarray] = None
mask_annotation = frame_annotation.mask
if mask_annotation is not None:
if load_blobs and self.load_masks:
fg_mask_np, mask_path = self._load_fg_probability(frame_annotation)
frame_data.mask_path = mask_path
frame_data.fg_probability = safe_as_tensor(fg_mask_np, torch.float)
bbox_xywh = mask_annotation.bounding_box_xywh
if bbox_xywh is None and fg_mask_np is not None:
bbox_xywh = get_bbox_from_mask(fg_mask_np, self.box_crop_mask_thr)
frame_data.bbox_xywh = safe_as_tensor(bbox_xywh, torch.float)
if frame_annotation.image is not None:
image_size_hw = safe_as_tensor(frame_annotation.image.size, torch.long)
frame_data.image_size_hw = image_size_hw # original image size
# image size after crop/resize
frame_data.effective_image_size_hw = image_size_hw
image_path = None
dataset_root = self.dataset_root
if frame_annotation.image.path is not None and dataset_root is not None:
image_path = os.path.join(dataset_root, frame_annotation.image.path)
frame_data.image_path = image_path
if load_blobs and self.load_images:
(
frame_data.image_rgb,
frame_data.image_path,
) = self._load_images(frame_annotation, frame_data.fg_probability)
if image_path is None:
raise ValueError("Image path is required to load images.")
if load_blobs and self.load_depths and frame_annotation.depth is not None:
image_np = load_image(self._local_path(image_path))
frame_data.image_rgb = self._postprocess_image(
image_np, frame_annotation.image.size, frame_data.fg_probability
)
if (
load_blobs
and self.load_depths
and frame_annotation.depth is not None
and frame_annotation.depth.path is not None
):
(
frame_data.depth_map,
frame_data.depth_path,
frame_data.depth_mask,
) = self._load_mask_depth(frame_annotation, frame_data.fg_probability)
) = self._load_mask_depth(frame_annotation, fg_mask_np)
if load_blobs and self.load_point_clouds and point_cloud is not None:
pcl_path = self._fix_point_cloud_path(point_cloud.path)
@@ -604,66 +654,56 @@ class GenericFrameDataBuilder(FrameDataBuilderBase[FrameDataSubtype], ABC):
def _load_fg_probability(
self, entry: types.FrameAnnotation
) -> Tuple[Optional[torch.Tensor], Optional[str], Optional[torch.Tensor]]:
full_path = os.path.join(self.dataset_root, entry.mask.path) # pyre-ignore
) -> Tuple[np.ndarray, str]:
assert self.dataset_root is not None and entry.mask is not None
full_path = os.path.join(self.dataset_root, entry.mask.path)
fg_probability = load_mask(self._local_path(full_path))
# we can use provided bbox_xywh or calculate it based on mask
# saves time to skip bbox calculation
# pyre-ignore
bbox_xywh = entry.mask.bounding_box_xywh or get_bbox_from_mask(
fg_probability, self.box_crop_mask_thr
)
if fg_probability.shape[-2:] != entry.image.size:
raise ValueError(
f"bad mask size: {fg_probability.shape[-2:]} vs {entry.image.size}!"
)
return (
safe_as_tensor(fg_probability, torch.float),
full_path,
safe_as_tensor(bbox_xywh, torch.long),
)
def _load_images(
return fg_probability, full_path
def _postprocess_image(
self,
entry: types.FrameAnnotation,
image_np: np.ndarray,
image_size: Tuple[int, int],
fg_probability: Optional[torch.Tensor],
) -> Tuple[torch.Tensor, str]:
assert self.dataset_root is not None and entry.image is not None
path = os.path.join(self.dataset_root, entry.image.path)
image_rgb = load_image(self._local_path(path))
) -> torch.Tensor:
image_rgb = safe_as_tensor(image_np, torch.float)
if image_rgb.shape[-2:] != entry.image.size:
raise ValueError(
f"bad image size: {image_rgb.shape[-2:]} vs {entry.image.size}!"
)
if image_rgb.shape[-2:] != image_size:
raise ValueError(f"bad image size: {image_rgb.shape[-2:]} vs {image_size}!")
if self.mask_images:
assert fg_probability is not None
image_rgb *= fg_probability
return image_rgb, path
return image_rgb
def _load_mask_depth(
self,
entry: types.FrameAnnotation,
fg_probability: Optional[torch.Tensor],
fg_mask: Optional[np.ndarray],
) -> Tuple[torch.Tensor, str, torch.Tensor]:
entry_depth = entry.depth
assert entry_depth is not None
path = os.path.join(self.dataset_root, entry_depth.path)
dataset_root = self.dataset_root
assert dataset_root is not None
assert entry_depth is not None and entry_depth.path is not None
path = os.path.join(dataset_root, entry_depth.path)
depth_map = load_depth(self._local_path(path), entry_depth.scale_adjustment)
if self.mask_depths:
assert fg_probability is not None
depth_map *= fg_probability
assert fg_mask is not None
depth_map *= fg_mask
if self.load_depth_masks:
assert entry_depth.mask_path is not None
mask_path = os.path.join(self.dataset_root, entry_depth.mask_path)
mask_path = entry_depth.mask_path
if self.load_depth_masks and mask_path is not None:
mask_path = os.path.join(dataset_root, mask_path)
depth_mask = load_depth_mask(self._local_path(mask_path))
else:
depth_mask = torch.ones_like(depth_map)
depth_mask = (depth_map > 0.0).astype(np.float32)
return torch.tensor(depth_map), path, torch.tensor(depth_mask)
@@ -708,6 +748,7 @@ class GenericFrameDataBuilder(FrameDataBuilderBase[FrameDataSubtype], ABC):
)
if path.startswith(unwanted_prefix):
path = path[len(unwanted_prefix) :]
assert self.dataset_root is not None
return os.path.join(self.dataset_root, path)
def _local_path(self, path: str) -> str:
@@ -715,6 +756,16 @@ class GenericFrameDataBuilder(FrameDataBuilderBase[FrameDataSubtype], ABC):
return path
return self.path_manager.get_local_path(path)
def _exists_in_dataset_root(self, relpath) -> bool:
if not self.dataset_root:
return False
full_path = os.path.join(self.dataset_root, relpath)
if self.path_manager is None:
return os.path.exists(full_path)
else:
return self.path_manager.exists(full_path)
@registry.register
class FrameDataBuilder(GenericWorkaround, GenericFrameDataBuilder[FrameData]):

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import copy
import functools
import gzip
@@ -124,9 +126,9 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
dimension of the cropping bounding box, relative to box size.
"""
frame_annotations_type: ClassVar[
Type[types.FrameAnnotation]
] = types.FrameAnnotation
frame_annotations_type: ClassVar[Type[types.FrameAnnotation]] = (
types.FrameAnnotation
)
path_manager: Any = None
frame_annotations_file: str = ""
@@ -190,6 +192,7 @@ class JsonIndexDataset(DatasetBase, ReplaceableBase):
box_crop=self.box_crop,
box_crop_mask_thr=self.box_crop_mask_thr,
box_crop_context=self.box_crop_context,
path_manager=self.path_manager,
)
logger.info(str(self))

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import json
import os

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import copy
import json

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import numpy as np
import torch

View File

@@ -1,6 +1,8 @@
# @lint-ignore-every LICENSELINT
# Adapted from https://github.com/bmild/nerf/blob/master/load_blender.py
# Copyright (c) 2020 bmild
# pyre-unsafe
import json
import os

View File

@@ -1,6 +1,8 @@
# @lint-ignore-every LICENSELINT
# Adapted from https://github.com/bmild/nerf/blob/master/load_llff.py
# Copyright (c) 2020 bmild
# pyre-unsafe
import logging
import os
import warnings
@@ -34,11 +36,7 @@ def _minify(basedir, path_manager, factors=(), resolutions=()):
imgdir = os.path.join(basedir, "images")
imgs = [os.path.join(imgdir, f) for f in sorted(_ls(path_manager, imgdir))]
imgs = [
f
for f in imgs
if any([f.endswith(ex) for ex in ["JPG", "jpg", "png", "jpeg", "PNG"]])
]
imgs = [f for f in imgs if f.endswith("JPG", "jpg", "png", "jpeg", "PNG")]
imgdir_orig = imgdir
wd = os.getcwd()

View File

@@ -0,0 +1,189 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# This functionality requires SQLAlchemy 2.0 or later.
import math
import struct
from typing import Optional, Tuple
import numpy as np
from pytorch3d.implicitron.dataset.types import (
DepthAnnotation,
ImageAnnotation,
MaskAnnotation,
PointCloudAnnotation,
VideoAnnotation,
ViewpointAnnotation,
)
from sqlalchemy import LargeBinary
from sqlalchemy.orm import (
composite,
DeclarativeBase,
Mapped,
mapped_column,
MappedAsDataclass,
)
from sqlalchemy.types import TypeDecorator
# these produce policies to serialize structured types to blobs
def ArrayTypeFactory(shape=None):
if shape is None:
class VariableShapeNumpyArrayType(TypeDecorator):
impl = LargeBinary
def process_bind_param(self, value, dialect):
if value is None:
return None
ndim_bytes = np.int32(value.ndim).tobytes()
shape_bytes = np.array(value.shape, dtype=np.int64).tobytes()
value_bytes = value.astype(np.float32).tobytes()
return ndim_bytes + shape_bytes + value_bytes
def process_result_value(self, value, dialect):
if value is None:
return None
ndim = np.frombuffer(value[:4], dtype=np.int32)[0]
value_start = 4 + 8 * ndim
shape = np.frombuffer(value[4:value_start], dtype=np.int64)
assert shape.shape == (ndim,)
return np.frombuffer(value[value_start:], dtype=np.float32).reshape(
shape
)
return VariableShapeNumpyArrayType
class NumpyArrayType(TypeDecorator):
impl = LargeBinary
def process_bind_param(self, value, dialect):
if value is not None:
if value.shape != shape:
raise ValueError(f"Passed an array of wrong shape: {value.shape}")
return value.astype(np.float32).tobytes()
return None
def process_result_value(self, value, dialect):
if value is not None:
return np.frombuffer(value, dtype=np.float32).reshape(shape)
return None
return NumpyArrayType
def TupleTypeFactory(dtype=float, shape: Tuple[int, ...] = (2,)):
format_symbol = {
float: "f", # float32
int: "i", # int32
}[dtype]
class TupleType(TypeDecorator):
impl = LargeBinary
_format = format_symbol * math.prod(shape)
def process_bind_param(self, value, _):
if value is None:
return None
if len(shape) > 1:
value = np.array(value, dtype=dtype).reshape(-1)
return struct.pack(TupleType._format, *value)
def process_result_value(self, value, _):
if value is None:
return None
loaded = struct.unpack(TupleType._format, value)
if len(shape) > 1:
loaded = _rec_totuple(
np.array(loaded, dtype=dtype).reshape(shape).tolist()
)
return loaded
return TupleType
def _rec_totuple(t):
if isinstance(t, list):
return tuple(_rec_totuple(x) for x in t)
return t
class Base(MappedAsDataclass, DeclarativeBase):
"""subclasses will be converted to dataclasses"""
class SqlFrameAnnotation(Base):
__tablename__ = "frame_annots"
sequence_name: Mapped[str] = mapped_column(primary_key=True)
frame_number: Mapped[int] = mapped_column(primary_key=True)
frame_timestamp: Mapped[float] = mapped_column(index=True)
image: Mapped[ImageAnnotation] = composite(
mapped_column("_image_path"),
mapped_column("_image_size", TupleTypeFactory(int)),
)
depth: Mapped[DepthAnnotation] = composite(
mapped_column("_depth_path", nullable=True),
mapped_column("_depth_scale_adjustment", nullable=True),
mapped_column("_depth_mask_path", nullable=True),
)
mask: Mapped[MaskAnnotation] = composite(
mapped_column("_mask_path", nullable=True),
mapped_column("_mask_mass", index=True, nullable=True),
mapped_column(
"_mask_bounding_box_xywh",
TupleTypeFactory(float, shape=(4,)),
nullable=True,
),
)
viewpoint: Mapped[ViewpointAnnotation] = composite(
mapped_column(
"_viewpoint_R", TupleTypeFactory(float, shape=(3, 3)), nullable=True
),
mapped_column(
"_viewpoint_T", TupleTypeFactory(float, shape=(3,)), nullable=True
),
mapped_column(
"_viewpoint_focal_length", TupleTypeFactory(float), nullable=True
),
mapped_column(
"_viewpoint_principal_point", TupleTypeFactory(float), nullable=True
),
mapped_column("_viewpoint_intrinsics_format", nullable=True),
)
class SqlSequenceAnnotation(Base):
__tablename__ = "sequence_annots"
sequence_name: Mapped[str] = mapped_column(primary_key=True)
category: Mapped[str] = mapped_column(index=True)
video: Mapped[VideoAnnotation] = composite(
mapped_column("_video_path", nullable=True),
mapped_column("_video_length", nullable=True),
)
point_cloud: Mapped[PointCloudAnnotation] = composite(
mapped_column("_point_cloud_path", nullable=True),
mapped_column("_point_cloud_quality_score", nullable=True),
mapped_column("_point_cloud_n_points", nullable=True),
)
# the bigger the better
viewpoint_quality_score: Mapped[Optional[float]] = mapped_column()

View File

@@ -4,15 +4,13 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
from os.path import dirname, join, realpath
from typing import Optional, Tuple
import torch
from pytorch3d.implicitron.tools.config import (
expand_args_fields,
registry,
run_auto_creation,
)
from pytorch3d.implicitron.tools.config import registry, run_auto_creation
from pytorch3d.io import IO
from pytorch3d.renderer import (
AmbientLights,

View File

@@ -4,6 +4,8 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import warnings
from collections import Counter

View File

@@ -4,12 +4,14 @@
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
# This file defines a base class for dataset map providers which
# provide data for a single scene.
from dataclasses import field
from typing import Iterable, Iterator, List, Optional, Tuple
from typing import Iterable, Iterator, List, Optional, Sequence, Tuple
import numpy as np
import torch
@@ -47,13 +49,12 @@ class SingleSceneDataset(DatasetBase, Configurable):
def __len__(self) -> int:
return len(self.poses)
# pyre-fixme[14]: `sequence_frames_in_order` overrides method defined in
# `DatasetBase` inconsistently.
def sequence_frames_in_order(
self, seq_name: str
self, seq_name: str, subset_filter: Optional[Sequence[str]] = None
) -> Iterator[Tuple[float, int, int]]:
for i in range(len(self)):
yield (0.0, i, i)
if subset_filter is None or self.frame_types[i] in subset_filter:
yield 0.0, i, i
def __getitem__(self, index) -> FrameData:
if index >= len(self):

View File

@@ -0,0 +1,768 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
import hashlib
import json
import logging
import os
from dataclasses import dataclass
from typing import (
Any,
ClassVar,
Dict,
Iterable,
Iterator,
List,
Optional,
Sequence,
Tuple,
Type,
Union,
)
import numpy as np
import pandas as pd
import sqlalchemy as sa
import torch
from pytorch3d.implicitron.dataset.dataset_base import DatasetBase
from pytorch3d.implicitron.dataset.frame_data import ( # noqa
FrameData,
FrameDataBuilder,
FrameDataBuilderBase,
)
from pytorch3d.implicitron.tools.config import (
registry,
ReplaceableBase,
run_auto_creation,
)
from sqlalchemy.orm import Session
from .orm_types import SqlFrameAnnotation, SqlSequenceAnnotation
logger = logging.getLogger(__name__)
_SET_LISTS_TABLE: str = "set_lists"
@registry.register
class SqlIndexDataset(DatasetBase, ReplaceableBase): # pyre-ignore
"""
A dataset with annotations stored as SQLite tables. This is an index-based dataset.
The length is returned after all sequence and frame filters are applied (see param
definitions below). Indices can either be ordinal in [0, len), or pairs of
(sequence_name, frame_number); with the performance of `dataset[i]` and
`dataset[sequence_name, frame_number]` being same. A faster way to get metadata only
(without blobs) is `dataset.meta[idx]` indexing; it requires box_crop==False.
With ordinal indexing, the sequences are NOT guaranteed to span contiguous index
ranges, and frame numbers are NOT guaranteed to be increasing within a sequence.
Sequence-aware batch samplers have to use `sequence_[frames|indices]_in_order`
iterators, which are efficient.
This functionality requires SQLAlchemy 2.0 or later.
Metadata-related args:
sqlite_metadata_file: A SQLite file containing frame and sequence annotation
tables (mapping to SqlFrameAnnotation and SqlSequenceAnnotation,
respectively).
dataset_root: A root directory to look for images, masks, etc. It can be
alternatively set in `frame_data_builder` args, but this takes precedence.
subset_lists_file: A JSON/sqlite file containing the lists of frames
corresponding to different subsets (e.g. train/val/test) of the dataset;
format: {subset: [(sequence_name, frame_id, file_path)]}. All entries
must be present in frame_annotation metadata table.
path_manager: a facade for non-POSIX filesystems.
subsets: Restrict frames/sequences only to the given list of subsets
as defined in subset_lists_file (see above). Applied before all other
filters.
remove_empty_masks: Removes the frames with no active foreground pixels
in the segmentation mask (needs frame_annotation.mask.mass to be set;
null values are retained).
pick_frames_sql_clause: SQL WHERE clause to constrain frame annotations
NOTE: This is a potential security risk! The string is passed to the SQL
engine verbatim. Dont expose it to end users of your application!
pick_categories: Restrict the dataset to the given list of categories.
pick_sequences: A Sequence of sequence names to restrict the dataset to.
exclude_sequences: A Sequence of the names of the sequences to exclude.
limit_sequences_per_category_to: Limit the dataset to the first up to N
sequences within each category (applies after all other sequence filters
but before `limit_sequences_to`).
limit_sequences_to: Limit the dataset to the first `limit_sequences_to`
sequences (after other sequence filters have been applied but before
frame-based filters).
limit_to: Limit the dataset to the first #limit_to frames (after other
filters have been applied, except n_frames_per_sequence).
n_frames_per_sequence: If > 0, randomly samples `n_frames_per_sequence`
frames in each sequences uniformly without replacement if it has
more frames than that; applied after other frame-level filters.
seed: The seed of the random generator sampling `n_frames_per_sequence`
random frames per sequence.
"""
frame_annotations_type: ClassVar[Type[SqlFrameAnnotation]] = SqlFrameAnnotation
sqlite_metadata_file: str = ""
dataset_root: Optional[str] = None
subset_lists_file: str = ""
eval_batches_file: Optional[str] = None
path_manager: Any = None
subsets: Optional[List[str]] = None
remove_empty_masks: bool = True
pick_frames_sql_clause: Optional[str] = None
pick_categories: Tuple[str, ...] = ()
pick_sequences: Tuple[str, ...] = ()
exclude_sequences: Tuple[str, ...] = ()
limit_sequences_per_category_to: int = 0
limit_sequences_to: int = 0
limit_to: int = 0
n_frames_per_sequence: int = -1
seed: int = 0
remove_empty_masks_poll_whole_table_threshold: int = 300_000
# we set it manually in the constructor
# _index: pd.DataFrame = field(init=False)
frame_data_builder: FrameDataBuilderBase
frame_data_builder_class_type: str = "FrameDataBuilder"
def __post_init__(self) -> None:
if sa.__version__ < "2.0":
raise ImportError("This class requires SQL Alchemy 2.0 or later")
if not self.sqlite_metadata_file:
raise ValueError("sqlite_metadata_file must be set")
if self.dataset_root:
frame_builder_type = self.frame_data_builder_class_type
getattr(self, f"frame_data_builder_{frame_builder_type}_args")[
"dataset_root"
] = self.dataset_root
run_auto_creation(self)
self.frame_data_builder.path_manager = self.path_manager
# pyre-ignore # NOTE: sqlite-specific args (read-only mode).
self._sql_engine = sa.create_engine(
f"sqlite:///file:{self.sqlite_metadata_file}?mode=ro&uri=true"
)
sequences = self._get_filtered_sequences_if_any()
if self.subsets:
index = self._build_index_from_subset_lists(sequences)
else:
# TODO: if self.subset_lists_file and not self.subsets, it might be faster to
# still use the concatenated lists, assuming they cover the whole dataset
index = self._build_index_from_db(sequences)
if self.n_frames_per_sequence >= 0:
index = self._stratified_sample_index(index)
if len(index) == 0:
raise ValueError(f"There are no frames in the subsets: {self.subsets}!")
self._index = index.set_index(["sequence_name", "frame_number"]) # pyre-ignore
self.eval_batches = None # pyre-ignore
if self.eval_batches_file:
self.eval_batches = self._load_filter_eval_batches()
logger.info(str(self))
def __len__(self) -> int:
# pyre-ignore[16]
return len(self._index)
def __getitem__(self, frame_idx: Union[int, Tuple[str, int]]) -> FrameData:
"""
Fetches FrameData by either iloc in the index or by (sequence, frame_no) pair
"""
return self._get_item(frame_idx, True)
@property
def meta(self):
"""
Allows accessing metadata only without loading blobs using `dataset.meta[idx]`.
Requires box_crop==False, since in that case, cameras cannot be adjusted
without loading masks.
Returns:
FrameData objects with blob fields like `image_rgb` set to None.
Raises:
ValueError if dataset.box_crop is set.
"""
return SqlIndexDataset._MetadataAccessor(self)
@dataclass
class _MetadataAccessor:
dataset: "SqlIndexDataset"
def __getitem__(self, frame_idx: Union[int, Tuple[str, int]]) -> FrameData:
return self.dataset._get_item(frame_idx, False)
def _get_item(
self, frame_idx: Union[int, Tuple[str, int]], load_blobs: bool = True
) -> FrameData:
if isinstance(frame_idx, int):
if frame_idx >= len(self._index):
raise IndexError(f"index {frame_idx} out of range {len(self._index)}")
seq, frame = self._index.index[frame_idx]
else:
seq, frame, *rest = frame_idx
if isinstance(frame, torch.LongTensor):
frame = frame.item()
if (seq, frame) not in self._index.index:
raise IndexError(
f"Sequence-frame index {frame_idx} not found; was it filtered out?"
)
if rest and rest[0] != self._index.loc[(seq, frame), "_image_path"]:
raise IndexError(f"Non-matching image path in {frame_idx}.")
stmt = sa.select(self.frame_annotations_type).where(
self.frame_annotations_type.sequence_name == seq,
self.frame_annotations_type.frame_number
== int(frame), # cast from np.int64
)
seq_stmt = sa.select(SqlSequenceAnnotation).where(
SqlSequenceAnnotation.sequence_name == seq
)
with Session(self._sql_engine) as session:
entry = session.scalars(stmt).one()
seq_metadata = session.scalars(seq_stmt).one()
assert entry.image.path == self._index.loc[(seq, frame), "_image_path"]
frame_data = self.frame_data_builder.build(
entry, seq_metadata, load_blobs=load_blobs
)
# The rest of the fields are optional
frame_data.frame_type = self._get_frame_type(entry)
return frame_data
def __str__(self) -> str:
# pyre-ignore[16]
return f"SqlIndexDataset #frames={len(self._index)}"
def sequence_names(self) -> Iterable[str]:
"""Returns an iterator over sequence names in the dataset."""
return self._index.index.unique("sequence_name")
# override
def category_to_sequence_names(self) -> Dict[str, List[str]]:
stmt = sa.select(
SqlSequenceAnnotation.category, SqlSequenceAnnotation.sequence_name
).where( # we limit results to sequences that have frames after all filters
SqlSequenceAnnotation.sequence_name.in_(self.sequence_names())
)
with self._sql_engine.connect() as connection:
cat_to_seqs = pd.read_sql(stmt, connection)
return cat_to_seqs.groupby("category")["sequence_name"].apply(list).to_dict()
# override
def get_frame_numbers_and_timestamps(
self, idxs: Sequence[int], subset_filter: Optional[Sequence[str]] = None
) -> List[Tuple[int, float]]:
"""
Implements the DatasetBase method.
NOTE: Avoid this function as there are more efficient alternatives such as
querying `dataset[idx]` directly or getting all sequence frames with
`sequence_[frames|indices]_in_order`.
Return the index and timestamp in their videos of the frames whose
indices are given in `idxs`. They need to belong to the same sequence!
If timestamps are absent, they are replaced with zeros.
This is used for letting SceneBatchSampler identify consecutive
frames.
Args:
idxs: a sequence int frame index in the dataset (it can be a slice)
subset_filter: must remain None
Returns:
list of tuples of
- frame index in video
- timestamp of frame in video, coalesced with 0s
Raises:
ValueError if idxs belong to more than one sequence.
"""
if subset_filter is not None:
raise NotImplementedError(
"Subset filters are not supported in SQL Dataset. "
"We encourage creating a dataset per subset."
)
index_slice, _ = self._get_frame_no_coalesced_ts_by_row_indices(idxs)
# alternatively, we can use `.values.tolist()`, which may be faster
# but returns a list of lists
return list(index_slice.itertuples())
# override
def sequence_frames_in_order(
self, seq_name: str, subset_filter: Optional[Sequence[str]] = None
) -> Iterator[Tuple[float, int, int]]:
"""
Overrides the default DatasetBase implementation (we dont use `_seq_to_idx`).
Returns an iterator over the frame indices in a given sequence.
We attempt to first sort by timestamp (if they are available),
then by frame number.
Args:
seq_name: the name of the sequence.
subset_filter: subset names to filter to
Returns:
an iterator over triplets `(timestamp, frame_no, dataset_idx)`,
where `frame_no` is the index within the sequence, and
`dataset_idx` is the index within the dataset.
`None` timestamps are replaced with 0s.
"""
# TODO: implement sort_timestamp_first? (which would matter if the orders
# of frame numbers and timestamps are different)
rows = self._index.index.get_loc(seq_name)
if isinstance(rows, slice):
assert rows.stop is not None, "Unexpected result from pandas"
rows = range(rows.start or 0, rows.stop, rows.step or 1)
else:
rows = np.where(rows)[0]
index_slice, idx = self._get_frame_no_coalesced_ts_by_row_indices(
rows, seq_name, subset_filter
)
index_slice["idx"] = idx
yield from index_slice.itertuples(index=False)
# override
def get_eval_batches(self) -> Optional[List[Any]]:
"""
This class does not support eval batches with ordinal indices. You can pass
eval_batches as a batch_sampler to a data_loader since the dataset supports
`dataset[seq_name, frame_no]` indexing.
"""
return self.eval_batches
# override
def join(self, other_datasets: Iterable[DatasetBase]) -> None:
raise ValueError("Not supported! Preprocess the data by merging them instead.")
# override
@property
def frame_data_type(self) -> Type[FrameData]:
return self.frame_data_builder.frame_data_type
def is_filtered(self) -> bool:
"""
Returns `True` in case the dataset has been filtered and thus some frame
annotations stored on the disk might be missing in the dataset object.
Does not account for subsets.
Returns:
is_filtered: `True` if the dataset has been filtered, else `False`.
"""
return (
self.remove_empty_masks
or self.limit_to > 0
or self.limit_sequences_to > 0
or self.limit_sequences_per_category_to > 0
or len(self.pick_sequences) > 0
or len(self.exclude_sequences) > 0
or len(self.pick_categories) > 0
or self.n_frames_per_sequence > 0
)
def _get_filtered_sequences_if_any(self) -> Optional[pd.Series]:
# maximum possible filter (if limit_sequences_per_category_to == 0):
# WHERE category IN 'self.pick_categories'
# AND sequence_name IN 'self.pick_sequences'
# AND sequence_name NOT IN 'self.exclude_sequences'
# LIMIT 'self.limit_sequence_to'
where_conditions = [
*self._get_category_filters(),
*self._get_pick_filters(),
*self._get_exclude_filters(),
]
def add_where(stmt):
return stmt.where(*where_conditions) if where_conditions else stmt
if self.limit_sequences_per_category_to <= 0:
stmt = add_where(sa.select(SqlSequenceAnnotation.sequence_name))
else:
subquery = sa.select(
SqlSequenceAnnotation.sequence_name,
sa.func.row_number()
.over(
order_by=sa.text("ROWID"), # NOTE: ROWID is SQLite-specific
partition_by=SqlSequenceAnnotation.category,
)
.label("row_number"),
)
subquery = add_where(subquery).subquery()
stmt = sa.select(subquery.c.sequence_name).where(
subquery.c.row_number <= self.limit_sequences_per_category_to
)
if self.limit_sequences_to > 0:
logger.info(
f"Limiting dataset to first {self.limit_sequences_to} sequences"
)
# NOTE: ROWID is SQLite-specific
stmt = stmt.order_by(sa.text("ROWID")).limit(self.limit_sequences_to)
if (
not where_conditions
and self.limit_sequences_to <= 0
and self.limit_sequences_per_category_to <= 0
):
# we will not need to filter by sequences
return None
with self._sql_engine.connect() as connection:
sequences = pd.read_sql_query(stmt, connection)["sequence_name"]
logger.info("... retained %d sequences" % len(sequences))
return sequences
def _get_category_filters(self) -> List[sa.ColumnElement]:
if not self.pick_categories:
return []
logger.info(f"Limiting dataset to categories: {self.pick_categories}")
return [SqlSequenceAnnotation.category.in_(self.pick_categories)]
def _get_pick_filters(self) -> List[sa.ColumnElement]:
if not self.pick_sequences:
return []
logger.info(f"Limiting dataset to sequences: {self.pick_sequences}")
return [SqlSequenceAnnotation.sequence_name.in_(self.pick_sequences)]
def _get_exclude_filters(self) -> List[sa.ColumnOperators]:
if not self.exclude_sequences:
return []
logger.info(f"Removing sequences from the dataset: {self.exclude_sequences}")
return [SqlSequenceAnnotation.sequence_name.notin_(self.exclude_sequences)]
def _load_subsets_from_json(self, subset_lists_path: str) -> pd.DataFrame:
assert self.subsets is not None
with open(subset_lists_path, "r") as f:
subset_to_seq_frame = json.load(f)
seq_frame_list = sum(
(
[(*row, subset) for row in subset_to_seq_frame[subset]]
for subset in self.subsets
),
[],
)
index = pd.DataFrame(
seq_frame_list,
columns=["sequence_name", "frame_number", "_image_path", "subset"],
)
return index
def _load_subsets_from_sql(self, subset_lists_path: str) -> pd.DataFrame:
subsets = self.subsets
assert subsets is not None
# we need a new engine since we store the subsets in a separate DB
engine = sa.create_engine(f"sqlite:///{subset_lists_path}")
table = sa.Table(_SET_LISTS_TABLE, sa.MetaData(), autoload_with=engine)
stmt = sa.select(table).where(table.c.subset.in_(subsets))
with engine.connect() as connection:
index = pd.read_sql(stmt, connection)
return index
def _build_index_from_subset_lists(
self, sequences: Optional[pd.Series]
) -> pd.DataFrame:
if not self.subset_lists_file:
raise ValueError("Requested subsets but subset_lists_file not given")
logger.info(f"Loading subset lists from {self.subset_lists_file}.")
subset_lists_path = self._local_path(self.subset_lists_file)
if subset_lists_path.lower().endswith(".json"):
index = self._load_subsets_from_json(subset_lists_path)
else:
index = self._load_subsets_from_sql(subset_lists_path)
index = index.set_index(["sequence_name", "frame_number"])
logger.info(f" -> loaded {len(index)} samples of {self.subsets}.")
if sequences is not None:
logger.info("Applying filtered sequences.")
sequence_values = index.index.get_level_values("sequence_name")
index = index.loc[sequence_values.isin(sequences)]
logger.info(f" -> retained {len(index)} samples.")
pick_frames_criteria = []
if self.remove_empty_masks:
logger.info("Culling samples with empty masks.")
if len(index) > self.remove_empty_masks_poll_whole_table_threshold:
# APPROACH 1: find empty masks and drop indices.
# dev load: 17s / 15 s (3.1M / 500K)
stmt = sa.select(
self.frame_annotations_type.sequence_name,
self.frame_annotations_type.frame_number,
).where(self.frame_annotations_type._mask_mass == 0)
with Session(self._sql_engine) as session:
to_remove = session.execute(stmt).all()
# Pandas uses np.int64 for integer types, so we have to case
# we might want to read it to pandas DataFrame directly to avoid the loop
to_remove = [(seq, np.int64(fr)) for seq, fr in to_remove]
index.drop(to_remove, errors="ignore", inplace=True)
else:
# APPROACH 3: load index into a temp table and join with annotations
# dev load: 94 s / 23 s (3.1M / 500K)
pick_frames_criteria.append(
sa.or_(
self.frame_annotations_type._mask_mass.is_(None),
self.frame_annotations_type._mask_mass != 0,
)
)
if self.pick_frames_sql_clause:
logger.info("Applying the custom SQL clause.")
pick_frames_criteria.append(sa.text(self.pick_frames_sql_clause))
if pick_frames_criteria:
index = self._pick_frames_by_criteria(index, pick_frames_criteria)
logger.info(f" -> retained {len(index)} samples.")
if self.limit_to > 0:
logger.info(f"Limiting dataset to first {self.limit_to} frames")
index = index.sort_index().iloc[: self.limit_to]
return index.reset_index()
def _pick_frames_by_criteria(self, index: pd.DataFrame, criteria) -> pd.DataFrame:
IndexTable = self._get_temp_index_table_instance()
with self._sql_engine.connect() as connection:
IndexTable.create(connection)
# we dont let pandass `to_sql` create the table automatically as
# the table would be permanent, so we create it and append with pandas
n_rows = index.to_sql(IndexTable.name, connection, if_exists="append")
assert n_rows == len(index)
sa_type = self.frame_annotations_type
stmt = (
sa.select(IndexTable)
.select_from(
IndexTable.join(
self.frame_annotations_type,
sa.and_(
sa_type.sequence_name == IndexTable.c.sequence_name,
sa_type.frame_number == IndexTable.c.frame_number,
),
)
)
.where(*criteria)
)
return pd.read_sql_query(stmt, connection).set_index(
["sequence_name", "frame_number"]
)
def _build_index_from_db(self, sequences: Optional[pd.Series]):
logger.info("Loading sequcence-frame index from the database")
stmt = sa.select(
self.frame_annotations_type.sequence_name,
self.frame_annotations_type.frame_number,
self.frame_annotations_type._image_path,
sa.null().label("subset"),
)
where_conditions = []
if sequences is not None:
logger.info(" applying filtered sequences")
where_conditions.append(
self.frame_annotations_type.sequence_name.in_(sequences.tolist())
)
if self.remove_empty_masks:
logger.info(" excluding samples with empty masks")
where_conditions.append(
sa.or_(
self.frame_annotations_type._mask_mass.is_(None),
self.frame_annotations_type._mask_mass != 0,
)
)
if self.pick_frames_sql_clause:
logger.info(" applying custom SQL clause")
where_conditions.append(sa.text(self.pick_frames_sql_clause))
if where_conditions:
stmt = stmt.where(*where_conditions)
if self.limit_to > 0:
logger.info(f"Limiting dataset to first {self.limit_to} frames")
stmt = stmt.order_by(
self.frame_annotations_type.sequence_name,
self.frame_annotations_type.frame_number,
).limit(self.limit_to)
with self._sql_engine.connect() as connection:
index = pd.read_sql_query(stmt, connection)
logger.info(f" -> loaded {len(index)} samples.")
return index
def _sort_index_(self, index):
logger.info("Sorting the index by sequence and frame number.")
index.sort_values(["sequence_name", "frame_number"], inplace=True)
logger.info(" -> Done.")
def _load_filter_eval_batches(self):
assert self.eval_batches_file
logger.info(f"Loading eval batches from {self.eval_batches_file}")
if not os.path.isfile(self.eval_batches_file):
# The batch indices file does not exist.
# Most probably the user has not specified the root folder.
raise ValueError(
f"Looking for dataset json file in {self.eval_batches_file}. "
+ "Please specify a correct dataset_root folder."
)
with open(self.eval_batches_file, "r") as f:
eval_batches = json.load(f)
# limit the dataset to sequences to allow multiple evaluations in one file
pick_sequences = set(self.pick_sequences)
if self.pick_categories:
cat_to_seq = self.category_to_sequence_names()
pick_sequences.update(
seq for cat in self.pick_categories for seq in cat_to_seq[cat]
)
if pick_sequences:
old_len = len(eval_batches)
eval_batches = [b for b in eval_batches if b[0][0] in pick_sequences]
logger.warn(
f"Picked eval batches by sequence/cat: {old_len} -> {len(eval_batches)}"
)
if self.exclude_sequences:
old_len = len(eval_batches)
exclude_sequences = set(self.exclude_sequences)
eval_batches = [b for b in eval_batches if b[0][0] not in exclude_sequences]
logger.warn(
f"Excluded eval batches by sequence: {old_len} -> {len(eval_batches)}"
)
return eval_batches
def _stratified_sample_index(self, index):
# NOTE this stratified sampling can be done more efficiently in
# the no-subset case above if it is added to the SQL query.
# We keep this generic implementation since no-subset case is uncommon
index = index.groupby("sequence_name", group_keys=False).apply(
lambda seq_frames: seq_frames.sample(
min(len(seq_frames), self.n_frames_per_sequence),
random_state=(
_seq_name_to_seed(seq_frames.iloc[0]["sequence_name"]) + self.seed
),
)
)
logger.info(f" -> retained {len(index)} samples aster stratified sampling.")
return index
def _get_frame_type(self, entry: SqlFrameAnnotation) -> Optional[str]:
return self._index.loc[(entry.sequence_name, entry.frame_number), "subset"]
def _get_frame_no_coalesced_ts_by_row_indices(
self,
idxs: Sequence[int],
seq_name: Optional[str] = None,
subset_filter: Union[Sequence[str], str, None] = None,
) -> Tuple[pd.DataFrame, Sequence[int]]:
"""
Loads timestamps for given index rows belonging to the same sequence.
If seq_name is known, it speeds up the computation.
Raises ValueError if `idxs` do not all belong to a single sequences .
"""
index_slice = self._index.iloc[idxs]
if subset_filter is not None:
if isinstance(subset_filter, str):
subset_filter = [subset_filter]
indicator = index_slice["subset"].isin(subset_filter)
index_slice = index_slice.loc[indicator]
idxs = [i for i, isin in zip(idxs, indicator) if isin]
frames = index_slice.index.get_level_values("frame_number").tolist()
if seq_name is None:
seq_name_list = index_slice.index.get_level_values("sequence_name").tolist()
seq_name_set = set(seq_name_list)
if len(seq_name_set) > 1:
raise ValueError("Given indices belong to more than one sequence.")
elif len(seq_name_set) == 1:
seq_name = seq_name_list[0]
coalesced_ts = sa.sql.functions.coalesce(
self.frame_annotations_type.frame_timestamp, 0
)
stmt = sa.select(
coalesced_ts.label("frame_timestamp"),
self.frame_annotations_type.frame_number,
).where(
self.frame_annotations_type.sequence_name == seq_name,
self.frame_annotations_type.frame_number.in_(frames),
)
with self._sql_engine.connect() as connection:
frame_no_ts = pd.read_sql_query(stmt, connection)
if len(frame_no_ts) != len(index_slice):
raise ValueError(
"Not all indices are found in the database; "
"do they belong to more than one sequence?"
)
return frame_no_ts, idxs
def _local_path(self, path: str) -> str:
if self.path_manager is None:
return path
return self.path_manager.get_local_path(path)
def _get_temp_index_table_instance(self, table_name: str = "__index"):
CachedTable = self.frame_annotations_type.metadata.tables.get(table_name)
if CachedTable is not None: # table definition is not idempotent
return CachedTable
return sa.Table(
table_name,
self.frame_annotations_type.metadata,
sa.Column("sequence_name", sa.String, primary_key=True),
sa.Column("frame_number", sa.Integer, primary_key=True),
sa.Column("_image_path", sa.String),
sa.Column("subset", sa.String),
prefixes=["TEMP"], # NOTE SQLite specific!
)
def _seq_name_to_seed(seq_name) -> int:
"""Generates numbers in [0, 2 ** 28)"""
return int(hashlib.sha1(seq_name.encode("utf-8")).hexdigest()[:7], 16)
def _safe_as_tensor(data, dtype):
return torch.tensor(data, dtype=dtype) if data is not None else None

View File

@@ -0,0 +1,424 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
import logging
import os
from typing import List, Optional, Tuple, Type
import numpy as np
from omegaconf import DictConfig, OmegaConf
from pytorch3d.implicitron.dataset.dataset_map_provider import (
DatasetMap,
DatasetMapProviderBase,
PathManagerFactory,
)
from pytorch3d.implicitron.tools.config import (
expand_args_fields,
registry,
run_auto_creation,
)
from .sql_dataset import SqlIndexDataset
_CO3D_SQL_DATASET_ROOT: str = os.getenv("CO3D_SQL_DATASET_ROOT", "")
# _NEED_CONTROL is a list of those elements of SqlIndexDataset which
# are not directly specified for it in the config but come from the
# DatasetMapProvider.
_NEED_CONTROL: Tuple[str, ...] = (
"path_manager",
"subsets",
"sqlite_metadata_file",
"subset_lists_file",
)
logger = logging.getLogger(__name__)
@registry.register
class SqlIndexDatasetMapProvider(DatasetMapProviderBase): # pyre-ignore [13]
"""
Generates the training, validation, and testing dataset objects for
a dataset laid out on disk like SQL-CO3D, with annotations in an SQLite data base.
The dataset is organized in the filesystem as follows::
self.dataset_root
├── <possible/partition/0>
│ ├── <sequence_name_0>
│ │ ├── depth_masks
│ │ ├── depths
│ │ ├── images
│ │ ├── masks
│ │ └── pointcloud.ply
│ ├── <sequence_name_1>
│ │ ├── depth_masks
│ │ ├── depths
│ │ ├── images
│ │ ├── masks
│ │ └── pointcloud.ply
│ ├── ...
│ ├── <sequence_name_N>
│ ├── set_lists
│ ├── <subset_base_name_0>.json
│ ├── <subset_base_name_1>.json
│ ├── ...
│ ├── <subset_base_name_2>.json
│ ├── eval_batches
│ │ ├── <eval_batches_base_name_0>.json
│ │ ├── <eval_batches_base_name_1>.json
│ │ ├── ...
│ │ ├── <eval_batches_base_name_M>.json
│ ├── frame_annotations.jgz
│ ├── sequence_annotations.jgz
├── <possible/partition/1>
├── ...
├── <possible/partition/K>
├── set_lists
├── <subset_base_name_0>.sqlite
├── <subset_base_name_1>.sqlite
├── ...
├── <subset_base_name_2>.sqlite
├── eval_batches
│ ├── <eval_batches_base_name_0>.json
│ ├── <eval_batches_base_name_1>.json
│ ├── ...
│ ├── <eval_batches_base_name_M>.json
The dataset contains sequences named `<sequence_name_i>` that may be partitioned by
directories such as `<possible/partition/0>` e.g. representing categories but they
can also be stored in a flat structure. Each sequence folder contains the list of
sequence images, depth maps, foreground masks, and valid-depth masks
`images`, `depths`, `masks`, and `depth_masks` respectively. Furthermore,
`set_lists/` dirtectories (with partitions or global) store json or sqlite files
`<subset_base_name_l>.<ext>`, each describing a certain sequence subset.
These subset path conventions are not hard-coded and arbitrary relative path can be
specified by setting `self.subset_lists_path` to the relative path w.r.t.
dataset root.
Each `<subset_base_name_l>.json` file contains the following dictionary::
{
"train": [
(sequence_name: str, frame_number: int, image_path: str),
...
],
"val": [
(sequence_name: str, frame_number: int, image_path: str),
...
],
"test": [
(sequence_name: str, frame_number: int, image_path: str),
...
],
]
defining the list of frames (identified with their `sequence_name` and
`frame_number`) in the "train", "val", and "test" subsets of the dataset. In case of
SQLite format, `<subset_base_name_l>.sqlite` contains a table with the header::
| sequence_name | frame_number | image_path | subset |
Note that `frame_number` can be obtained only from the metadata and
does not necesarrily correspond to the numeric suffix of the corresponding image
file name (e.g. a file `<partition_0>/<sequence_name_0>/images/frame00005.jpg` can
have its frame number set to `20`, not 5).
Each `<eval_batches_base_name_M>.json` file contains a list of evaluation examples
in the following form::
[
[ # batch 1
(sequence_name: str, frame_number: int, image_path: str),
...
],
[ # batch 2
(sequence_name: str, frame_number: int, image_path: str),
...
],
]
Note that the evaluation examples always come from the `"test"` subset of the dataset.
(test frames can repeat across batches). The batches can contain single element,
which is typical in case of regular radiance field fitting.
Args:
subset_lists_path: The relative path to the dataset subset definition.
For CO3D, these include e.g. "skateboard/set_lists/set_lists_manyview_dev_0.json".
By default (None), dataset is not partitioned to subsets (in that case, setting
`ignore_subsets` will speed up construction)
dataset_root: The root folder of the dataset.
metadata_basename: name of the SQL metadata file in dataset_root;
not expected to be changed by users
test_on_train: Construct validation and test datasets from
the training subset; note that in practice, in this
case all subset dataset objects will be same
only_test_set: Load only the test set. Incompatible with `test_on_train`.
ignore_subsets: Dont filter by subsets in the dataset; note that in this
case all subset datasets will be same
eval_batch_num_training_frames: Add a certain number of training frames to each
eval batch. Useful for evaluating models that require
source views as input (e.g. NeRF-WCE / PixelNeRF).
dataset_args: Specifies additional arguments to the
JsonIndexDataset constructor call.
path_manager_factory: (Optional) An object that generates an instance of
PathManager that can translate provided file paths.
path_manager_factory_class_type: The class type of `path_manager_factory`.
"""
category: Optional[str] = None
subset_list_name: Optional[str] = None # TODO: docs
# OR
subset_lists_path: Optional[str] = None
eval_batches_path: Optional[str] = None
dataset_root: str = _CO3D_SQL_DATASET_ROOT
metadata_basename: str = "metadata.sqlite"
test_on_train: bool = False
only_test_set: bool = False
ignore_subsets: bool = False
train_subsets: Tuple[str, ...] = ("train",)
val_subsets: Tuple[str, ...] = ("val",)
test_subsets: Tuple[str, ...] = ("test",)
eval_batch_num_training_frames: int = 0
# this is a mould that is never constructed, used to build self._dataset_map values
dataset_class_type: str = "SqlIndexDataset"
dataset: SqlIndexDataset
path_manager_factory: PathManagerFactory
path_manager_factory_class_type: str = "PathManagerFactory"
def __post_init__(self):
super().__init__()
run_auto_creation(self)
if self.only_test_set and self.test_on_train:
raise ValueError("Cannot have only_test_set and test_on_train")
if self.ignore_subsets and not self.only_test_set:
self.test_on_train = True # no point in loading same data 3 times
path_manager = self.path_manager_factory.get()
sqlite_metadata_file = os.path.join(self.dataset_root, self.metadata_basename)
sqlite_metadata_file = _local_path(path_manager, sqlite_metadata_file)
if not os.path.isfile(sqlite_metadata_file):
# The sqlite_metadata_file does not exist.
# Most probably the user has not specified the root folder.
raise ValueError(
f"Looking for frame annotations in {sqlite_metadata_file}."
+ " Please specify a correct dataset_root folder."
+ " Note: By default the root folder is taken from the"
+ " CO3D_SQL_DATASET_ROOT environment variable."
)
if self.subset_lists_path and self.subset_list_name:
raise ValueError(
"subset_lists_path and subset_list_name cannot be both set"
)
subset_lists_file = self._get_lists_file("set_lists")
# setup the common dataset arguments
common_dataset_kwargs = {
**getattr(self, f"dataset_{self.dataset_class_type}_args"),
"sqlite_metadata_file": sqlite_metadata_file,
"dataset_root": self.dataset_root,
"subset_lists_file": subset_lists_file,
"path_manager": path_manager,
}
if self.category:
logger.info(f"Forcing category filter in the datasets to {self.category}")
common_dataset_kwargs["pick_categories"] = self.category.split(",")
# get the used dataset type
dataset_type: Type[SqlIndexDataset] = registry.get(
SqlIndexDataset, self.dataset_class_type
)
expand_args_fields(dataset_type)
if subset_lists_file is not None and not os.path.isfile(subset_lists_file):
available_subsets = self._get_available_subsets(
OmegaConf.to_object(common_dataset_kwargs["pick_categories"])
)
msg = f"Cannot find subset list file {self.subset_lists_path}."
if available_subsets:
msg += f" Some of the available subsets: {str(available_subsets)}."
raise ValueError(msg)
train_dataset = None
val_dataset = None
if not self.only_test_set:
# load the training set
logger.debug("Constructing train dataset.")
train_dataset = dataset_type(
**common_dataset_kwargs, subsets=self._get_subsets(self.train_subsets)
)
logger.info(f"Train dataset: {str(train_dataset)}")
if self.test_on_train:
assert train_dataset is not None
val_dataset = test_dataset = train_dataset
else:
# load the val and test sets
if not self.only_test_set:
# NOTE: this is always loaded in JsonProviderV2
logger.debug("Extracting val dataset.")
val_dataset = dataset_type(
**common_dataset_kwargs, subsets=self._get_subsets(self.val_subsets)
)
logger.info(f"Val dataset: {str(val_dataset)}")
logger.debug("Extracting test dataset.")
eval_batches_file = self._get_lists_file("eval_batches")
del common_dataset_kwargs["eval_batches_file"]
test_dataset = dataset_type(
**common_dataset_kwargs,
subsets=self._get_subsets(self.test_subsets, True),
eval_batches_file=eval_batches_file,
)
logger.info(f"Test dataset: {str(test_dataset)}")
if (
eval_batches_file is not None
and self.eval_batch_num_training_frames > 0
):
self._extend_eval_batches(test_dataset)
self._dataset_map = DatasetMap(
train=train_dataset, val=val_dataset, test=test_dataset
)
def _get_subsets(self, subsets, is_eval: bool = False):
if self.ignore_subsets:
return None
if is_eval and self.eval_batch_num_training_frames > 0:
# we will need to have training frames for extended batches
return list(subsets) + list(self.train_subsets)
return subsets
def _extend_eval_batches(self, test_dataset: SqlIndexDataset) -> None:
rng = np.random.default_rng(seed=0)
eval_batches = test_dataset.get_eval_batches()
if eval_batches is None:
raise ValueError("Eval batches were not loaded!")
for batch in eval_batches:
sequence = batch[0][0]
seq_frames = list(
test_dataset.sequence_frames_in_order(sequence, self.train_subsets)
)
idx_to_add = rng.permutation(len(seq_frames))[
: self.eval_batch_num_training_frames
]
batch.extend((sequence, seq_frames[a][1]) for a in idx_to_add)
@classmethod
def dataset_tweak_args(cls, type, args: DictConfig) -> None:
"""
Called by get_default_args.
Certain fields are not exposed on each dataset class
but rather are controlled by this provider class.
"""
for key in _NEED_CONTROL:
del args[key]
def create_dataset(self):
# No `dataset` member of this class is created.
# The dataset(s) live in `self.get_dataset_map`.
pass
def get_dataset_map(self) -> DatasetMap:
return self._dataset_map # pyre-ignore [16]
def _get_available_subsets(self, categories: List[str]):
"""
Get the available subset names for a given category folder (if given) inside
a root dataset folder `dataset_root`.
"""
path_manager = self.path_manager_factory.get()
subsets: List[str] = []
for prefix in [""] + categories:
set_list_dir = os.path.join(self.dataset_root, prefix, "set_lists")
if not (
(path_manager is not None) and path_manager.isdir(set_list_dir)
) and not os.path.isdir(set_list_dir):
continue
set_list_files = (os.listdir if path_manager is None else path_manager.ls)(
set_list_dir
)
subsets.extend(os.path.join(prefix, "set_lists", f) for f in set_list_files)
return subsets
def _get_lists_file(self, flavor: str) -> Optional[str]:
if flavor == "eval_batches":
subset_lists_path = self.eval_batches_path
else:
subset_lists_path = self.subset_lists_path
if not subset_lists_path and not self.subset_list_name:
return None
category_elem = ""
if self.category and "," not in self.category:
# if multiple categories are given, looking for global set lists
category_elem = self.category
subset_lists_path = subset_lists_path or (
os.path.join(
category_elem, f"{flavor}", f"{flavor}_{self.subset_list_name}"
)
)
assert subset_lists_path
path_manager = self.path_manager_factory.get()
# try absolute path first
subset_lists_file = _get_local_path_check_extensions(
subset_lists_path, path_manager
)
if subset_lists_file:
return subset_lists_file
full_path = os.path.join(self.dataset_root, subset_lists_path)
subset_lists_file = _get_local_path_check_extensions(full_path, path_manager)
if not subset_lists_file:
raise FileNotFoundError(
f"Subset lists path given but not found: {full_path}"
)
return subset_lists_file
def _get_local_path_check_extensions(
path, path_manager, extensions=("", ".sqlite", ".json")
) -> Optional[str]:
for ext in extensions:
local = _local_path(path_manager, path + ext)
if os.path.isfile(local):
return local
return None
def _local_path(path_manager, path: str) -> str:
if path_manager is None:
return path
return path_manager.get_local_path(path)

View File

@@ -0,0 +1,191 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
# pyre-unsafe
import logging
from typing import Any, Dict, Optional, Tuple
from pytorch3d.implicitron.dataset.data_loader_map_provider import (
DataLoaderMap,
SceneBatchSampler,
SequenceDataLoaderMapProvider,
)
from pytorch3d.implicitron.dataset.dataset_base import DatasetBase
from pytorch3d.implicitron.dataset.dataset_map_provider import DatasetMap
from pytorch3d.implicitron.dataset.frame_data import FrameData
from pytorch3d.implicitron.tools.config import registry, run_auto_creation
from torch.utils.data import DataLoader
logger = logging.getLogger(__name__)
# TODO: we can merge it with SequenceDataLoaderMapProvider in PyTorch3D
# and support both eval_batches protocols
@registry.register
class TrainEvalDataLoaderMapProvider(SequenceDataLoaderMapProvider):
"""
Implementation of DataLoaderMapProviderBase that may use internal eval batches for
the test dataset. In particular, if `eval_batches_relpath` is set, it loads
eval batches from that json file, otherwise test set is treated in the same way as
train and val, i.e. the parameters `dataset_length_test` and `test_conditioning_type`
are respected.
If conditioning is not required, then the batch size should
be set as 1, and most of the fields do not matter.
If conditioning is required, each batch will contain one main
frame first to predict and the, rest of the elements are for
conditioning.
If images_per_seq_options is left empty, the conditioning
frames are picked according to the conditioning type given.
This does not have regard to the order of frames in a
scene, or which frames belong to what scene.
If images_per_seq_options is given, then the conditioning types
must be SAME and the remaining fields are used.
Members:
batch_size: The size of the batch of the data loader.
num_workers: Number of data-loading threads in each data loader.
dataset_length_train: The number of batches in a training epoch. Or 0 to mean
an epoch is the length of the training set.
dataset_length_val: The number of batches in a validation epoch. Or 0 to mean
an epoch is the length of the validation set.
dataset_length_test: used if test_dataset.eval_batches is NOT set. The number of
batches in a testing epoch. Or 0 to mean an epoch is the length of the test
set.
images_per_seq_options: Possible numbers of frames sampled per sequence in a batch.
If a conditioning_type is KNOWN or TRAIN, then this must be left at its initial
value. Empty (the default) means that we are not careful about which frames
come from which scene.
sample_consecutive_frames: if True, will sample a contiguous interval of frames
in the sequence. It first sorts the frames by timestimps when available,
otherwise by frame numbers, finds the connected segments within the sequence
of sufficient length, then samples a random pivot element among them and
ideally uses it as a middle of the temporal window, shifting the borders
where necessary. This strategy mitigates the bias against shorter segments
and their boundaries.
consecutive_frames_max_gap: if a number > 0, then used to define the maximum
difference in frame_number of neighbouring frames when forming connected
segments; if both this and consecutive_frames_max_gap_seconds are 0s,
the whole sequence is considered a segment regardless of frame numbers.
consecutive_frames_max_gap_seconds: if a number > 0.0, then used to define the
maximum difference in frame_timestamp of neighbouring frames when forming
connected segments; if both this and consecutive_frames_max_gap are 0s,
the whole sequence is considered a segment regardless of frame timestamps.
"""
batch_size: int = 1
num_workers: int = 0
dataset_length_train: int = 0
dataset_length_val: int = 0
dataset_length_test: int = 0
images_per_seq_options: Tuple[int, ...] = ()
sample_consecutive_frames: bool = False
consecutive_frames_max_gap: int = 0
consecutive_frames_max_gap_seconds: float = 0.1
def __post_init__(self):
run_auto_creation(self)
def get_data_loader_map(self, datasets: DatasetMap) -> DataLoaderMap:
"""
Returns a collection of data loaders for a given collection of datasets.
"""
train = self._make_generic_data_loader(
datasets.train,
self.dataset_length_train,
datasets.train,
)
val = self._make_generic_data_loader(
datasets.val,
self.dataset_length_val,
datasets.train,
)
if datasets.test is not None and datasets.test.get_eval_batches() is not None:
test = self._make_eval_data_loader(datasets.test)
else:
test = self._make_generic_data_loader(
datasets.test,
self.dataset_length_test,
datasets.train,
)
return DataLoaderMap(train=train, val=val, test=test)
def _make_eval_data_loader(
self,
dataset: Optional[DatasetBase],
) -> Optional[DataLoader[FrameData]]:
if dataset is None:
return None
return DataLoader(
dataset,
batch_sampler=dataset.get_eval_batches(),
**self._get_data_loader_common_kwargs(dataset),
)
def _make_generic_data_loader(
self,
dataset: Optional[DatasetBase],
num_batches: int,
train_dataset: Optional[DatasetBase],
) -> Optional[DataLoader[FrameData]]:
"""
Returns the dataloader for a dataset.
Args:
dataset: the dataset
num_batches: possible ceiling on number of batches per epoch
train_dataset: the training dataset, used if conditioning_type==TRAIN
conditioning_type: source for padding of batches
"""
if dataset is None:
return None
data_loader_kwargs = self._get_data_loader_common_kwargs(dataset)
if len(self.images_per_seq_options) > 0:
# this is a typical few-view setup
# conditioning comes from the same subset since subsets are split by seqs
batch_sampler = SceneBatchSampler(
dataset,
self.batch_size,
num_batches=len(dataset) if num_batches <= 0 else num_batches,
images_per_seq_options=self.images_per_seq_options,
sample_consecutive_frames=self.sample_consecutive_frames,
consecutive_frames_max_gap=self.consecutive_frames_max_gap,
consecutive_frames_max_gap_seconds=self.consecutive_frames_max_gap_seconds,
)
return DataLoader(
dataset,
batch_sampler=batch_sampler,
**data_loader_kwargs,
)
if self.batch_size == 1:
# this is a typical many-view setup (without conditioning)
return self._simple_loader(dataset, num_batches, data_loader_kwargs)
# edge case: conditioning on train subset, typical for Nerformer-like many-view
# there is only one sequence in all datasets, so we condition on another subset
return self._train_loader(
dataset, train_dataset, num_batches, data_loader_kwargs
)
def _get_data_loader_common_kwargs(self, dataset: DatasetBase) -> Dict[str, Any]:
return {
"num_workers": self.num_workers,
"collate_fn": dataset.frame_data_type.collate,
}

Some files were not shown because too many files have changed in this diff Show More