Initial release
Browse files- README.md +121 -0
- config.yaml +68 -0
- model.safetensors +3 -0
README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: cc-by-nc-4.0
|
| 3 |
+
tags:
|
| 4 |
+
- relighting
|
| 5 |
+
- inverse-rendering
|
| 6 |
+
- pbr
|
| 7 |
+
- image-to-image
|
| 8 |
+
- pytorch
|
| 9 |
+
pipeline_tag: image-to-image
|
| 10 |
+
library_name: pytorch
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
# PIXLRelight
|
| 14 |
+
|
| 15 |
+
PIXLRelight is a feed-forward model for physically controllable single-image relighting. Given a source photograph and a target lighting condition — specified either as an RGB image or as a path-traced Blender Cycles render — it produces a relit version of the source under the new illumination in under a tenth of a second.
|
| 16 |
+
|
| 17 |
+
This repository hosts the trained model checkpoint and matching configuration. Full code, training details, and additional results are on the [project page](https://mlfarinha.github.io/pixl-relight/).
|
| 18 |
+
|
| 19 |
+
## Abstract
|
| 20 |
+
|
| 21 |
+
We present PIXLRelight, a feed-forward approach for physically controllable single-image relighting. Existing methods either provide limited lighting control (e.g. through text or environment maps), accumulate errors when chaining inverse and forward rendering, or require costly per-image optimization. Our key idea is to bridge physically based rendering (PBR) and learned image synthesis through a shared intrinsic conditioning that can be obtained from either real photographs or PBR renders. At training time, paired multi-illumination photographs are decomposed into albedo, diffuse shading, and non-diffuse residuals, which condition the model. At inference time, the same conditioning is computed from a path-traced render of a coarse 3D reconstruction of the input under user-specified PBR lights. A transformer-based neural renderer then applies the target illumination to the source photograph, preserving fine image detail through a per-pixel affine modulation. PIXLRelight enables arbitrary PBR-style lighting control, achieves state-of-the-art relighting quality, and runs in under a tenth of a second per image.
|
| 22 |
+
|
| 23 |
+
## Files
|
| 24 |
+
|
| 25 |
+
- `model.safetensors` — model weights
|
| 26 |
+
- `config.yaml` — OmegaConf config defining the model architecture (`net`, `head`, `rgbx` submodules)
|
| 27 |
+
|
| 28 |
+
## Quick start
|
| 29 |
+
|
| 30 |
+
### Command line
|
| 31 |
+
|
| 32 |
+
After cloning the [GitHub repository](https://github.com/mlfarinha/pixl-relight) and installing its requirements, place each sample in its own directory:
|
| 33 |
+
|
| 34 |
+
samples/
|
| 35 |
+
├── room00/
|
| 36 |
+
│ ├── source.jpg
|
| 37 |
+
│ └── target.jpg # target lighting as an RGB image
|
| 38 |
+
├── room01/
|
| 39 |
+
│ ├── source.jpg
|
| 40 |
+
│ └── target.jpg # target lighting as an RGB image
|
| 41 |
+
├── room02/
|
| 42 |
+
│ ├── source.jpg
|
| 43 |
+
│ ├── diffuse_color.exr # ...or as Blender Cycles passes
|
| 44 |
+
│ ├── diffuse_direct.exr
|
| 45 |
+
│ ├── diffuse_indirect.exr
|
| 46 |
+
│ ├── glossy_color.exr
|
| 47 |
+
│ ├── glossy_direct.exr
|
| 48 |
+
│ ├── glossy_indirect.exr
|
| 49 |
+
│ ├── transmission_color.exr
|
| 50 |
+
│ ├── transmission_direct.exr
|
| 51 |
+
│ ├── transmission_indirect.exr
|
| 52 |
+
│ ├── volume_direct.exr
|
| 53 |
+
│ ├── volume_indirect.exr
|
| 54 |
+
│ ├── environment.exr
|
| 55 |
+
│ └── emission.exr
|
| 56 |
+
├── room03/
|
| 57 |
+
│ └── ...
|
| 58 |
+
└── ...
|
| 59 |
+
|
| 60 |
+
Then run:
|
| 61 |
+
|
| 62 |
+
python infer.py --input_dir samples/ --output_dir outputs/
|
| 63 |
+
|
| 64 |
+
The model and config are downloaded from this repository on first run and cached locally.
|
| 65 |
+
|
| 66 |
+
### Python
|
| 67 |
+
|
| 68 |
+
```python
|
| 69 |
+
from huggingface_hub import hf_hub_download
|
| 70 |
+
from omegaconf import OmegaConf
|
| 71 |
+
from safetensors.torch import load_file
|
| 72 |
+
|
| 73 |
+
from src.utils.cfg import create_object
|
| 74 |
+
|
| 75 |
+
REPO_ID = "mlfarinha/pixlrelight"
|
| 76 |
+
|
| 77 |
+
config_path = hf_hub_download(repo_id=REPO_ID, filename="config.yaml")
|
| 78 |
+
ckpt_path = hf_hub_download(repo_id=REPO_ID, filename="model.safetensors")
|
| 79 |
+
|
| 80 |
+
cfg = OmegaConf.load(config_path)
|
| 81 |
+
model = create_object(cfg.model)
|
| 82 |
+
model.load_state_dict(load_file(ckpt_path), strict=False)
|
| 83 |
+
model.cuda().eval()
|
| 84 |
+
|
| 85 |
+
# Target lighting as an RGB image (decomposed on the fly).
|
| 86 |
+
relit = model.inference(
|
| 87 |
+
source_images="source.jpg",
|
| 88 |
+
target_images="target.jpg",
|
| 89 |
+
output_type="pil",
|
| 90 |
+
)
|
| 91 |
+
relit[0].save("relit.png")
|
| 92 |
+
|
| 93 |
+
# Or as a directory of Blender Cycles render passes.
|
| 94 |
+
relit = model.inference(
|
| 95 |
+
source_images="source.jpg",
|
| 96 |
+
cycles="path/to/cycles_passes/",
|
| 97 |
+
output_type="pil",
|
| 98 |
+
)
|
| 99 |
+
relit[0].save("relit.png")
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
## Limitations
|
| 103 |
+
|
| 104 |
+
PIXLRelight is trained on indoor scenes and relights at the source's native resolution by applying a per-pixel affine modulation. The model does not synthesise content not present in the source — strong cast shadows or specular highlights that change the visible surface geometry may not transfer faithfully.
|
| 105 |
+
|
| 106 |
+
## Citation
|
| 107 |
+
|
| 108 |
+
If you use PIXLRelight in your work, please cite:
|
| 109 |
+
|
| 110 |
+
```bibtex
|
| 111 |
+
@article{farinha2026pixlrelight,
|
| 112 |
+
title = {PIXLRelight: Controllable Relighting via Intrinsic Conditioning},
|
| 113 |
+
author = {Farinha, Miguel and Clark, Ronald},
|
| 114 |
+
journal = {arXiv preprint arXiv:2605.18735},
|
| 115 |
+
year = {2026}
|
| 116 |
+
}
|
| 117 |
+
```
|
| 118 |
+
|
| 119 |
+
## License
|
| 120 |
+
|
| 121 |
+
This model is released under the [Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)](https://creativecommons.org/licenses/by-nc/4.0/) license. The model weights and configuration may be used for research and personal purposes with attribution, but not for commercial purposes.
|
config.yaml
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
model:
|
| 2 |
+
__object__:
|
| 3 |
+
path: src.models.pixl_relight
|
| 4 |
+
name: PIXLRelight
|
| 5 |
+
args: as_params
|
| 6 |
+
|
| 7 |
+
net:
|
| 8 |
+
__object__:
|
| 9 |
+
path: src.models.net
|
| 10 |
+
name: Net
|
| 11 |
+
args: as_params
|
| 12 |
+
|
| 13 |
+
img_size: 512
|
| 14 |
+
patch_size: 16
|
| 15 |
+
pos_embed_rope_base: 100.0
|
| 16 |
+
pos_embed_rope_min_period: null
|
| 17 |
+
pos_embed_rope_max_period: null
|
| 18 |
+
pos_embed_rope_normalize_coords: separate
|
| 19 |
+
pos_embed_rope_shift_coords: null
|
| 20 |
+
pos_embed_rope_jitter_coords: null
|
| 21 |
+
pos_embed_rope_rescale_coords: null
|
| 22 |
+
pos_embed_rope_dtype: bf16
|
| 23 |
+
embed_dim: 1024
|
| 24 |
+
depth: 24
|
| 25 |
+
num_heads: 16
|
| 26 |
+
ffn_ratio: 4.0
|
| 27 |
+
qkv_bias: True
|
| 28 |
+
drop_path_rate: 0.0
|
| 29 |
+
layerscale_init: 1.0
|
| 30 |
+
norm_layer: layernormbf16
|
| 31 |
+
n_storage_tokens: 8
|
| 32 |
+
mask_k_bias: False
|
| 33 |
+
qk_norm: True
|
| 34 |
+
rgb_patch_embed: vit_large
|
| 35 |
+
intrinsics_patch_embed: convnext_base
|
| 36 |
+
intermediate_layer_idx: [4, 11, 17, 23]
|
| 37 |
+
gradient_checkpointing: False
|
| 38 |
+
|
| 39 |
+
head:
|
| 40 |
+
__object__:
|
| 41 |
+
path: src.models.head
|
| 42 |
+
name: DPTHead
|
| 43 |
+
args: as_params
|
| 44 |
+
|
| 45 |
+
dim_in: 1024
|
| 46 |
+
patch_size: 16
|
| 47 |
+
output_dim: 6
|
| 48 |
+
activation: sigmoid
|
| 49 |
+
conf_activation: null
|
| 50 |
+
features: 256
|
| 51 |
+
out_channels: [256, 512, 1024, 1024]
|
| 52 |
+
pos_embed: True
|
| 53 |
+
head_name: rgb
|
| 54 |
+
output_mode: modulation
|
| 55 |
+
modulation_clamp: True
|
| 56 |
+
|
| 57 |
+
rgbx:
|
| 58 |
+
__object__:
|
| 59 |
+
path: src.rgbx.inference
|
| 60 |
+
name: Marigold
|
| 61 |
+
args: as_params
|
| 62 |
+
|
| 63 |
+
checkpoint_path: prs-eth/marigold-iid-lighting-v1-1
|
| 64 |
+
denoise_steps: 1
|
| 65 |
+
processing_res: 0
|
| 66 |
+
half_precision: True
|
| 67 |
+
output_processing_res: True
|
| 68 |
+
resample_method: bilinear
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:69c2bd11c2f272754f7080bc33e4b049fd334ea5d596df0c475f51c93699710e
|
| 3 |
+
size 2563499816
|