Skip to content

umautobots/trnerf

Repository files navigation

Thermal Restoration NeRF (TRNeRF)

Implementation of Thermal Restoration NeRF (TRNeRF)
[project page] [paper (IEEE)] [paper (CVF, open access)]

Table of Contents

Dataset Download, Format, and Conversion

The dataset is available through the project page. See the Data Format documentation page for a detailed description of the files. We also provide scripts for converting the data from the H5 format to ROS1 rosbags or common formats (CSV files and folders of PNG images). See the Conversion documentation page for more details.

To run training and evaluation (except the detection metric) with the recommended settings on all sequences, the minimally required subset of the dataset and the expected file structure is as follows:

/path/to/trnerf_dataset_folder/
├── cam_calibration
│   └── camchain.yaml
├── slow_indoor
│   ├── adk_right.h5
│   └── pseudo_ground_truth_poses.h5
├── slow_outdoor
│   └── ...
├── medium_indoor
│   ├── adk_right.h5
│   ├── pseudo_ground_truth_adk_right.h5
│   └── pseudo_ground_truth_poses.h5
├── medium_outdoor
│   └── ...
├── fast_indoor
│   └── ...
└── fast_outdoor
    └── ...

Additionally:

Training

In this section we describe how to perform training with TRNeRF.

Setup

We recommend running the code with Docker, as explained below. However, if you already have nerfstudio installed, it may be possible to install TRNeRF as follows:

cd /path/to/trnerf/trnerf_utils/
pip3 install -e .
cd ../trnerf_main/
pip3 install -e .
ns-install-cli

You can check the install by running ns-train -h and confirming that trnerf appears in the list of subcommands.

To run TRNeRF with Docker, first ensure Docker is installed and has access to your NVIDIA GPU(s). On Ubuntu, this can be done by installing Docker Engine, performing this post-installation step, updating your NVIDIA drivers, and finally installing the NVIDIA Container Toolkit.

After installing Docker, a Docker image for running TRNeRF can be built as follows:

cd /path/to/trnerf/
docker build \
    --build-arg CUDA_ARCHITECTURES=<compute capability> \
    --build-arg USER_ID=$(id -u) \
    --tag trnerf_training \
    --file docker/Dockerfile_nerfstudio \
    .

where <compute capability> should be replaced with the compute capability of your GPU(s) with the decimal point removed (e.g., if the compute capability is 8.6, then put 86 here). The result will be a new Docker image named trnerf_training.

Running

Run the Docker image created in the previous section with the following command:

docker run -it --gpus '"device=0"' -p 7007:7007 --shm-size=12gb -v ~/.cache/:/home/user/.cache -v /path/to/trnerf_dataset_folder/:/data -v /path/to/output_folder/:/output trnerf_training

where /path/to/trnerf_dataset_folder/ should be replaced with the path to the downloaded TRNeRF dataset (see Dataset Download, Format, and Conversion) and /path/to/output_folder/ should be replaced with the folder you would like training output to be stored in. The folders will appear within the container as /data and /output. The command -p 7007:7007 binds port 7007 of the container to that of the host as the nerfstudio viewer uses port 7007 by default. You can also change --gpus '"device=0"' to another GPU (e.g., --gpus '"device=2"'), a list of GPUs (e.g., --gpus '"device=0, 2"'), or all GPUs (--gpus all).

The command above will start an interactive bash session in the running container. From here, you can view the TRNeRF and TRNeRF dataparser arguments with ns-train trnerf -h and ns-train trnerf trnerf_dataparser -h, respectively. To run TRNeRF training with recommended settings, we've provided the run_training_rec.sh bash script that can be executed in the container as follows:

/home/user/trnerf/scripts/training/run_training_rec.sh \
    /output/ \
    /data/ \
    <speed> \
    <scene>

where <speed> can be slow, medium, or fast and <scene> can be indoor or outdoor. The result will be a trial folder /output/right_<speed>_<scene>_recommended/trnerf/<date and time>/ that contains configuration information (config.yml and dataparser_transforms.json) and the trained model (nerfstudio_models/step-*.ckpt). If training crashes due to memory limitations, see Reducing CPU & GPU Memory Consumption below.

