Full Code of hustvl/TiNeuVox for AI

main d1f3adb67494 cached
31 files
67.7 KB
18.6k tokens
22 symbols
1 requests
Download .txt
Repository: hustvl/TiNeuVox
Branch: main
Commit: d1f3adb67494
Files: 31
Total size: 67.7 KB

Directory structure:
gitextract_12u6qfpa/

├── .gitignore
├── LICENSE
├── README.md
├── configs/
│   ├── misc/
│   │   ├── espresso.py
│   │   └── hyper_default.py
│   ├── nerf-base/
│   │   ├── bouncingballs.py
│   │   ├── default.py
│   │   ├── hellwarrior.py
│   │   ├── hook.py
│   │   ├── jumpingjacks.py
│   │   ├── lego.py
│   │   ├── mutant.py
│   │   ├── standup.py
│   │   └── trex.py
│   ├── nerf-small/
│   │   ├── bouncingballs.py
│   │   ├── default.py
│   │   ├── hellwarrior.py
│   │   ├── hook.py
│   │   ├── jumpingjacks.py
│   │   ├── lego.py
│   │   ├── mutant.py
│   │   ├── standup.py
│   │   └── trex.py
│   └── vrig_dataset/
│       ├── 3dprinter.py
│       ├── broom.py
│       ├── chicken.py
│       ├── hyper_default.py
│       └── peel-banana.py
├── metric.py
├── requirements.txt
└── run.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
# TiNeuVox: Time-Aware Neural Voxels
## ACM SIGGRAPH Asia 2022

### [Project Page](https://jaminfong.cn/tineuvox) | [ACM Paper](https://dl.acm.org/doi/10.1145/3550469.3555383) | [Arxiv Paper](https://arxiv.org/abs/2205.15285) | [Video](https://youtu.be/sROLfK_VkCk)

