Yash Kulthe1, Andrew Gilbert1, John Collomosse1,2
1CVSSP, University of Surrey, UK 2Adobe Research
We present MultiNeRF, a 3D watermarking method that embeds multiple uniquely keyed watermarks within images rendered by a single Neural Radiance Field (NeRF) model, whilst maintaining high visual quality. Our approach extends the TensoRF NeRF model by incorporating a dedicated watermark grid alongside the existing geometry and appearance grids. This extension ensures higher watermark capacity without entangling watermark signals with scene content. We propose a FiLM-based conditional modulation mechanism that dynamically activates watermarks based on input identifiers, allowing multiple independent watermarks to be embedded and extracted without requiring model retraining. MultiNeRF is validated on the NeRF-Synthetic and LLFF datasets, with statistically significant improvements in robust capacity without compromising rendering quality. By generalizing single-watermark NeRF methods into a flexible multi-watermarking framework, MultiNeRF provides a scalable solution for 3D content attribution.
- Python 3.7+
- CUDA 11.6 or higher
- PyTorch 1.13+
- Clone the repository
git clone https://github.com/yash-research/MultiNeRF-code.git
cd MultiNeRF-code- Create conda environment
conda env create -f env.yml
conda activate multinerf| Dataset | Download Link | Extract to |
|---|---|---|
| NeRF-Synthetic | Google Drive | ./data/NeRF_dataset/syn/ |
| LLFF | Google Drive | ./data/NeRF_dataset/llff/ |
| Weights | Download Link | Place in |
|---|---|---|
| TensoRF Pre-trained | Google Drive | ./data/TensorRF_weights/ |
| Watermark Decoder | Google Drive | ./data/pretrained_decoder/ |
| Perceptual Loss | Google Drive | ./loss/losses/ |
| MultiNeRF Checkpoints | Google Drive | ./log/ |
Note: The checkpoint folder contains
model_weight/*.thandkeys.txtwhich are required for inference.
multinerf/
├── data/
│ ├── NeRF_dataset/
│ │ ├── syn/
│ │ │ ├── lego/
│ │ │ ├── chair/
│ │ │ └── ...
│ │ └── llff/
│ │ ├── fern/
│ │ └── ...
│ ├── TensorRF_weights/
│ │ └── lego.th
│ └── pretrained_decoder/
│ └── 16_256_decoder_whit.pth
├── loss/
│ └── losses/
│ └── rgb_watson_vgg_trial0.pth
├── configs/
├── models/
└── ...
Train MultiNeRF with multiple watermarks on the Lego scene:
python train_multinerf.py --config configs/multinerf_16bits_16multipleWM_lego.txtKey configuration parameters:
num_watermark: Number of watermarks to embed (default: 16)embedding_dim: Dimension of watermark embedding (default: 16)gpu_id: GPU device ID to use (default: 0)
Render images with a specific watermark:
python train_multinerf.py \
--config configs/multinerf_16bits_16multipleWM_lego.txt \
--ckpt ./log/multinerf_16bits_16multipleWM_lego/model_weight/*.th \
--test_name test_run \
--render_only_watermark 1 \
--render_test 1 \
--render_train 1 \
--watermark_num 0 \
--gpu_id 0Key rendering parameters:
--ckpt: Path to trained checkpoint--test_name: Name for the test output folder--render_only_watermark 1: Enable watermark rendering mode--render_test 1: Render test set images--render_train 1: Render training set images--watermark_num: Which watermark ID to render (0 to num_watermark-1)--gpu_id: GPU device ID
If you find this work useful, please cite:
@InProceedings{Kulthe_2025_ICCV,
author = {Kulthe, Yash and Gilbert, Andrew and Collomosse, John},
title = {MultiNeRF: Multiple Watermark Embedding for Neural Radiance Fields},
booktitle = {Proceedings of the IEEE/CVF International Conference on Computer Vision (ICCV) Workshops},
month = {October},
year = {2025},
pages = {1523-1532}
}This code builds upon several excellent works:
- TensoRF - Base NeRF implementation
- WateRF - NeRF watermarking framework
- Revisited HiDDeN implementation - Watermark decoder
- Add other bit decoders and pre-trained MultiNeRF checkpoints for different watermark capacities (8, 32, 48, 64 watermarks)
- Add robustness evaluation code
- Add demo Jupyter notebook for ease of use
- Add Apptainer/Docker container for easy setup