We've also provided the run_training_rec_all.sh and run_training_ablations.sh bash scripts in the folder scripts/training to perform training on all scenes with recommended settings and to perform training with all of the settings and data tested in the ablation study, respectively. The run_training_rec_all.sh bash script can be executed in the container as follows:

/home/user/trnerf/scripts/training/run_training_rec_all.sh \
    /output/ \
    /data/

and run_training_ablations.sh can be run with the same arguments.

Using the Nerfstudio Viewer

If you are training locally, you can use the nerfstudio viewer by opening a browser and going to localhost:7007. If you are training on a remote machine, run the following in a terminal window on your local machine:

ssh -L 7007:localhost:7007 <username>@<training-host-ip>

and you should now be able to use the viewer by navigating to localhost:7007 as described above.

If you cannot see the camera poses, uncheck Composite depth. You can click on a camera pose to jump to its view. It may take a while for training to converge to something visually recognizable.

By default, the visualization will be scaled between the minimum and maximum intensities observed in the scene. To switch to a higher contrast visualization select viewer_output in the Output type dropdown.

To use the viewer after training, run the following from within the Docker container:

ns-viewer --load-config /path/to/config.yml

where /path/to/config.yml should be replaced with the path to the config.yml file in the trial folder that was generated during training.

Reducing CPU & GPU Memory Consumption

The CPU and GPU memory consumption can be reduced by editing the run_training.sh bash script.

To reduce the CPU memory usage you can set --pipeline.datamanager.train-num-images-to-sample-from to a lower value. You may also want to increase --pipeline.datamanager.train-num-times-to-repeat-images accordingly.

To reduce the GPU memory consumption, we suggest:

  • setting --mixed-precision to False
  • multiplying the --gradient-accumulation-steps for both fields by some factor
  • dividing the --pipeline.datamanager.train-num-rays-per-batch by the same factor
  • multiplying the --max-num-iterations by the same factor

Evaluation

In this section we describe how to render restored images, compute metrics from the restored images, and compile and visualize the results.

Setup

Performing the evaluation requires two Docker images. The first is the trnerf_training Docker image described above for training. The second Docker image has Kalibr installed for Aprilgrid detection and can be built as follows:

cd /path/to/trnerf/
docker build \
    --build-arg USER_ID=$(id -u) \
    --tag trnerf_detection_metric \
    --file docker/Dockerfile_kalibr \
    .

The result will be a new Docker image named trnerf_detection_metric.

Rendering Restored Images

Run the trnerf_training Docker image as described above. To render a restored image for each training image in a sequence, run the following in the container:

python3 /home/user/trnerf/trnerf_main/trnerf/render_restored.py --path-config /path/to/config.yml

where /path/to/config.yml should be replaced with the path to the config.yml file in the trial folder that was generated during training. The result will be a file, restored.h5, that contains the restored images, in the same folder as config.yml.

We've provided the run_rendering_all.sh bash script to perform rendering for all trials. It can be run as follows:

/home/user/trnerf/scripts/evaluation/rendering/run_rendering_all.sh /output/

Computing the LPIPS Metric

Run the trnerf_training Docker image as described above. You can view the arguments for computing the LPIPS metric with python3 /home/user/trnerf/evaluation/compute_lpips_metric.py -h. To compute the LPIPS metric for a single trial, we've provided the run_lpips_metric_trial.sh bash script that can be executed in the container as follows:

/home/user/trnerf/scripts/evaluation/computing_metrics/run_lpips_metric_trial.sh /path/to/trial_folder/ /data/

where /path/to/trial_folder/ should be replaced with the path to the trial folder that was generated during training. The result will be a file results_lpips_metric.pickle in the trial folder. Note that the LPIPS metric is only computed for the medium and fast sequences as pseudo ground truth images are not generated for the slow sequences.

We've also provided the run_lpips_metric_all.sh bash script to compute the LPIPS metric for all medium/fast trials. It can be run in the container as follows:

/home/user/trnerf/scripts/evaluation/computing_metrics/run_lpips_metric_all.sh /output/ /data/

