Tejaswi Tripathi commited on
Commit Β·
cec4d26
1
Parent(s): 83aacdb
Updated README
Browse files
README.md
CHANGED
|
@@ -11,4 +11,196 @@ pinned: false
|
|
| 11 |
short_description: An improved portrait mode renderer for pictures.
|
| 12 |
---
|
| 13 |
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
short_description: An improved portrait mode renderer for pictures.
|
| 12 |
---
|
| 13 |
|
| 14 |
+
# Physically-Based Portrait Mode Engine
|
| 15 |
+
|
| 16 |
+
A Gradio demo that simulates **shallow depth-of-field** (portrait mode) on ordinary photos. Instead of applying a flat Gaussian blur to the background, it estimates scene depth, builds a **circle-of-confusion (CoC)** map, and uses a trained neural renderer (**RendererNet**) to produce physically motivated defocus. In-focus regions are preserved by blending the render back onto the original image.
|
| 17 |
+
|
| 18 |
+
The app is designed to run as a [Hugging Face Space](https://huggingface.co/docs/hub/spaces) and is self-contained: model definitions and inference code live in a single `app.py` file.
|
| 19 |
+
|
| 20 |
+
## What it does
|
| 21 |
+
|
| 22 |
+
Given an input photograph and camera parameters (f-stop, focal length), the pipeline:
|
| 23 |
+
|
| 24 |
+
1. **Estimates relative depth** with [Depth Anything V2](https://huggingface.co/depth-anything/Depth-Anything-V2-Base-hf) via the Hugging Face `transformers` library.
|
| 25 |
+
2. **Builds a pseudo CoC map** by measuring how far each pixel's depth deviates from the depth at the **image center** (the assumed focus point). Pixels closer to the focus depth get a CoC near zero; pixels farther away get larger CoC values.
|
| 26 |
+
3. **Renders defocus with RendererNet**, a U-Net that takes the RGB image plus normalized f-stop, focal length, and CoC channels and outputs a blurred RGB image at the chosen aperture settings.
|
| 27 |
+
4. **Blends the NN render onto the original** using a smooth CoC-based weight so that in-focus areas (CoC below a threshold) remain untouched.
|
| 28 |
+
5. **Produces a non-NN baseline** for comparison: a flat Gaussian blur applied only where CoC exceeds a separate threshold.
|
| 29 |
+
|
| 30 |
+
Three outputs are shown:
|
| 31 |
+
|
| 32 |
+
| Output | Description |
|
| 33 |
+
|--------|-------------|
|
| 34 |
+
| **Rendered (NN)** | RendererNet defocus, blended with the original in in-focus regions |
|
| 35 |
+
| **Gaussian baseline** | Simple background blur for comparison against the learned renderer |
|
| 36 |
+
| **Pseudo CoC map** | Colorized circle-of-confusion visualization (inferno colormap) |
|
| 37 |
+
|
| 38 |
+
## Pipeline overview
|
| 39 |
+
|
| 40 |
+
```
|
| 41 |
+
Input image
|
| 42 |
+
β
|
| 43 |
+
βΌ
|
| 44 |
+
Resize (longest side β€ 1024 px)
|
| 45 |
+
β
|
| 46 |
+
βΌ
|
| 47 |
+
Depth Anything V2 βββΊ relative depth [0, 1]
|
| 48 |
+
β
|
| 49 |
+
βΌ
|
| 50 |
+
Pseudo CoC map (focus = image center, max 4 px)
|
| 51 |
+
β
|
| 52 |
+
ββββββββββββββββββββββββββββββββ
|
| 53 |
+
βΌ βΌ
|
| 54 |
+
RendererNet (512Γ512) Gaussian blur baseline
|
| 55 |
+
f-stop + focal length + CoC (CoC > threshold)
|
| 56 |
+
β β
|
| 57 |
+
βΌ β
|
| 58 |
+
CoC-weighted blend βββββββββββββββββ
|
| 59 |
+
β
|
| 60 |
+
βΌ
|
| 61 |
+
Final outputs (NN render, baseline, CoC map)
|
| 62 |
+
```
|
| 63 |
+
|
| 64 |
+
### Pseudo CoC
|
| 65 |
+
|
| 66 |
+
Because the demo has no interactive focus point, focus is fixed at the **center of the image** (`h // 2`, `w // 2`). The CoC at each pixel is proportional to the absolute difference between that pixel's relative depth and the depth at the focus point, scaled to a maximum of **4 px** (`COC_MAX_PX`).
|
| 67 |
+
|
| 68 |
+
### RendererNet input
|
| 69 |
+
|
| 70 |
+
RendererNet is a U-Net with **6 input channels** and **3 output channels** (RGB):
|
| 71 |
+
|
| 72 |
+
| Channel(s) | Content |
|
| 73 |
+
|------------|---------|
|
| 74 |
+
| 0β2 | RGB image, resized to 512Γ512 |
|
| 75 |
+
| 3 | f-stop map, normalized by `F_STOP_MAX` (22.0) |
|
| 76 |
+
| 4 | Focal length map, normalized by `FOCAL_LENGTH_MM_MAX` (200.0) |
|
| 77 |
+
| 5 | CoC map, clipped to [0, 25] px and normalized by `COC_PX_NORM` (25.0) |
|
| 78 |
+
|
| 79 |
+
The network output is resized back to the working resolution and blended with the original using a smoothstep weight derived from the CoC map and the **in-focus CoC threshold** slider.
|
| 80 |
+
|
| 81 |
+
### Blending
|
| 82 |
+
|
| 83 |
+
The blend weight uses a smoothstep on CoC values above the focus threshold, so transitions between sharp and blurred regions are gradual rather than hard-edged. Where CoC is near zero, the original pixels are kept; where CoC is large, the RendererNet output dominates.
|
| 84 |
+
|
| 85 |
+
## Models
|
| 86 |
+
|
| 87 |
+
### Depth Anything V2
|
| 88 |
+
|
| 89 |
+
- **Default checkpoint:** `depth-anything/Depth-Anything-V2-Base-hf`
|
| 90 |
+
- Loaded at startup via `AutoImageProcessor` and `AutoModelForDepthEstimation` from `transformers`.
|
| 91 |
+
- Returns relative (not metric) depth, normalized per image to [0, 1].
|
| 92 |
+
- Requires **torch** and **torchvision**.
|
| 93 |
+
|
| 94 |
+
Swap to a different variant via the `DEPTH_MODEL_ID` environment variable:
|
| 95 |
+
|
| 96 |
+
| Model ID | Trade-off |
|
| 97 |
+
|----------|-----------|
|
| 98 |
+
| `depth-anything/Depth-Anything-V2-Small-hf` | Faster, lower quality β good for CPU Spaces |
|
| 99 |
+
| `depth-anything/Depth-Anything-V2-Base-hf` | Default; balanced speed and quality |
|
| 100 |
+
| `depth-anything/Depth-Anything-V2-Large-hf` | Best quality, slowest |
|
| 101 |
+
|
| 102 |
+
### RendererNet
|
| 103 |
+
|
| 104 |
+
- A U-Net architecture (inlined in `app.py`) trained to render defocus given RGB + camera parameters + CoC.
|
| 105 |
+
- Weights are loaded from **`renderer/best_renderer.pth`** by default.
|
| 106 |
+
- Can alternatively be fetched from the Hugging Face Hub when `RENDERER_REPO_ID` is set.
|
| 107 |
+
|
| 108 |
+
## Using the demo
|
| 109 |
+
|
| 110 |
+
1. Upload an image (JPEG or PNG).
|
| 111 |
+
2. Adjust **f-stop** (0.95β22.0) β lower values produce stronger background blur.
|
| 112 |
+
3. Adjust **focal length** (4β200 mm) β longer focal lengths increase the shallow-DoF effect.
|
| 113 |
+
4. Tune **in-focus CoC threshold** β pixels with CoC below this value suppress the NN render and keep the original sharp.
|
| 114 |
+
5. Optionally expand **Gaussian baseline** to configure the comparison blur (CoC threshold and sigma).
|
| 115 |
+
6. Click **Render**.
|
| 116 |
+
|
| 117 |
+
If a `cache/` directory with example images exists, sample images appear in the Examples panel.
|
| 118 |
+
|
| 119 |
+
## Configuration
|
| 120 |
+
|
| 121 |
+
All settings below can be overridden with environment variables (useful for Hugging Face Space **Settings β Repository secrets / Variables** without editing code).
|
| 122 |
+
|
| 123 |
+
| Variable | Default | Description |
|
| 124 |
+
|----------|---------|-------------|
|
| 125 |
+
| `DEPTH_MODEL_ID` | `depth-anything/Depth-Anything-V2-Base-hf` | Hugging Face model ID for depth estimation |
|
| 126 |
+
| `RENDERER_LOCAL_PATH` | `renderer/best_renderer.pth` | Path to RendererNet weights on disk |
|
| 127 |
+
| `RENDERER_REPO_ID` | *(empty)* | Hugging Face repo to download weights from |
|
| 128 |
+
| `RENDERER_FILENAME` | `best_renderer.pth` | Filename within the Hub repo |
|
| 129 |
+
| `HF_TOKEN` | *(empty)* | Token for private Hub repos (only needed with `RENDERER_REPO_ID`) |
|
| 130 |
+
|
| 131 |
+
### Internal constants
|
| 132 |
+
|
| 133 |
+
These are fixed in code and must match RendererNet's training setup:
|
| 134 |
+
|
| 135 |
+
| Constant | Value | Purpose |
|
| 136 |
+
|----------|-------|---------|
|
| 137 |
+
| `F_STOP_MAX` | 22.0 | f-stop normalization divisor |
|
| 138 |
+
| `FOCAL_LENGTH_MM_MAX` | 200.0 | Focal length normalization divisor |
|
| 139 |
+
| `COC_PX_NORM` | 25.0 | CoC channel clip and normalize |
|
| 140 |
+
| `TARGET_SIZE` | 512 | RendererNet spatial resolution |
|
| 141 |
+
| `COC_MAX_PX` | 4.0 | Maximum pseudo CoC magnitude |
|
| 142 |
+
| `MAX_SIDE` | 1024 | Longest image side before inference |
|
| 143 |
+
|
| 144 |
+
## Local development
|
| 145 |
+
|
| 146 |
+
### Requirements
|
| 147 |
+
|
| 148 |
+
- Python 3.10+ (3.13 on Hugging Face Spaces)
|
| 149 |
+
- CUDA optional (falls back to CPU)
|
| 150 |
+
|
| 151 |
+
### Install and run
|
| 152 |
+
|
| 153 |
+
```bash
|
| 154 |
+
git clone https://github.com/<your-username>/Physically-Based-Portrait-Mode-Engine.git
|
| 155 |
+
cd Physically-Based-Portrait-Mode-Engine
|
| 156 |
+
|
| 157 |
+
pip install -r requirements.txt
|
| 158 |
+
|
| 159 |
+
# Ensure RendererNet weights are present
|
| 160 |
+
# (renderer/best_renderer.pth is included in the repo)
|
| 161 |
+
|
| 162 |
+
python app.py
|
| 163 |
+
```
|
| 164 |
+
|
| 165 |
+
Gradio will print a local URL (typically `http://127.0.0.1:7860`).
|
| 166 |
+
|
| 167 |
+
### Dependencies
|
| 168 |
+
|
| 169 |
+
```
|
| 170 |
+
gradio>=4.44.0
|
| 171 |
+
torch>=2.1.0
|
| 172 |
+
torchvision>=0.16.0
|
| 173 |
+
transformers>=4.45.0
|
| 174 |
+
huggingface_hub>=0.24.0
|
| 175 |
+
numpy>=1.26.0
|
| 176 |
+
pillow>=10.0.0
|
| 177 |
+
scikit-image>=0.22.0
|
| 178 |
+
matplotlib>=3.7.0
|
| 179 |
+
```
|
| 180 |
+
|
| 181 |
+
On first run, Depth Anything V2 weights are downloaded from the Hugging Face Hub (~370 MB for the Base model).
|
| 182 |
+
|
| 183 |
+
## Project structure
|
| 184 |
+
|
| 185 |
+
```
|
| 186 |
+
.
|
| 187 |
+
βββ app.py # Gradio app, RendererNet definition, full inference pipeline
|
| 188 |
+
βββ requirements.txt # Python dependencies
|
| 189 |
+
βββ renderer/
|
| 190 |
+
β βββ best_renderer.pth # Trained RendererNet weights
|
| 191 |
+
βββ cache/ # Optional example images for Gradio Examples
|
| 192 |
+
```
|
| 193 |
+
|
| 194 |
+
## Limitations
|
| 195 |
+
|
| 196 |
+
- **Fixed focus point:** Focus is always the image center; there is no click-to-focus or subject detection.
|
| 197 |
+
- **Relative depth only:** Depth Anything V2 outputs ordinal depth, not metric distances, so the CoC map is a heuristic rather than a physically exact optical simulation.
|
| 198 |
+
- **Resolution cap:** Images are downscaled so the longest side is at most 1024 px to keep CPU inference responsive.
|
| 199 |
+
- **RendererNet runs at 512Γ512:** Fine detail may be softened; output is upsampled to the working resolution.
|
| 200 |
+
- **CPU Spaces are slow:** First inference after startup can take tens of seconds; consider the Small depth model or a GPU Space for faster turnaround.
|
| 201 |
+
|
| 202 |
+
## Acknowledgments
|
| 203 |
+
|
| 204 |
+
- [Depth Anything V2](https://github.com/DepthAnything/Depth-Anything-V2) β monocular depth estimation ([Lihe Yang et al.](https://huggingface.co/depth-anything/Depth-Anything-V2-Base-hf))
|
| 205 |
+
- [Hugging Face Transformers](https://github.com/huggingface/transformers) β model loading and inference
|
| 206 |
+
- [Gradio](https://gradio.app/) β web UI
|