[Fast Dynamic Radiance Fields with Time-Aware Neural Voxels](https://jaminfong.cn/tineuvox)   
[Jiemin Fang](https://jaminfong.cn/)<sup>1,2*</sup>, [Taoran Yi](https://github.com/taoranyi)<sup>2*</sup>, [Xinggang Wang](https://xinggangw.info/)<sup>✉2</sup>, [Lingxi Xie](http://lingxixie.com/)<sup>3</sup>, </br>[Xiaopeng Zhang](https://sites.google.com/site/zxphistory/)<sup>3</sup>, [Wenyu Liu](http://eic.hust.edu.cn/professor/liuwenyu/)<sup>2</sup>, [Matthias Nießner](https://niessnerlab.org/members/matthias_niessner/profile.html)<sup>4</sup>, [Qi Tian](https://scholar.google.com/citations?hl=en&user=61b6eYkAAAAJ)<sup>3</sup>  
<sup>1</sup>Institute of AI, HUST &emsp; <sup>2</sup>School of EIC, HUST &emsp; <sup>3</sup>Huawei Cloud &emsp; <sup>4</sup>TUM

---------------------------------------------------
![block](./imgs/render_demo.gif)   
Our method converges very quickly. This is a comparison between D-NeRF (left) and our method (right). 

![block](./imgs/rep_img.jpg)
We propose a radiance field framework by representing scenes with time-aware voxel features, named as TiNeuVox. A tiny coordinate deformation network is introduced to model coarse motion trajectories and temporal information is further enhanced in the radiance network. A multi-distance interpolation method is proposed and applied on voxel features to model both small and large motions. Our framework significantly accelerates the optimization of dynamic radiance fields while maintaining high rendering quality. Empirical evaluation is performed on both syntheticand real scenes. Our TiNeuVox completes training with only **8 minutes** and **8-MB** storage cost while showing similar or even better rendering performance than previous dynamic NeRF methods.

## Notes
* *May. 31, 2022* The first and preliminary version is realeased. Code may not be cleaned thoroughly, so feel free to open an issue if any question.


## Requirements
* lpips
* mmcv
* imageio
* imageio-ffmpeg
* opencv-python
* pytorch_msssim
* torch
* torch_scatter

## Data Preparation
**For synthetic scenes:**  
The dataset provided in [D-NeRF](https://github.com/albertpumarola/D-NeRF) is used. You can download the dataset from [dropbox](https://www.dropbox.com/s/0bf6fl0ye2vz3vr/data.zip?dl=0). Then organize your dataset as follows.
```
├── data_dnerf 
│   ├── mutant
│   ├── standup 
│   ├── ...
```

**For real dynamic scenes:**  
The dataset provided in [HyperNeRF](https://github.com/google/hypernerf) is used. You can download scenes from [Hypernerf Dataset](https://github.com/google/hypernerf/releases/tag/v0.1) and organize them as [Nerfies](https://github.com/google/nerfies#datasets).



## Training
For training synthetic scenes such as `standup`, run 
``` 
python run.py --config configs/nerf-*/standup.py 
``` 
Use `small` for TiNeuVox-S and `base` for TiNeuVox-B.
Use `--render_video` to render a video.

For training real scenes such as `vrig_chicken`, run 
``` 
python run.py --config configs/vrig_dataset/chicken.py  
``` 

## Evaluation
Run the following script to evaluate the model.  

**For synthetic ones:**  
```
python run.py --config configs/nerf-small/standup.py --render_test --render_only --eval_psnr --eval_lpips_vgg --eval_ssim 
```

**For real ones:**  
```
python run.py --config configs/vrig_dataset/chicken.py --render_test --render_only --eval_psnr
```

To fairly compare with values reported in D-NeRF, `metric.py` is provided to directly evaluate the rendered images with `uint8` values.

## Main Results   
Please visit our [video](https://youtu.be/sROLfK_VkCk) for more rendered videos.

### Synthetic Scenes

| **Method** | **w/Time Enc.**  | **w/Explicit Rep.** |**Time** | **Storage** | **PSNR** | **SSIM** | **LPIPS** |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| NeRF | ✗ |✗ |∼ hours |5 MB |19.00 |0.87 |0.18
DirectVoxGO | ✗ |✓ |5 mins |205 MB |18.61| 0.85| 0.17
Plenoxels |✗ |✓ |6 mins| 717 MB |20.24 |0.87 |0.16
T-NeRF  |✓ |✗ |∼ hours |– |29.51 |0.95 |0.08
D-NeRF | ✓ |✗ |20 hours |4 MB |30.50 |0.95 |0.07
TiNeuVox-S (ours)| ✓ |✓ |8 mins |8 MB |30.75 |0.96 |0.07
TiNeuVox-B (ours)| ✓ |✓ |28 mins |48 MB |32.67 |0.97 |0.04

### Real Dynamic Scenes
| **Method** | **Time** | **PSNR** | **MS-SSIM** |
|:-:|:-:|:-:|:-:|
NeRF |∼ hours |20.1 |0.745
NV | ∼ hours |16.9 |0.571
NSFF | ∼ hours |26.3 |0.916
Nerfies | ∼ hours |22.2 |0.803
HyperNeRF | 32 hours |22.4 |0.814
TiNeuVox-S (ours) |10 mins |23.4 |0.813
TiNeuVox-B (ours) |30 mins |24.3 |0.837

## Acknowledgements
This repository is partially based on [DirectVoxGO](https://github.com/sunset1995/directvoxgo) and [D-NeRF](https://github.com/albertpumarola/D-NeRF). Thanks for their awesome works.


## Citation
If you find this repository/work helpful in your research, welcome to cite the paper and give a ⭐.
```
@inproceedings{TiNeuVox,
  author = {Fang, Jiemin and Yi, Taoran and Wang, Xinggang and Xie, Lingxi and Zhang, Xiaopeng and Liu, Wenyu and Nie\ss{}ner, Matthias and Tian, Qi},
  title = {Fast Dynamic Radiance Fields with Time-Aware Neural Voxels},
  year = {2022},
  booktitle = {SIGGRAPH Asia 2022 Conference Papers}
}
```


================================================
FILE: configs/misc/espresso.py
================================================
_base_ = './hyper_default.py'

expname = 'misc/espresso'
basedir = './logs/vrig_data'

data = dict(
    datadir='./espresso',
    dataset_type='hyper_dataset',
    white_bkgd=False,
)

================================================
FILE: configs/misc/hyper_default.py
================================================
from copy import deepcopy

expname = None                    # experiment name
basedir = './logs/'               # where to store ckpts and logs

''' Template of data options
'''
data = dict(
    datadir=None,                 # path to dataset root folder
    dataset_type=None,            
    load2gpu_on_the_fly=True,    # do not load all images into gpu (to save gpu memory)
    testskip=1,                   # subsample testset to preview results
    white_bkgd=False,             # use white background (note that some dataset don't provide alpha and with blended bg color)
    half_res=True,              
    factor=4,                     
    ndc=False,                    # use ndc coordinate (only for forward-facing; not support yet)
    spherify=False,               # inward-facing
    llffhold=8,                   # testsplit
    load_depths=False,            # load depth
    use_bg_points=True,
    add_cam=True,

)

''' Template of training options
'''
train_config = dict(
    N_iters=20000,                # number of optimization steps
    N_rand=4096,                  # batch size (number of random rays per optimization step)
    lrate_feature=1e-1,           # lr of voxel grid
    lrate_featurenet=1e-3,
    lrate_deformation_net=7e-4,
    lrate_densitynet=1e-3,
    lrate_timenet=1e-3,
    lrate_camnet=1e-3,
    lrate_rgbnet=1e-3,           # lr of the mlp 
    lrate_decay=20,               # lr decay by 0.1 after every lrate_decay*1000 steps
    ray_sampler='in_maskcache',        # ray sampling strategies
    weight_main=1.0,              # weight of photometric loss
    weight_entropy_last=0.001,
    weight_rgbper=0.01,            # weight of per-point rgb loss
    tv_every=1,                   # count total variation loss every tv_every step
    tv_after=0,                   # count total variation loss from tv_from step
    tv_before=1e9,                   # count total variation before the given number of iterations
    tv_feature_before=10000,            # count total variation densely before the given number of iterations
    weight_tv_feature=1e-5,
    pg_scale=[2000, 4000, 6000, 8000],
    skip_zero_grad_fields=['feature'],
)

''' Template of model and rendering options
'''

model_and_render = dict(
    num_voxels=160**3,          # expected number of voxel
    num_voxels_base=160**3,      # to rescale delta distance
    voxel_dim=6,                 # feature voxel grid dim
    defor_depth=3,               # depth of the deformation MLP 
    net_width=256,             # width of the  MLP
    alpha_init=1e-3,              # set the alpha values everywhere at the begin of training
    fast_color_thres=1e-4,           # threshold of alpha value to skip the fine stage sampled point
    stepsize=0.5,                 # sampling stepsize in volume rendering
    world_bound_scale=1.05,
)



del deepcopy


================================================
FILE: configs/nerf-base/bouncingballs.py
================================================
_base_ = './default.py'

expname = 'base/dnerf_bouncingballs-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/bouncingballs',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/nerf-base/default.py
================================================
from copy import deepcopy

expname = None                    # experiment name
basedir = './logs/'               # where to store ckpts and logs

''' Template of data options
'''
data = dict(
    datadir=None,                 # path to dataset root folder
    dataset_type=None,            
    load2gpu_on_the_fly=False,    # do not load all images into gpu (to save gpu memory)
    testskip=1,                   # subsample testset to preview results
    white_bkgd=False,             # use white background (note that some dataset don't provide alpha and with blended bg color)
    half_res=True,              
    factor=4,                     
    ndc=False,                    # use ndc coordinate (only for forward-facing; not support yet)
    spherify=False,               # inward-facing
    llffhold=8,                   # testsplit
    load_depths=False,            # load depth
    use_bg_points=False,
    add_cam=False,
)

''' Template of training options
'''
train_config = dict(
    N_iters=20000,                # number of optimization steps
    N_rand=4096,                  # batch size (number of random rays per optimization step)
    lrate_feature=8e-2,           # lr of  voxel grid
    lrate_featurenet=8e-4,
    lrate_deformation_net=6e-4,
    lrate_densitynet=8e-4,
    lrate_timenet=8e-4,
    lrate_rgbnet=8e-4,           # lr of the mlp  
    lrate_decay=20,               # lr decay by 0.1 after every lrate_decay*1000 steps
    ray_sampler='in_maskcache',        # ray sampling strategies
    weight_main=1.0,              # weight of photometric loss
    weight_entropy_last=0.001,
    weight_rgbper=0.01,            # weight of per-point rgb loss
    tv_every=1,                   # count total variation loss every tv_every step
    tv_after=0,                   # count total variation loss from tv_from step
    tv_before=1e9,                   # count total variation before the given number of iterations
    tv_feature_before=10000,            # count total variation densely before the given number of iterations
    weight_tv_feature=0,
    pg_scale=[2000, 4000, 6000],
    skip_zero_grad_fields=['feature'],
)

''' Template of model and rendering options
'''

model_and_render = dict(
    num_voxels=160**3,          # expected number of voxel
    num_voxels_base=160**3,      # to rescale delta distance
    voxel_dim=6,                 # feature voxel grid dim
    defor_depth=3,               # depth of the deformation MLP 
    net_width=256,             # width of the  MLP
    alpha_init=1e-3,              # set the alpha values everywhere at the begin of training
    fast_color_thres=1e-4,           # threshold of alpha value to skip the fine stage sampled point
    stepsize=0.5,                 # sampling stepsize in volume rendering
    world_bound_scale=1.05,
)



del deepcopy


================================================
FILE: configs/nerf-base/hellwarrior.py
================================================
_base_ = './default.py'

expname = 'base/dnerf_hellwarrior-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/hellwarrior',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/nerf-base/hook.py
================================================
_base_ = './default.py'

expname = 'base/dnerf_hook-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/hook',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/nerf-base/jumpingjacks.py
================================================
_base_ = './default.py'

expname = 'base/dnerf_jumpingjacks-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/jumpingjacks',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/nerf-base/lego.py
================================================
_base_ = './default.py'

expname = 'base/dnerf_lego-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/lego',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/nerf-base/mutant.py
================================================
_base_ = './default.py'

expname = 'base/dnerf_mutant-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/mutant',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/nerf-base/standup.py
================================================
_base_ = './default.py'

expname = 'base/dnerf_standup-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/standup',
    dataset_type='dnerf',
    white_bkgd=True,
)

================================================
FILE: configs/nerf-base/trex.py
================================================
_base_ = './default.py'

expname = 'base/dnerf_trex-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/trex',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/nerf-small/bouncingballs.py
================================================
_base_ = './default.py'

expname = 'small/dnerf_bouncingballs-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/bouncingballs',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/nerf-small/default.py
================================================
from copy import deepcopy

expname = None                    # experiment name
basedir = './logs/'               # where to store ckpts and logs

''' Template of data options
'''
data = dict(
    datadir=None,                 # path to dataset root folder
    dataset_type=None,            
    load2gpu_on_the_fly=False,    # do not load all images into gpu (to save gpu memory)
    testskip=1,                   # subsample testset to preview results
    white_bkgd=False,             # use white background (note that some dataset don't provide alpha and with blended bg color)
    half_res=True,              
    factor=4,                     
    ndc=False,                    # use ndc coordinate (only for forward-facing; not support yet)
    spherify=False,               # inward-facing
    llffhold=8,                   # testsplit
    load_depths=False,            # load depth
    use_bg_points=False,
    add_cam=False,
)

''' Template of training options
'''
train_config = dict(
    N_iters=20000,                # number of optimization steps
    N_rand=4096,                  # batch size (number of random rays per optimization step)
    lrate_feature=8e-2,           # lr of density voxel grid
    lrate_featurenet=8e-4,
    lrate_deformation_net=6e-4,
    lrate_densitynet=8e-4,
    lrate_timenet=8e-4,
    lrate_rgbnet=8e-4,           # lr of the mlp to preduct view-dependent color
    lrate_decay=20,               # lr decay by 0.1 after every lrate_decay*1000 steps
    ray_sampler='in_maskcache',        # ray sampling strategies
    weight_main=1.0,              # weight of photometric loss
    weight_entropy_last=0.001,
    weight_rgbper=0.01,            # weight of per-point rgb loss
    tv_every=1,                   # count total variation loss every tv_every step
    tv_after=0,                   # count total variation loss from tv_from step
    tv_before=1e9,                   # count total variation before the given number of iterations
    tv_feature_before=10000,            # count total variation densely before the given number of iterations
    weight_tv_feature=0,
    pg_scale=[2000, 4000, 6000],
    skip_zero_grad_fields=['feature'],
)

''' Template of model and rendering options
'''

model_and_render = dict(
    num_voxels=100**3,          # expected number of voxel
    num_voxels_base=100**3,      # to rescale delta distance
    voxel_dim=4,                 # feature voxel grid dim
    defor_depth=3,               # depth of the colors MLP (there are rgbnet_depth-1 intermediate features)
    net_width=64,             # width of the colors MLP
    alpha_init=1e-2,              # set the alpha values everywhere at the begin of training
    fast_color_thres=1e-4,           # threshold of alpha value to skip the fine stage sampled point
    stepsize=0.5,                 # sampling stepsize in volume rendering
    world_bound_scale=1.05,
)



del deepcopy


================================================
FILE: configs/nerf-small/hellwarrior.py
================================================
_base_ = './default.py'

expname = 'small/dnerf_hellwarrior-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/hellwarrior',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/nerf-small/hook.py
================================================
_base_ = './default.py'

expname = 'small/dnerf_hook-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/hook',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/nerf-small/jumpingjacks.py
================================================
_base_ = './default.py'

expname = 'small/dnerf_jumpingjacks-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/jumpingjacks',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/nerf-small/lego.py
================================================
_base_ = './default.py'

expname = 'small/dnerf_lego-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/lego',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/nerf-small/mutant.py
================================================
_base_ = './default.py'

expname = 'small/dnerf_mutant-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/mutant',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/nerf-small/standup.py
================================================
_base_ = './default.py'

expname = 'small/dnerf_standup-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/standup',
    dataset_type='dnerf',
    white_bkgd=True,
)

================================================
FILE: configs/nerf-small/trex.py
================================================
_base_ = './default.py'

expname = 'small/dnerf_trex-400'
basedir = './logs/nerf_synthetic'

data = dict(
    datadir='/data_dnerf/trex',
    dataset_type='dnerf',
    white_bkgd=True,
)



================================================
FILE: configs/vrig_dataset/3dprinter.py
================================================
_base_ = './hyper_default.py'

expname = 'vrig/base-3dprinter'
basedir = './logs/vrig_data'

data = dict(
    datadir='./vrig-3dprinter',
    dataset_type='hyper_dataset',
    white_bkgd=False,
)

================================================
FILE: configs/vrig_dataset/broom.py
================================================
_base_ = './hyper_default.py'

expname = 'vrig/base-broom'
basedir = './logs/vrig_data'

data = dict(
    datadir='./vrig_dataset/broom2',
    dataset_type='hyper_dataset',
    white_bkgd=False,
)

================================================
FILE: configs/vrig_dataset/chicken.py
================================================
_base_ = './hyper_default.py'

expname = 'vrig/base-chicken'
basedir = './logs/vrig_data'

data = dict(
    datadir='./vrig-chicken',
    dataset_type='hyper_dataset',
    white_bkgd=False,
)

================================================
FILE: configs/vrig_dataset/hyper_default.py
================================================
from copy import deepcopy

expname = None                    # experiment name
basedir = './logs/'               # where to store ckpts and logs

''' Template of data options
'''
data = dict(
    datadir=None,                 # path to dataset root folder
    dataset_type=None,            
    load2gpu_on_the_fly=True,    # do not load all images into gpu (to save gpu memory)
    testskip=1,                   # subsample testset to preview results
    white_bkgd=False,             # use white background (note that some dataset don't provide alpha and with blended bg color)
    half_res=True,              
    factor=4,                     
    ndc=False,                    # use ndc coordinate (only for forward-facing; not support yet)
    spherify=False,               # inward-facing
    llffhold=8,                   # testsplit
    load_depths=False,            # load depth
    use_bg_points=True,
    add_cam=True,

)

''' Template of training options
'''
train_config = dict(
    N_iters=20000,                # number of optimization steps
    N_rand=4096,                  # batch size (number of random rays per optimization step)
    lrate_feature=1e-1,           # lr of voxel grid
    lrate_featurenet=1e-3,
    lrate_deformation_net=7e-4,
    lrate_densitynet=1e-3,
    lrate_timenet=1e-3,
    lrate_camnet=1e-3,
    lrate_rgbnet=1e-3,           # lr of the mlp 
    lrate_decay=20,               # lr decay by 0.1 after every lrate_decay*1000 steps
    ray_sampler='in_maskcache',        # ray sampling strategies
    weight_main=1.0,              # weight of photometric loss
    weight_entropy_last=0.001,
    weight_rgbper=0.01,            # weight of per-point rgb loss
    tv_every=1,                   # count total variation loss every tv_every step
    tv_after=0,                   # count total variation loss from tv_from step
    tv_before=1e9,                   # count total variation before the given number of iterations
    tv_feature_before=10000,            # count total variation densely before the given number of iterations
    weight_tv_feature=1e-5,
    pg_scale=[2000, 4000, 6000, 8000],
    skip_zero_grad_fields=['feature'],
)

''' Template of model and rendering options
'''

model_and_render = dict(
    num_voxels=160**3,          # expected number of voxel
    num_voxels_base=160**3,      # to rescale delta distance
    voxel_dim=6,                 # feature voxel grid dim
    defor_depth=3,               # depth of the deformation MLP 
    net_width=256,             # width of the  MLP
    alpha_init=1e-3,              # set the alpha values everywhere at the begin of training
    fast_color_thres=1e-4,           # threshold of alpha value to skip the fine stage sampled point
    stepsize=0.5,                 # sampling stepsize in volume rendering
    world_bound_scale=1.05,
)



del deepcopy


================================================
FILE: configs/vrig_dataset/peel-banana.py
================================================
_base_ = './hyper_default.py'

expname = 'vrig/base-peel-banana'
basedir = './logs/vrig_data'

data = dict(
    datadir='./vrig-peel-banana',
    dataset_type='hyper_dataset',
    white_bkgd=False,
)

================================================
FILE: metric.py
================================================

import argparse
import math
import os

import imageio
import lpips
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F


# Mean Square Error
class MSE(object):
    def __call__(self, pred, gt):
        return torch.mean((pred - gt) ** 2)

# Peak Signal to Noise Ratio
class PSNR(object):
    def __call__(self, pred, gt):
        mse = torch.mean((pred - gt) ** 2)
        return 10 * torch.log10(1 / mse)


# structural similarity index
class SSIM(object):
    '''
    borrowed from https://github.com/huster-wgm/Pytorch-metrics/blob/master/metrics.py
    '''
    def gaussian(self, w_size, sigma):
        gauss = torch.Tensor([math.exp(-(x - w_size//2)**2/float(2*sigma**2)) for x in range(w_size)])
        return gauss/gauss.sum()

    def create_window(self, w_size, channel=1):
        _1D_window = self.gaussian(w_size, 1.5).unsqueeze(1)
        _2D_window = _1D_window.mm(_1D_window.t()).float().unsqueeze(0).unsqueeze(0)
        window = _2D_window.expand(channel, 1, w_size, w_size).contiguous()
        return window

    def __call__(self, y_pred, y_true, w_size=11, size_average=True, full=False):
        """
        args:
            y_true : 4-d ndarray in [batch_size, channels, img_rows, img_cols]
            y_pred : 4-d ndarray in [batch_size, channels, img_rows, img_cols]
            w_size : int, default 11
            size_average : boolean, default True
            full : boolean, default False
        return ssim, larger the better
        """
        # Value range can be different from 255. Other common ranges are 1 (sigmoid) and 2 (tanh).
        if torch.max(y_pred) > 128:
            max_val = 255
        else:
            max_val = 1

        if torch.min(y_pred) < -0.5:
            min_val = -1
        else:
            min_val = 0
        L = max_val - min_val

        padd = 0
        (_, channel, height, width) = y_pred.size()
        window = self.create_window(w_size, channel=channel).to(y_pred.device)

        mu1 = F.conv2d(y_pred, window, padding=padd, groups=channel)
        mu2 = F.conv2d(y_true, window, padding=padd, groups=channel)

        mu1_sq = mu1.pow(2)
        mu2_sq = mu2.pow(2)
        mu1_mu2 = mu1 * mu2

        sigma1_sq = F.conv2d(y_pred * y_pred, window, padding=padd, groups=channel) - mu1_sq
        sigma2_sq = F.conv2d(y_true * y_true, window, padding=padd, groups=channel) - mu2_sq
        sigma12 = F.conv2d(y_pred * y_true, window, padding=padd, groups=channel) - mu1_mu2

        C1 = (0.01 * L) ** 2
        C2 = (0.03 * L) ** 2

        v1 = 2.0 * sigma12 + C2
        v2 = sigma1_sq + sigma2_sq + C2
        cs = torch.mean(v1 / v2)  # contrast sensitivity

        ssim_map = ((2 * mu1_mu2 + C1) * v1) / ((mu1_sq + mu2_sq + C1) * v2)

        if size_average:
            ret = ssim_map.mean()
        else:
            ret = ssim_map.mean(1).mean(1).mean(1)

        if full:
            return ret, cs
        return ret



# Learned Perceptual Image Patch Similarity
class LPIPS(object):
    '''
    borrowed from https://github.com/huster-wgm/Pytorch-metrics/blob/master/metrics.py
    '''
    def __init__(self):
        self.model = lpips.LPIPS(net='vgg').cuda()

    def __call__(self, y_pred, y_true, normalized=True):
        """
        args:
            y_true : 4-d ndarray in [batch_size, channels, img_rows, img_cols]
            y_pred : 4-d ndarray in [batch_size, channels, img_rows, img_cols]
            normalized : change [0,1] => [-1,1] (default by LPIPS)
        return LPIPS, smaller the better
        """
        if normalized:
            y_pred = y_pred * 2.0 - 1.0
            y_true = y_true * 2.0 - 1.0
        error =  self.model.forward(y_pred, y_true)
        return torch.mean(error)


def read_images_in_dir(imgs_dir):
    imgs = []
    fnames = os.listdir(imgs_dir)
    fnames.sort()
    for fname in fnames:
        if fname.endswith(".mp4") == True:  # ignore canonical space, only evalute real scene
            continue
        if fname.endswith(".txt") == True:  # ignore canonical space, only evalute real scene
            continue

        img_path = os.path.join(imgs_dir, fname)
        # print(img_path)
        img = imageio.imread(img_path)
        img = (np.array(img) / 255.).astype(np.float32)
        img = np.transpose(img, (2, 0, 1))
        imgs.append(img)
    
    imgs = np.stack(imgs)       
    return imgs

def estim_error(estim, gt):
    errors = dict()
    metric = PSNR()
    errors["psnr"] = metric(estim, gt).item()
    metric = SSIM()
    errors["ssim"] = metric(estim, gt).item()
    metric = LPIPS()
    errors["lpips"] = metric(estim, gt).item()
    return errors


parser = argparse.ArgumentParser()
parser.add_argument('--estim_dir', type = str, default = None , help ='images path')
parser.add_argument('--gt_dir', type = str, default = None ,help ='GT path')
args = parser.parse_args()

psnr_cal = 0
ssim_cal = 0
lpips_cal = 0
scens = ['hellwarrior','mutant','hook','bouncingballs','lego','trex','standup','jumpingjacks']
for str in scens:
    estim_dir = args.estim_dir + '/dnerf_'+str+'-400/render_test_fine_last'
    gt_dir = args.gt_dir + '/'+str+'/renderonly_test_799999/gt'

    estim = read_images_in_dir(estim_dir)
    gt = read_images_in_dir(gt_dir)

    estim = torch.Tensor(estim).cuda()
    gt = torch.Tensor(gt).cuda()

    errors = estim_error(estim, gt)
    psnr_cal += errors["psnr"]
    ssim_cal += errors["ssim"]
    lpips_cal += errors["lpips"]
    print(str , errors)
print(psnr_cal/8 , ssim_cal/8 , lpips_cal/8)


================================================
FILE: requirements.txt
================================================
numpy
scipy
tqdm
lpips
mmcv
imageio
imageio-ffmpeg
opencv-python
pytorch_msssim
torch
torch_scatter
Pillow

================================================
FILE: run.py
================================================
import argparse
import copy
import os
import random
import time
from builtins import print

import imageio
import mmcv
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from pytorch_msssim import ms_ssim
from tqdm import tqdm, trange

from lib import tineuvox, utils
from lib.load_data import load_data


def config_parser():
    '''Define command line arguments
    '''
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('--config', required=True,
                        help='config file path')
    parser.add_argument("--seed", type=int, default=0,
                        help='Random seed')
    parser.add_argument("--ft_path", type=str, default='',
                        help='specific weights npy file to reload for coarse network')
    # testing options
    parser.add_argument("--render_only", action='store_true',
                        help='do not optimize, reload weights and render out render_poses path')
    parser.add_argument("--render_test", action='store_true')
    parser.add_argument("--render_train", action='store_true')
    parser.add_argument("--render_video", action='store_true')
    parser.add_argument("--render_video_factor", type=int, default=0,
                        help='downsampling factor to speed up rendering, set 4 or 8 for fast preview')
    parser.add_argument("--eval_ssim", action='store_true')
    parser.add_argument("--eval_lpips_alex", action='store_true')
    parser.add_argument("--eval_lpips_vgg", action='store_true')
    parser.add_argument("--eval_psnr", action='store_true')

    # logging/saving options
    parser.add_argument("--i_print",   type=int, default=2000,
                        help='frequency of console printout and metric loggin')
    parser.add_argument("--fre_test", type=int, default=30000,
                        help='frequency of test')
    parser.add_argument("--step_to_half", type=int, default=19000,
                        help='The iteration when fp32 becomes fp16')
    return parser

@torch.no_grad()
def render_viewpoints_hyper(model, data_class, ndc, render_kwargs, test=True, 
                                all=False, savedir=None, eval_psnr=False):
    
    rgbs = []
    rgbs_gt =[]
    rgbs_tensor =[]
    rgbs_gt_tensor =[]
    depths = []
    psnrs = []
    ms_ssims =[]

    if test:
        if all:
            idx = data_class.i_test
        else:
            idx = data_class.i_test[::16]
    else:
        if all:
            idx = data_class.i_train
        else:
            idx = data_class.i_train[::16]
    for i in tqdm(idx):
        rays_o, rays_d, viewdirs,rgb_gt = data_class.load_idx(i, not_dic=True)
        keys = ['rgb_marched', 'depth']
        time_one = data_class.all_time[i]*torch.ones_like(rays_o[:,0:1])
        cam_one = data_class.all_cam[i]*torch.ones_like(rays_o[:,0:1])
        bacth_size = 1000
        render_result_chunks = [
            {k: v for k, v in model(ro, rd, vd,ts, cams,**render_kwargs).items() if k in keys}
            for ro, rd, vd ,ts,cams in zip(rays_o.split(bacth_size, 0), rays_d.split(bacth_size, 0),
                                             viewdirs.split(bacth_size, 0),time_one.split(bacth_size, 0),cam_one.split(bacth_size, 0))
        ]
        render_result = {
            k: torch.cat([ret[k] for ret in render_result_chunks]).reshape(data_class.h,data_class.w,-1)
            for k in render_result_chunks[0].keys()
        }
        rgb_gt = rgb_gt.reshape(data_class.h,data_class.w,-1).cpu().numpy()
        rgb = render_result['rgb_marched'].cpu().numpy()
        depth = render_result['depth'].cpu().numpy()
        rgbs.append(rgb)
        depths.append(depth)
        rgbs_gt.append(rgb_gt)
        if eval_psnr:
            p = -10. * np.log10(np.mean(np.square(rgb - rgb_gt)))
            psnrs.append(p)
            rgbs_tensor.append(torch.from_numpy(np.clip(rgb,0,1)).reshape(-1,data_class.h,data_class.w))
            rgbs_gt_tensor.append(torch.from_numpy(np.clip(rgb_gt,0,1)).reshape(-1,data_class.h,data_class.w))
        if i==0:
            print('Testing', rgb.shape)
    if eval_psnr:
        rgbs_tensor = torch.stack(rgbs_tensor,0)
        rgbs_gt_tensor = torch.stack(rgbs_gt_tensor,0)
        ms_ssims = ms_ssim(rgbs_gt_tensor, rgbs_tensor, data_range=1, size_average=True )
    if len(psnrs):
        print('Testing psnr', np.mean(psnrs), '(avg)')
        print('Testing ms_ssims', ms_ssims, '(avg)')

    if savedir is not None:
        print(f'Writing images to {savedir}')
        for i in trange(len(rgbs)):
            rgb8 = utils.to8b(rgbs[i])
            filename = os.path.join(savedir, '{:03d}.png'.format(i))
            imageio.imwrite(filename, rgb8)
    rgbs = np.array(rgbs)
    depths = np.array(depths)
    return rgbs,depths


@torch.no_grad()
def render_viewpoints(model, render_poses, HW, Ks, ndc, render_kwargs,
                      gt_imgs=None, savedir=None, test_times=None, render_factor=0, eval_psnr=False,
                      eval_ssim=False, eval_lpips_alex=False, eval_lpips_vgg=False,):
    '''Render images for the given viewpoints; run evaluation if gt given.
    '''
    assert len(render_poses) == len(HW) and len(HW) == len(Ks)

    if render_factor!=0:
        HW = np.copy(HW)
        Ks = np.copy(Ks)
        HW //= render_factor
        Ks[:, :2, :3] //= render_factor
    rgbs = []
    depths = []
    psnrs = []
    ssims = []
    lpips_alex = []
    lpips_vgg = []

    for i, c2w in enumerate(tqdm(render_poses)):

        H, W = HW[i]
        K = Ks[i]
        rays_o, rays_d, viewdirs = tineuvox.get_rays_of_a_view(
                H, W, K, c2w, ndc)
        keys = ['rgb_marched', 'depth']
        rays_o = rays_o.flatten(0,-2)
        rays_d = rays_d.flatten(0,-2)
        viewdirs = viewdirs.flatten(0,-2)
        time_one = test_times[i]*torch.ones_like(rays_o[:,0:1])
        bacth_size=1000
        render_result_chunks = [
            {k: v for k, v in model(ro, rd, vd,ts, **render_kwargs).items() if k in keys}
            for ro, rd, vd ,ts in zip(rays_o.split(bacth_size, 0), rays_d.split(bacth_size, 0), viewdirs.split(bacth_size, 0),time_one.split(bacth_size, 0))
        ]
        render_result = {
            k: torch.cat([ret[k] for ret in render_result_chunks]).reshape(H,W,-1)
            for k in render_result_chunks[0].keys()
        }
        rgb = render_result['rgb_marched'].cpu().numpy()
        depth = render_result['depth'].cpu().numpy()

        rgbs.append(rgb)
        depths.append(depth)
        if i==0:
            print('Testing', rgb.shape)

        if gt_imgs is not None and render_factor == 0:
            if eval_psnr:
                p = -10. * np.log10(np.mean(np.square(rgb - gt_imgs[i])))
                psnrs.append(p)
            if eval_ssim:
                ssims.append(utils.rgb_ssim(rgb, gt_imgs[i], max_val=1))
            if eval_lpips_alex:
                lpips_alex.append(utils.rgb_lpips(rgb, gt_imgs[i], net_name = 'alex', device = c2w.device))
            if eval_lpips_vgg:
                lpips_vgg.append(utils.rgb_lpips(rgb, gt_imgs[i], net_name = 'vgg', device = c2w.device))

    if len(psnrs):
        if eval_psnr: print('Testing psnr', np.mean(psnrs), '(avg)')
        if eval_ssim: print('Testing ssim', np.mean(ssims), '(avg)')
        if eval_lpips_vgg: print('Testing lpips (vgg)', np.mean(lpips_vgg), '(avg)')
        if eval_lpips_alex: print('Testing lpips (alex)', np.mean(lpips_alex), '(avg)')

    if savedir is not None:
        print(f'Writing images to {savedir}')
        for i in trange(len(rgbs)):
            rgb8 = utils.to8b(rgbs[i])
            filename = os.path.join(savedir, '{:03d}.png'.format(i))
            imageio.imwrite(filename, rgb8)

    rgbs = np.array(rgbs)
    depths = np.array(depths)
    return rgbs, depths


def seed_everything():
    '''Seed everything for better reproducibility.
    (some pytorch operation is non-deterministic like the backprop of grid_samples)
    '''
    torch.manual_seed(args.seed)
    np.random.seed(args.seed)
    random.seed(args.seed)


def load_everything(args, cfg):
    '''Load images / poses / camera settings / data split.
    '''
    data_dict = load_data(cfg.data)
    if cfg.data.dataset_type == 'hyper_dataset':
        kept_keys = {
            'data_class',
            'near', 'far',
            'i_train', 'i_val', 'i_test',}
        for k in list(data_dict.keys()):
            if k not in kept_keys:
                data_dict.pop(k)
        return data_dict

    # remove useless field
    kept_keys = {
            'hwf', 'HW', 'Ks', 'near', 'far',
            'i_train', 'i_val', 'i_test', 'irregular_shape',
            'poses', 'render_poses', 'images','times','render_times'}
    for k in list(data_dict.keys()):
        if k not in kept_keys:
            data_dict.pop(k)

    # construct data tensor
    if data_dict['irregular_shape']:
        data_dict['images'] = [torch.FloatTensor(im, device='cpu') for im in data_dict['images']]
    else:
        data_dict['images'] = torch.FloatTensor(data_dict['images'], device = 'cpu')
    data_dict['poses'] = torch.Tensor(data_dict['poses'])
    return data_dict


def compute_bbox_by_cam_frustrm(args, cfg, HW, Ks, poses, i_train, near, far, **kwargs):
    print('compute_bbox_by_cam_frustrm: start')
    xyz_min = torch.Tensor([np.inf, np.inf, np.inf])
    xyz_max = -xyz_min
    for (H, W), K, c2w in zip(HW[i_train], Ks[i_train], poses[i_train]):
        rays_o, rays_d, viewdirs = tineuvox.get_rays_of_a_view(
                H=H, W=W, K=K, c2w=c2w,ndc=cfg.data.ndc)
        if cfg.data.ndc:
            pts_nf = torch.stack([rays_o+rays_d*near, rays_o+rays_d*far])
        else:
            pts_nf = torch.stack([rays_o+viewdirs*near, rays_o+viewdirs*far])
        xyz_min = torch.minimum(xyz_min, pts_nf.amin((0,1,2)))
        xyz_max = torch.maximum(xyz_max, pts_nf.amax((0,1,2)))
    print('compute_bbox_by_cam_frustrm: xyz_min', xyz_min)
    print('compute_bbox_by_cam_frustrm: xyz_max', xyz_max)
    print('compute_bbox_by_cam_frustrm: finish')
    return xyz_min, xyz_max


def compute_bbox_by_cam_frustrm_hyper(args, cfg,data_class):
    print('compute_bbox_by_cam_frustrm: start')
    xyz_min = torch.Tensor([np.inf, np.inf, np.inf])
    xyz_max = -xyz_min
    for i in data_class.i_train:
        rays_o, _, viewdirs,_ = data_class.load_idx(i,not_dic=True)
        pts_nf = torch.stack([rays_o+viewdirs*data_class.near, rays_o+viewdirs*data_class.far])
        xyz_min = torch.minimum(xyz_min, pts_nf.amin((0,1,2)))
        xyz_max = torch.maximum(xyz_max, pts_nf.amax((0,1,2)))
    print('compute_bbox_by_cam_frustrm: xyz_min', xyz_min)
    print('compute_bbox_by_cam_frustrm: xyz_max', xyz_max)
    print('compute_bbox_by_cam_frustrm: finish')
    return xyz_min, xyz_max


def scene_rep_reconstruction(args, cfg, cfg_model, cfg_train, xyz_min, xyz_max, data_dict):

    # init
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    if abs(cfg_model.world_bound_scale - 1) > 1e-9:
        xyz_shift = (xyz_max - xyz_min) * (cfg_model.world_bound_scale - 1) / 2
        xyz_min -= xyz_shift
        xyz_max += xyz_shift

    if cfg.data.dataset_type !='hyper_dataset':
        HW, Ks, near, far, i_train, i_val, i_test, poses, render_poses, images ,times,render_times= [
            data_dict[k] for k in [
                'HW', 'Ks', 'near', 'far', 'i_train', 'i_val', 'i_test', 'poses', 
                'render_poses', 'images',
                'times','render_times'
            ]
        ]
        times = torch.Tensor(times)
        times_i_train = times[i_train].to('cpu' if cfg.data.load2gpu_on_the_fly else device)
    else:
        data_class = data_dict['data_class']
        near = data_class.near
        far = data_class.far
        i_train = data_class.i_train
        i_test = data_class.i_test

    last_ckpt_path = os.path.join(cfg.basedir, cfg.expname, 'fine_last.tar')
    # init model and optimizer
    start = 0
    # init model
    model_kwargs = copy.deepcopy(cfg_model)

    num_voxels = model_kwargs.pop('num_voxels')
    if len(cfg_train.pg_scale) :
        num_voxels = int(num_voxels / (2**len(cfg_train.pg_scale)))
    model = tineuvox.TiNeuVox(
        xyz_min=xyz_min, xyz_max=xyz_max,
        num_voxels=num_voxels,
        **model_kwargs)
    model = model.to(device)
    optimizer = utils.create_optimizer_or_freeze_model(model, cfg_train, global_step=0)

    # init rendering setup
    render_kwargs = {
        'near': near,
        'far': far,
        'bg': 1 if cfg.data.white_bkgd else 0,
        'stepsize': cfg_model.stepsize,
    }
    # init batch rays sampler
    def gather_training_rays_hyper():
        now_device = 'cpu'  if cfg.data.load2gpu_on_the_fly else device
        N = len(data_class.i_train)*data_class.h*data_class.w
        rgb_tr = torch.zeros([N,3], device=now_device)
        rays_o_tr = torch.zeros_like(rgb_tr)
        rays_d_tr = torch.zeros_like(rgb_tr)
        viewdirs_tr = torch.zeros_like(rgb_tr)
        times_tr = torch.ones([N,1], device=now_device)
        cam_tr = torch.ones([N,1], device=now_device)
        imsz = []
        top = 0
        for i in data_class.i_train:
            rays_o, rays_d, viewdirs,rgb = data_class.load_idx(i,not_dic=True)
            n = rgb.shape[0]
            if data_class.add_cam:
                cam_tr[top:top+n] = cam_tr[top:top+n]*data_class.all_cam[i]
            times_tr[top:top+n] = times_tr[top:top+n]*data_class.all_time[i]
            rgb_tr[top:top+n].copy_(rgb)
            rays_o_tr[top:top+n].copy_(rays_o.to(now_device))
            rays_d_tr[top:top+n].copy_(rays_d.to(now_device))
            viewdirs_tr[top:top+n].copy_(viewdirs.to(now_device))
            imsz.append(n)
            top += n
        assert top == N
        index_generator = tineuvox.batch_indices_generator(len(rgb_tr), cfg_train.N_rand)
        batch_index_sampler = lambda: next(index_generator)
        return rgb_tr, times_tr,cam_tr,rays_o_tr, rays_d_tr, viewdirs_tr, imsz, batch_index_sampler


    def gather_training_rays():
        if data_dict['irregular_shape']:
            rgb_tr_ori = [images[i].to('cpu' if cfg.data.load2gpu_on_the_fly else device) for i in i_train]
        else:
            rgb_tr_ori = images[i_train].to('cpu' if cfg.data.load2gpu_on_the_fly else device)

        if cfg_train.ray_sampler == 'in_maskcache':
            print('cfg_train.ray_sampler =in_maskcache')
            rgb_tr, times_flaten,rays_o_tr, rays_d_tr, viewdirs_tr, imsz = tineuvox.get_training_rays_in_maskcache_sampling(
                    rgb_tr_ori=rgb_tr_ori,times=times_i_train,
                    train_poses=poses[i_train],
                    HW=HW[i_train], Ks=Ks[i_train],
                    ndc=cfg.data.ndc, 
                    model=model, render_kwargs=render_kwargs)
        elif cfg_train.ray_sampler == 'flatten':
            print('cfg_train.ray_sampler =flatten')
            rgb_tr, times_flaten,rays_o_tr, rays_d_tr, viewdirs_tr, imsz = tineuvox.get_training_rays_flatten(
                rgb_tr_ori=rgb_tr_ori,times=times_i_train,
                train_poses=poses[i_train],
                HW=HW[i_train], Ks=Ks[i_train], ndc=cfg.data.ndc,)
        else:
            print('cfg_train.ray_sampler =random')
            rgb_tr, times_flaten,rays_o_tr, rays_d_tr, viewdirs_tr, imsz = tineuvox.get_training_rays(
                rgb_tr=rgb_tr_ori,times=times_i_train,
                train_poses=poses[i_train],
                HW=HW[i_train], Ks=Ks[i_train], ndc=cfg.data.ndc,)
        index_generator = tineuvox.batch_indices_generator(len(rgb_tr), cfg_train.N_rand)
        batch_index_sampler = lambda: next(index_generator)
        return rgb_tr,times_flaten, rays_o_tr, rays_d_tr, viewdirs_tr, imsz, batch_index_sampler
    if cfg.data.dataset_type !='hyper_dataset':
        rgb_tr,times_flaten, rays_o_tr, rays_d_tr, viewdirs_tr, imsz, batch_index_sampler = gather_training_rays()
    else:
        rgb_tr,times_flaten,cam_tr, rays_o_tr, rays_d_tr, viewdirs_tr, imsz, batch_index_sampler = gather_training_rays_hyper()

    torch.cuda.empty_cache()
    psnr_lst = []
    time0 = time.time()
    global_step = -1

    for global_step in trange(1+start, 1+cfg_train.N_iters):

        if global_step == args.step_to_half:
                model.feature.data=model.feature.data.half()
        # progress scaling checkpoint
        if global_step in cfg_train.pg_scale:
            n_rest_scales = len(cfg_train.pg_scale)-cfg_train.pg_scale.index(global_step)-1
            cur_voxels = int(cfg_model.num_voxels / (2**n_rest_scales))
            if isinstance(model, tineuvox.TiNeuVox):
                model.scale_volume_grid(cur_voxels)
            else:
                raise NotImplementedError
            optimizer = utils.create_optimizer_or_freeze_model(model, cfg_train, global_step=0)

        # random sample rays
        if cfg_train.ray_sampler in ['flatten', 'in_maskcache'] or cfg.data.dataset_type =='hyper_dataset':
            sel_i = batch_index_sampler()
            target = rgb_tr[sel_i]
            rays_o = rays_o_tr[sel_i]
            rays_d = rays_d_tr[sel_i]
            viewdirs = viewdirs_tr[sel_i]
            times_sel = times_flaten[sel_i]
            if cfg.data.dataset_type == 'hyper_dataset':
                if data_class.add_cam == True:
                    cam_sel = cam_tr[sel_i]
                    cam_sel = cam_sel.to(device)
                    render_kwargs.update({'cam_sel':cam_sel})
                if data_class.use_bg_points == True:
                    sel_idx = torch.randint(data_class.bg_points.shape[0], [cfg_train.N_rand//3])
                    bg_points_sel = data_class.bg_points[sel_idx]
                    bg_points_sel = bg_points_sel.to(device)
                    render_kwargs.update({'bg_points_sel':bg_points_sel})
        elif cfg_train.ray_sampler == 'random':
            sel_b = torch.randint(rgb_tr.shape[0], [cfg_train.N_rand])
            sel_r = torch.randint(rgb_tr.shape[1], [cfg_train.N_rand])
            sel_c = torch.randint(rgb_tr.shape[2], [cfg_train.N_rand])
            target = rgb_tr[sel_b, sel_r, sel_c]
            rays_o = rays_o_tr[sel_b, sel_r, sel_c]
            rays_d = rays_d_tr[sel_b, sel_r, sel_c]
            viewdirs = viewdirs_tr[sel_b, sel_r, sel_c]
            times_sel = times_flaten[sel_b, sel_r, sel_c]
        else:
            raise NotImplementedError

        if cfg.data.load2gpu_on_the_fly:
            target = target.to(device)
            rays_o = rays_o.to(device)
            rays_d = rays_d.to(device)
            viewdirs = viewdirs.to(device)
            times_sel = times_sel.to(device)

        # volume rendering
        render_result = model(rays_o, rays_d, viewdirs, times_sel, global_step=global_step, **render_kwargs)

        # gradient descent step
        optimizer.zero_grad(set_to_none = True)
        loss = cfg_train.weight_main * F.mse_loss(render_result['rgb_marched'], target)
        psnr = utils.mse2psnr(loss.detach())
        
        if cfg.data.dataset_type =='hyper_dataset':
            if data_class.use_bg_points == True:
                loss = loss+F.mse_loss(render_result['bg_points_delta'],bg_points_sel)
        if cfg_train.weight_entropy_last > 0:
            pout = render_result['alphainv_last'].clamp(1e-6, 1-1e-6)
            entropy_last_loss = -(pout*torch.log(pout) + (1-pout)*torch.log(1-pout)).mean()
            loss += cfg_train.weight_entropy_last * entropy_last_loss
        if cfg_train.weight_rgbper > 0:
            rgbper = (render_result['raw_rgb'] - target[render_result['ray_id']]).pow(2).sum(-1)
            rgbper_loss = (rgbper * render_result['weights'].detach()).sum() / len(rays_o)
            loss += cfg_train.weight_rgbper * rgbper_loss
        loss.backward()

        if global_step<cfg_train.tv_before and global_step>cfg_train.tv_after and global_step%cfg_train.tv_every==0:
            if cfg_train.weight_tv_feature>0:
                model.feature_total_variation_add_grad(
                    cfg_train.weight_tv_feature/len(rays_o), global_step<cfg_train.tv_feature_before)
        optimizer.step()
        psnr_lst.append(psnr.item())
        # update lr
        decay_steps = cfg_train.lrate_decay * 1000
        decay_factor = 0.1 ** (1/decay_steps)
        for i_opt_g, param_group in enumerate(optimizer.param_groups):
            param_group['lr'] = param_group['lr'] * decay_factor

        # check log & save
        if global_step%args.i_print == 0:
            eps_time = time.time() - time0
            eps_time_str = f'{eps_time//3600:02.0f}:{eps_time//60%60:02.0f}:{eps_time%60:02.0f}'
            tqdm.write(f'scene_rep_reconstruction : iter {global_step:6d} / '
                       f'Loss: {loss.item():.9f} / PSNR: {np.mean(psnr_lst):5.2f} / '
                       f'Eps: {eps_time_str}')
            psnr_lst = []

        if global_step%(args.fre_test) == 0:
            render_viewpoints_kwargs = {
                'model': model,
                'ndc': cfg.data.ndc,
                'render_kwargs': {
                    'near': near,
                    'far': far,
                    'bg': 1 if cfg.data.white_bkgd else 0,
                    'stepsize': cfg_model.stepsize,

                    },
                }
            testsavedir = os.path.join(cfg.basedir, cfg.expname, f'{global_step}-test')
            if os.path.exists(testsavedir) == False:
                os.makedirs(testsavedir)
            if cfg.data.dataset_type != 'hyper_dataset': 
                rgbs,disps = render_viewpoints(
                    render_poses=data_dict['poses'][data_dict['i_test']],
                    HW=data_dict['HW'][data_dict['i_test']],
                    Ks=data_dict['Ks'][data_dict['i_test']],
                    gt_imgs=[data_dict['images'][i].cpu().numpy() for i in data_dict['i_test']],
                    savedir=testsavedir,
                    test_times=data_dict['times'][data_dict['i_test']],
                    eval_psnr=args.eval_psnr, eval_ssim=args.eval_ssim, eval_lpips_alex=args.eval_lpips_alex, eval_lpips_vgg=args.eval_lpips_vgg,
                    **render_viewpoints_kwargs)
            else:
                rgbs,disps = render_viewpoints_hyper(
                    data_class=data_class,
                    savedir=testsavedir, all=False, test=True, eval_psnr=args.eval_psnr,
                    **render_viewpoints_kwargs)

    if global_step != -1:
        torch.save({
            'global_step': global_step,
            'model_kwargs': model.get_kwargs(),
            'model_state_dict': model.state_dict(),
        }, last_ckpt_path)
        print('scene_rep_reconstruction : saved checkpoints at', last_ckpt_path)


def train(args, cfg, data_dict=None):

    # init
    print('train: start')
    os.makedirs(os.path.join(cfg.basedir, cfg.expname), exist_ok=True)
    with open(os.path.join(cfg.basedir, cfg.expname, 'args.txt'), 'w') as file:
        for arg in sorted(vars(args)):
            attr = getattr(args, arg)
            file.write('{} = {}\n'.format(arg, attr))
    cfg.dump(os.path.join(cfg.basedir, cfg.expname, 'config.py'))

    # coarse geometry searching
    if cfg.data.dataset_type == 'hyper_dataset':
        xyz_min, xyz_max = compute_bbox_by_cam_frustrm_hyper(args = args, cfg = cfg,data_class = data_dict['data_class'])
    else:
        xyz_min, xyz_max = compute_bbox_by_cam_frustrm(args = args, cfg = cfg, **data_dict)
    coarse_ckpt_path = None

    # fine detail reconstruction
    eps_time = time.time()
    scene_rep_reconstruction(
            args=args, cfg=cfg,
            cfg_model=cfg.model_and_render, cfg_train=cfg.train_config,
            xyz_min=xyz_min, xyz_max=xyz_max,
            data_dict=data_dict)
    eps_loop = time.time() - eps_time
    eps_time_str = f'{eps_loop//3600:02.0f}:{eps_loop//60%60:02.0f}:{eps_loop%60:02.0f}'
    print('train: finish (eps time', eps_time_str, ')')

if __name__=='__main__':

    # load setup
    parser = config_parser()
    args = parser.parse_args()
    cfg = mmcv.Config.fromfile(args.config)
    # init enviroment
    if torch.cuda.is_available():
        torch.set_default_tensor_type('torch.cuda.FloatTensor')
        device = torch.device('cuda')
    else:
        device = torch.device('cpu')
    seed_everything()
    data_dict = None
    # load images / poses / camera settings / data split
    data_dict = load_everything(args = args, cfg = cfg)

    # train
    if not args.render_only :
        train(args, cfg, data_dict = data_dict)

    # load model for rendring
    if args.render_test or args.render_train or args.render_video:
        if args.ft_path:
            ckpt_path = args.ft_path
        else:
            ckpt_path = os.path.join(cfg.basedir, cfg.expname, 'fine_last.tar')
        ckpt_name = ckpt_path.split('/')[-1][:-4]
        model_class = tineuvox.TiNeuVox
        model = utils.load_model(model_class, ckpt_path).to(device)
        near=data_dict['near']
        far=data_dict['far']
        stepsize = cfg.model_and_render.stepsize
        render_viewpoints_kwargs = {
            'model': model,
            'ndc': cfg.data.ndc,
            'render_kwargs': {
                'near': near,
                'far': far,
                'bg': 1 if cfg.data.white_bkgd else 0,
                'stepsize': stepsize,
                'render_depth': True,
            },
        }
    # render trainset and eval
    if args.render_train:
        testsavedir = os.path.join(cfg.basedir, cfg.expname, f'render_train_{ckpt_name}')
        os.makedirs(testsavedir, exist_ok = True)
        if cfg.data.dataset_type  != 'hyper_dataset':
            rgbs, disps = render_viewpoints(
                    render_poses=data_dict['poses'][data_dict['i_train']],
                    HW=data_dict['HW'][data_dict['i_train']],
                    Ks=data_dict['Ks'][data_dict['i_train']],
                    gt_imgs=[data_dict['images'][i].cpu().numpy() for i in data_dict['i_train']],
                    savedir=testsavedir,
                    test_times=data_dict['times'][data_dict['i_train']],
                    eval_psnr=args.eval_psnr, eval_ssim=args.eval_ssim, eval_lpips_alex=args.eval_lpips_alex, eval_lpips_vgg=args.eval_lpips_vgg,
                    **render_viewpoints_kwargs)
        elif cfg.data.dataset_type == 'hyper_dataset':   
            rgbs,disps = render_viewpoints_hyper(
                    data_calss=data_dict['data_calss'],
                    savedir=testsavedir, all=True, test=False,
                    eval_psnr=args.eval_psnr,
                    **render_viewpoints_kwargs)
        else:
            raise NotImplementedError

        imageio.mimwrite(os.path.join(testsavedir, 'train_video.rgb.mp4'), utils.to8b(rgbs), fps = 30, quality = 8)
        imageio.mimwrite(os.path.join(testsavedir, 'train_video.disp.mp4'), utils.to8b(disps / np.max(disps)), fps = 30, quality = 8)

    # render testset and eval
    if args.render_test:
        testsavedir = os.path.join(cfg.basedir, cfg.expname, f'render_test_{ckpt_name}')
        os.makedirs(testsavedir, exist_ok=True)
        if cfg.data.dataset_type  != 'hyper_dataset':
            rgbs, disps = render_viewpoints(
                    render_poses=data_dict['poses'][data_dict['i_test']],
                    HW=data_dict['HW'][data_dict['i_test']],
                    Ks=data_dict['Ks'][data_dict['i_test']],
                    gt_imgs=[data_dict['images'][i].cpu().numpy() for i in data_dict['i_test']],
                    savedir=testsavedir,
                    test_times=data_dict['times'][data_dict['i_test']],
                    eval_psnr=args.eval_psnr,eval_ssim = args.eval_ssim, eval_lpips_alex=args.eval_lpips_alex, eval_lpips_vgg=args.eval_lpips_vgg,
                    **render_viewpoints_kwargs)
        elif cfg.data.dataset_type == 'hyper_dataset':   
            rgbs,disps = render_viewpoints_hyper(
                    data_class=data_dict['data_class'],
                    savedir=testsavedir,all=True,test=True,
                    eval_psnr=args.eval_psnr,
                    **render_viewpoints_kwargs)
        else:
            raise NotImplementedError

        imageio.mimwrite(os.path.join(testsavedir, 'test_video.rgb.mp4'), utils.to8b(rgbs), fps=30, quality=8)
        imageio.mimwrite(os.path.join(testsavedir, 'test_video.disp.mp4'), utils.to8b(disps / np.max(disps)), fps=30, quality=8)

    # render video
    if args.render_video:
        if cfg.data.dataset_type  != 'hyper_dataset':
            testsavedir = os.path.join(cfg.basedir, cfg.expname, f'render_video_{ckpt_name}_time')
            os.makedirs(testsavedir, exist_ok=True)
            rgbs, disps = render_viewpoints(
                    render_poses=data_dict['render_poses'],
                    HW=data_dict['HW'][data_dict['i_test']][[0]].repeat(len(data_dict['render_poses']), 0),
                    Ks=data_dict['Ks'][data_dict['i_test']][[0]].repeat(len(data_dict['render_poses']), 0),
                    render_factor=args.render_video_factor,
                    savedir=testsavedir,
                    test_times=data_dict['render_times'],
                    **render_viewpoints_kwargs)
            imageio.mimwrite(os.path.join(testsavedir, 'video.rgb.mp4'), utils.to8b(rgbs), fps=30, quality=8)
            imageio.mimwrite(os.path.join(testsavedir, 'video.disp.mp4'), utils.to8b(disps / np.max(disps)), fps=30, quality =8)
        else:
            raise NotImplementedError

    print('Done')

Download .txt
gitextract_12u6qfpa/

├── .gitignore
├── LICENSE
├── README.md
├── configs/
│   ├── misc/
│   │   ├── espresso.py
│   │   └── hyper_default.py
│   ├── nerf-base/
│   │   ├── bouncingballs.py
│   │   ├── default.py
│   │   ├── hellwarrior.py
│   │   ├── hook.py
│   │   ├── jumpingjacks.py
│   │   ├── lego.py
│   │   ├── mutant.py
│   │   ├── standup.py
│   │   └── trex.py
│   ├── nerf-small/
│   │   ├── bouncingballs.py
│   │   ├── default.py
│   │   ├── hellwarrior.py
│   │   ├── hook.py
│   │   ├── jumpingjacks.py
│   │   ├── lego.py
│   │   ├── mutant.py
│   │   ├── standup.py
│   │   └── trex.py
│   └── vrig_dataset/
│       ├── 3dprinter.py
│       ├── broom.py
│       ├── chicken.py
│       ├── hyper_default.py
│       └── peel-banana.py
├── metric.py
├── requirements.txt
└── run.py
Download .txt
SYMBOL INDEX (22 symbols across 2 files)

FILE: metric.py
  class MSE (line 15) | class MSE(object):
    method __call__ (line 16) | def __call__(self, pred, gt):
  class PSNR (line 20) | class PSNR(object):
    method __call__ (line 21) | def __call__(self, pred, gt):
  class SSIM (line 27) | class SSIM(object):
    method gaussian (line 31) | def gaussian(self, w_size, sigma):
    method create_window (line 35) | def create_window(self, w_size, channel=1):
    method __call__ (line 41) | def __call__(self, y_pred, y_true, w_size=11, size_average=True, full=...
  class LPIPS (line 99) | class LPIPS(object):
    method __init__ (line 103) | def __init__(self):
    method __call__ (line 106) | def __call__(self, y_pred, y_true, normalized=True):
  function read_images_in_dir (line 121) | def read_images_in_dir(imgs_dir):
  function estim_error (line 141) | def estim_error(estim, gt):

FILE: run.py
  function config_parser (line 21) | def config_parser():
  function render_viewpoints_hyper (line 54) | def render_viewpoints_hyper(model, data_class, ndc, render_kwargs, test=...
  function render_viewpoints (line 123) | def render_viewpoints(model, render_poses, HW, Ks, ndc, render_kwargs,
  function seed_everything (line 199) | def seed_everything():
  function load_everything (line 208) | def load_everything(args, cfg):
  function compute_bbox_by_cam_frustrm (line 240) | def compute_bbox_by_cam_frustrm(args, cfg, HW, Ks, poses, i_train, near,...
  function compute_bbox_by_cam_frustrm_hyper (line 259) | def compute_bbox_by_cam_frustrm_hyper(args, cfg,data_class):
  function scene_rep_reconstruction (line 274) | def scene_rep_reconstruction(args, cfg, cfg_model, cfg_train, xyz_min, x...
  function train (line 525) | def train(args, cfg, data_dict=None):
Condensed preview — 31 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (73K chars).
[
  {
    "path": ".gitignore",
    "chars": 1799,
    "preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 5355,
    "preview": "# TiNeuVox: Time-Aware Neural Voxels\n## ACM SIGGRAPH Asia 2022\n\n### [Project Page](https://jaminfong.cn/tineuvox) | [ACM"
  },
  {
    "path": "configs/misc/espresso.py",
    "chars": 183,
    "preview": "_base_ = './hyper_default.py'\n\nexpname = 'misc/espresso'\nbasedir = './logs/vrig_data'\n\ndata = dict(\n    datadir='./espre"
  },
  {
    "path": "configs/misc/hyper_default.py",
    "chars": 2863,
    "preview": "from copy import deepcopy\n\nexpname = None                    # experiment name\nbasedir = './logs/'               # where"
  },
  {
    "path": "configs/nerf-base/bouncingballs.py",
    "chars": 205,
    "preview": "_base_ = './default.py'\n\nexpname = 'base/dnerf_bouncingballs-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    da"
  },
  {
    "path": "configs/nerf-base/default.py",
    "chars": 2835,
    "preview": "from copy import deepcopy\n\nexpname = None                    # experiment name\nbasedir = './logs/'               # where"
  },
  {
    "path": "configs/nerf-base/hellwarrior.py",
    "chars": 201,
    "preview": "_base_ = './default.py'\n\nexpname = 'base/dnerf_hellwarrior-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    data"
  },
  {
    "path": "configs/nerf-base/hook.py",
    "chars": 187,
    "preview": "_base_ = './default.py'\n\nexpname = 'base/dnerf_hook-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    datadir='/d"
  },
  {
    "path": "configs/nerf-base/jumpingjacks.py",
    "chars": 203,
    "preview": "_base_ = './default.py'\n\nexpname = 'base/dnerf_jumpingjacks-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    dat"
  },
  {
    "path": "configs/nerf-base/lego.py",
    "chars": 187,
    "preview": "_base_ = './default.py'\n\nexpname = 'base/dnerf_lego-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    datadir='/d"
  },
  {
    "path": "configs/nerf-base/mutant.py",
    "chars": 191,
    "preview": "_base_ = './default.py'\n\nexpname = 'base/dnerf_mutant-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    datadir='"
  },
  {
    "path": "configs/nerf-base/standup.py",
    "chars": 191,
    "preview": "_base_ = './default.py'\n\nexpname = 'base/dnerf_standup-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    datadir="
  },
  {
    "path": "configs/nerf-base/trex.py",
    "chars": 187,
    "preview": "_base_ = './default.py'\n\nexpname = 'base/dnerf_trex-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    datadir='/d"
  },
  {
    "path": "configs/nerf-small/bouncingballs.py",
    "chars": 206,
    "preview": "_base_ = './default.py'\n\nexpname = 'small/dnerf_bouncingballs-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    d"
  },
  {
    "path": "configs/nerf-small/default.py",
    "chars": 2920,
    "preview": "from copy import deepcopy\n\nexpname = None                    # experiment name\nbasedir = './logs/'               # where"
  },
  {
    "path": "configs/nerf-small/hellwarrior.py",
    "chars": 202,
    "preview": "_base_ = './default.py'\n\nexpname = 'small/dnerf_hellwarrior-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    dat"
  },
  {
    "path": "configs/nerf-small/hook.py",
    "chars": 188,
    "preview": "_base_ = './default.py'\n\nexpname = 'small/dnerf_hook-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    datadir='/"
  },
  {
    "path": "configs/nerf-small/jumpingjacks.py",
    "chars": 204,
    "preview": "_base_ = './default.py'\n\nexpname = 'small/dnerf_jumpingjacks-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    da"
  },
  {
    "path": "configs/nerf-small/lego.py",
    "chars": 188,
    "preview": "_base_ = './default.py'\n\nexpname = 'small/dnerf_lego-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    datadir='/"
  },
  {
    "path": "configs/nerf-small/mutant.py",
    "chars": 192,
    "preview": "_base_ = './default.py'\n\nexpname = 'small/dnerf_mutant-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    datadir="
  },
  {
    "path": "configs/nerf-small/standup.py",
    "chars": 192,
    "preview": "_base_ = './default.py'\n\nexpname = 'small/dnerf_standup-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    datadir"
  },
  {
    "path": "configs/nerf-small/trex.py",
    "chars": 188,
    "preview": "_base_ = './default.py'\n\nexpname = 'small/dnerf_trex-400'\nbasedir = './logs/nerf_synthetic'\n\ndata = dict(\n    datadir='/"
  },
  {
    "path": "configs/vrig_dataset/3dprinter.py",
    "chars": 195,
    "preview": "_base_ = './hyper_default.py'\n\nexpname = 'vrig/base-3dprinter'\nbasedir = './logs/vrig_data'\n\ndata = dict(\n    datadir='."
  },
  {
    "path": "configs/vrig_dataset/broom.py",
    "chars": 196,
    "preview": "_base_ = './hyper_default.py'\n\nexpname = 'vrig/base-broom'\nbasedir = './logs/vrig_data'\n\ndata = dict(\n    datadir='./vri"
  },
  {
    "path": "configs/vrig_dataset/chicken.py",
    "chars": 191,
    "preview": "_base_ = './hyper_default.py'\n\nexpname = 'vrig/base-chicken'\nbasedir = './logs/vrig_data'\n\ndata = dict(\n    datadir='./v"
  },
  {
    "path": "configs/vrig_dataset/hyper_default.py",
    "chars": 2863,
    "preview": "from copy import deepcopy\n\nexpname = None                    # experiment name\nbasedir = './logs/'               # where"
  },
  {
    "path": "configs/vrig_dataset/peel-banana.py",
    "chars": 199,
    "preview": "_base_ = './hyper_default.py'\n\nexpname = 'vrig/base-peel-banana'\nbasedir = './logs/vrig_data'\n\ndata = dict(\n    datadir="
  },
  {
    "path": "metric.py",
    "chars": 5534,
    "preview": "\nimport argparse\nimport math\nimport os\n\nimport imageio\nimport lpips\nimport numpy as np\nimport torch\nimport torch.nn as n"
  },
  {
    "path": "requirements.txt",
    "chars": 106,
    "preview": "numpy\nscipy\ntqdm\nlpips\nmmcv\nimageio\nimageio-ffmpeg\nopencv-python\npytorch_msssim\ntorch\ntorch_scatter\nPillow"
  },
  {
    "path": "run.py",
    "chars": 29599,
    "preview": "import argparse\nimport copy\nimport os\nimport random\nimport time\nfrom builtins import print\n\nimport imageio\nimport mmcv\ni"
  }
]

About this extraction

This page contains the full source code of the hustvl/TiNeuVox GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 31 files (67.7 KB), approximately 18.6k tokens, and a symbol index with 22 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!