Additionally, the run_lpips_metric_raw.sh script can be run with the same arguments as run_lpips_metric_all.sh to compute the LPIPS metric with the raw images from all medium/fast sequences. If needed, this will create new trial folders with the pattern /output/<camera>_<speed>_<scene>_raw/ to store the results.

Note that run_lpips_metric_trial.sh and run_lpips_metric_all.sh assume that the speed (slow/medium/fast), scene (indoor/outdoor), and camera (left/right) can be inferred from the trial folder paths (which is true for any trial folder generated from the provided training bash scripts). Alternatively, run_lpips_metric.sh can be run directly with additional arguments.

Computing the Detection Metric

Run the trnerf_detection_metric Docker image created in the section above with the following command:

docker run -it -v /path/to/trnerf_dataset_folder/:/data -v /path/to/output_folder/:/output trnerf_detection_metric

where /path/to/trnerf_dataset_folder/ should be replaced with the path to the downloaded TRNeRF dataset (see Dataset Download, Format, and Conversion) and /path/to/output_folder/ should be replaced with the output folder used during training. The folders will appear within the container as /data and /output.

The command above will start an interactive bash session in the running container. Analogous to the previous section, you can view the arguments for computing the detection metric with python3 /home/user/trnerf/evaluation/compute_detection_metric.py -h. To compute the detection metric for a single trial, we've provided the run_detection_metric_trial.sh bash script that can be executed in the container as follows:

/home/user/trnerf/scripts/evaluation/computing_metrics/run_detection_metric_trial.sh /path/to/trial_folder/ /data/

where /path/to/trial_folder/ should be replaced with the path to the trial folder that was generated during training. The result will be a file results_detection_metric.pickle in the trial folder.

We've also provided the run_detection_metric_all.sh bash script to compute the detection metric for all trials. It can be run in the container as follows:

/home/user/trnerf/scripts/evaluation/computing_metrics/run_detection_metric_all.sh /output/ /data/

Additionally, the run_detection_metric_raw.sh script can be run with the same arguments as run_detection_metric_all.sh to compute the detection metric with the raw images from all sequences. If needed, this will create new trial folders with the pattern /output/<camera>_<speed>_<scene>_raw/ to store the results.

Note that run_detection_metric_trial.sh and run_detection_metric_all.sh assume that the speed (slow/medium/fast), scene (indoor/outdoor), and camera (left/right) can be inferred from the trial folder paths (which is true for any trial folder generated from the provided training bash scripts). Alternatively, run_detection_metric.sh can be run directly with additional arguments.

Creating a Spreadsheet

In either Docker container, the detection and LPIPS results across all trials can be compiled into spreadsheet by running:

python3 /home/user/trnerf/evaluation/create_spreadsheet.py /output/

The result will be a file results.xlsx in the /output/ folder.

Creating a Comparison Video

In either Docker container, you can view the arguments for creating a comparison video with python3 /home/user/trnerf/evaluation/create_comparison_video.py -h. As an example, the following command:

python3 /home/user/trnerf/evaluation/create_comparison_video.py \
    --paths \
        /output/right_medium_indoor_raw/ \
        /output/right_medium_indoor_recommended/trnerf/<date and time>/ \
    --method-list \
        Raw \
        TRNeRF \
    --include-pseudo-gt \
    --annotate-results \
    --grid-shape 1 3 \
    --path-output-video /output/example_video.mp4

will create a video /output/example_video.mp4 that includes pseudo ground truth, raw, and restored thermal images side-by-side, labeled by type, and annotated with detected corners and per-frame metrics.

Dataset Preparation

In this section, we describe the steps that we took to prepare our dataset for use with TRNeRF. If you want to run TRNeRF with a custom dataset, you may need to adapt these steps. Note that these steps do not include calibration and timestamp synchronization. It is assumed that the data is already precisely time synchronized and that accurate calibration results are available.

Pseudo Ground Truth Pose Generation

Run the trnerf_training Docker image as described above. To compute the pseudo ground truth poses for all sequences we've provided the run_generate_poses.sh bash script that can be executed in the container as follows:

/home/user/trnerf/scripts/pseudo_gt_generation/run_generate_poses.sh /output/ /data/

The result will be one file for each sequence following the pattern /output/<speed>_<scene>/pseudo_ground_truth_poses.h5 that contains the pseudo ground truth poses. There will also be a folder, /output/pose_estimation, that contains intermediate outputs that are used below but can otherwise be deleted.

Pseudo Ground Truth Image Generation

Run the trnerf_training Docker image as described above. To compute the pseudo ground truth images for both cameras in the medium and fast sequences we've provided the run_generate_images.sh bash script that can be executed in the container as follows:

/home/user/trnerf/scripts/pseudo_gt_generation/run_generate_images.sh /output/ /data/

The result will be two files (one for each camera) for each medium and fast sequence following the pattern /output/<speed>_<scene>/pseudo_ground_truth_adk_<camera>.h5 and for each slow sequence following the pattern /output/<speed>_<scene>/two_point_nuc_results_adk_<camera>.h5. The pseudo_ground_truth_adk_<camera>.h5 files contain the pseudo ground truth images, and the two_point_nuc_results_adk_<camera>.h5 contain the two point NUC results (pixelwise gains and offsets) that were used in generating the pseudo ground truth images. There will also be a folder, /output/training_w_two_point_output, that contains intermediate outputs and can be deleted.

Determining Scene Specific Arguments

There are scene specific arguments which are hardcoded in run_training.sh and other bash scripts. This section details how they were determined.

The --rotation, --translation, and --scale-factor arguments are used by the TRNeRF data parser to transform the camera poses such that the poses (and the scene) fit (almost entirely) within the scene box (a cube with side length 2 centered about the origin). The script visualize_scene_box.py can be used to determine these arguments by visualizing how well they transform the COLMAP estimated poses and point cloud into the scene box. For example, the following produces this visualization for the medium indoor sequence:

python3 /home/user/trnerf/dataset_prep/visualize_scene_box.py \
    --path-poses /data/medium_indoor/pseudo_ground_truth_poses.h5 \
    --path-colmap-model /output/pose_estimation/colmap/indoor/sparse/0/ \
    --name-camera adk_right \
    --path-calibration-results /data/cam_calibration/camchain.yaml \
    --rotation 0.0 0.0 0.0 \
    --translation -0.37 -1.875 -0.95 \
    --scale-factor 0.35

Note that this script requires the COLMAP model produced during the pseudo ground truth pose generation to visualize the point cloud estimate of the scene.

As described in the paper, the thermal image thresholds used during training are set to the minimum and maximum values observed in the each scene. Similarly, the thermal image thresholds used for visualization and evaluation are set to the 0.1 and 99.9 percentiles. The script compute_thresholds.py can be used to compute these thresholds across multiple sequences. For example, the following computes the thresholds used for the indoor scene:

python3 /home/user/trnerf/dataset_prep/compute_thresholds.py \
    --paths-image-file \
        /data/slow_indoor/adk_right.h5 \
        /data/medium_indoor/adk_right.h5 \
        /data/fast_indoor/adk_right.h5 \
    --paths-poses \
        /data/slow_indoor/pseudo_ground_truth_poses.h5 \
        /data/medium_indoor/pseudo_ground_truth_poses.h5 \
        /data/fast_indoor/pseudo_ground_truth_poses.h5

Note that the pose files are required only to determine the subset of images that are to be used for training.

Citation

@InProceedings{trnerf_2025,
    author    = {Carmichael, Spencer and Bhat, Manohar and Ramanagopal, Mani and Buchan, Austin and Vasudevan, Ram and Skinner, Katherine A.},
    title     = {{TRNeRF}: Restoring Blurry, Rolling Shutter, and Noisy Thermal Images with Neural Radiance Fields},
    booktitle = {Proceedings of the Winter Conference on Applications of Computer Vision (WACV)},
    month     = {February},
    year      = {2025},
    pages     = {7969-7979}
}

License

TRNeRF, by the UM & Ford Center for Autonomous Vehicles (FCAV), is licensed under CC BY-NC-SA 4.0. For inquiries about commercial licensing, please reach out to the authors.

About

[WACV 2025] TRNeRF: Restoring Blurry, Rolling Shutter, and Noisy Thermal Images with Neural Radiance Fields

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors