---
title: "Own models & training"
url: https://phatdev.net/en/docs/pixgamma/model-rieng
lang: en
updated: 2026-10-22
alternate:
  vi: https://phatdev.net/docs/pixgamma/model-rieng
markdown: https://phatdev.net/en/docs/pixgamma/model-rieng.md
---

# Own models & training

Part of the doc set: [PixGamma](https://phatdev.net/en/docs/pixgamma.md)

> PixGamma Photo v2 and v1, the benchmark of public models, versions tried and the training toolkit.

PixGamma has its own models, trained on the Mac with [traiNNer-redux](https://github.com/the-database/traiNNer-redux) on the GPU (MPS) and converted to Core ML. A model only ships when it beats the current one on **both benchmarks**: the scored photo set and a full-pipeline run on real photos.

<div style="margin:1.6em 0"><figure style="margin:0"><a href="https://phatdev.net/uploads/p/pixgamma/benchmark-vi-light-3840.webp" target="_blank" rel="noopener" class="pd-th-light" style="display:block;border:0" aria-label="DISTS on 40 photos never used for training: PixGamma Photo v1 against 9 public models (4K)"><img src="https://phatdev.net/uploads/p/pixgamma/benchmark-vi-light-1920.webp" srcset="/uploads/p/pixgamma/benchmark-vi-light-960.webp 960w, /uploads/p/pixgamma/benchmark-vi-light-1920.webp 1920w, /uploads/p/pixgamma/benchmark-vi-light-3840.webp 3840w" sizes="(max-width: 900px) 100vw, 760px" width="3840" height="2160" alt="DISTS on 40 photos never used for training: PixGamma Photo v1 against 9 public models" loading="lazy" decoding="async" style="width:100%;height:auto;display:block;border:1px solid var(--line);border-radius:12px"></a><a href="https://phatdev.net/uploads/p/pixgamma/benchmark-vi-dark-3840.webp" target="_blank" rel="noopener" class="pd-th-dark" style="display:block;border:0" aria-label="DISTS on 40 photos never used for training: PixGamma Photo v1 against 9 public models (4K)"><img src="https://phatdev.net/uploads/p/pixgamma/benchmark-vi-dark-1920.webp" srcset="/uploads/p/pixgamma/benchmark-vi-dark-960.webp 960w, /uploads/p/pixgamma/benchmark-vi-dark-1920.webp 1920w, /uploads/p/pixgamma/benchmark-vi-dark-3840.webp 3840w" sizes="(max-width: 900px) 100vw, 760px" width="3840" height="2160" alt="DISTS on 40 photos never used for training: PixGamma Photo v1 against 9 public models" loading="lazy" decoding="async" style="width:100%;height:auto;display:block;border:1px solid var(--line);border-radius:12px"></a><figcaption style="margin-top:8px;font-size:13px;line-height:1.5;color:var(--muted);text-align:center">DISTS on 40 photos never used for training: PixGamma Photo v1 against 9 public models</figcaption></figure></div>

## Choosing a base model

PixGamma scored highly rated public 4x models (Hugging Face, OpenModelDB, GitHub) on 40 photos never used for training: 22 laptop shots plus portraits, animals, fabric and leather. The main metric is **DISTS** (texture similarity, lower is better), alongside PSNR.

| 4x model | DISTS |
|---|---|
| **PixGamma Photo v2** | **0.164** |
| PixGamma Photo v1 | 0.165 |
| 4xBHI_dat2_real (base of Photo v1) | 0.173 |
| UltraSharpV2 Lite | 0.176 |
| RealWebPhoto ATD | 0.176 |
| UltraSharpV2 | 0.177 |
| RealWebPhoto DAT2 | 0.179 |
| 4xBHI RealPLKSR | 0.180 |
| Real-ESRGAN x4plus | 0.186 |
| 4xNomosWebPhoto (Photo model in 0.1) | 0.199 |

PSNR on the same set: PixGamma Photo v1 30.5 dB, 4xBHI_dat2_real 29.0 dB, 4xNomosWebPhoto 26.9 dB.

## PixGamma Photo v2 (default photo model)

<div style="margin:1.6em 0"><figure style="margin:0"><a href="https://phatdev.net/uploads/p/pixgamma/compare-fur-v2b-vi-light-3840.webp" target="_blank" rel="noopener" class="pd-th-light" style="display:block;border:0" aria-label="PixGamma Photo v2: a cat from 480 px to 4x next to the 1920 px original; clearer fur than the input, but not yet strand-for-strand like the original (4K)"><img src="https://phatdev.net/uploads/p/pixgamma/compare-fur-v2b-vi-light-1920.webp" srcset="/uploads/p/pixgamma/compare-fur-v2b-vi-light-960.webp 960w, /uploads/p/pixgamma/compare-fur-v2b-vi-light-1920.webp 1920w, /uploads/p/pixgamma/compare-fur-v2b-vi-light-3840.webp 3840w" sizes="(max-width: 900px) 100vw, 760px" width="3840" height="2160" alt="PixGamma Photo v2: a cat from 480 px to 4x next to the 1920 px original; clearer fur than the input, but not yet strand-for-strand like the original" loading="lazy" decoding="async" style="width:100%;height:auto;display:block;border:1px solid var(--line);border-radius:12px"></a><a href="https://phatdev.net/uploads/p/pixgamma/compare-fur-v2b-vi-dark-3840.webp" target="_blank" rel="noopener" class="pd-th-dark" style="display:block;border:0" aria-label="PixGamma Photo v2: a cat from 480 px to 4x next to the 1920 px original; clearer fur than the input, but not yet strand-for-strand like the original (4K)"><img src="https://phatdev.net/uploads/p/pixgamma/compare-fur-v2b-vi-dark-1920.webp" srcset="/uploads/p/pixgamma/compare-fur-v2b-vi-dark-960.webp 960w, /uploads/p/pixgamma/compare-fur-v2b-vi-dark-1920.webp 1920w, /uploads/p/pixgamma/compare-fur-v2b-vi-dark-3840.webp 3840w" sizes="(max-width: 900px) 100vw, 760px" width="3840" height="2160" alt="PixGamma Photo v2: a cat from 480 px to 4x next to the 1920 px original; clearer fur than the input, but not yet strand-for-strand like the original" loading="lazy" decoding="async" style="width:100%;height:auto;display:block;border:1px solid var(--line);border-radius:12px"></a><figcaption style="margin-top:8px;font-size:13px;line-height:1.5;color:var(--muted);text-align:center">PixGamma Photo v2: a cat from 480 px to 4x next to the 1920 px original; clearer fur than the input, but not yet strand-for-strand like the original</figcaption></figure></div>

- Photo v1 trained further with a **light GAN** for crisper fur, hair and fabric grain.
- DISTS on the 40-photo set: **0.164** (v1: 0.165); on sharp photos: **0.170** (v1: 0.183).
- **Text regions keep Photo v1** (no GAN), so the GAN never draws letter strokes.
- A second round with a stronger GAN scored worse and is not shipped.
- Photo v2 is a 4x model; 2x upscales still use SPAN.

## PixGamma Photo v1

- **DAT2** architecture, fine-tuned for 15,000 iterations from 4xBHI_dat2_real (Philip Hofmann, CC-BY-4.0).
- Data: CC0 and public-domain photos from Wikimedia Commons, with artwork and sensitive images filtered out and the benchmark photos excluded. Half of the low-resolution inputs go through a **downscale + double JPEG chain** like web images; 2,500 synthetic text tiles keep strokes intact.
- Losses: Charbonnier and MS-SSIM (pixel accuracy), LDL (artifact suppression), focal frequency (high frequencies), DISTS (real texture). **No GAN**, so the model does not invent texture.
- Result: the base DAT2 brightens images by about one gray level and shifts dark areas; v1 shows almost no color drift.

## Tried and not shipped

| Version | Tried | Why not |
|---|---|---|
| First Photo v2 (0.2.1) | v1 plus a light GAN, used on text too | Broken small text, jagged key edges; the current build keeps text regions on Photo v1 |
| Photo v2 round 2 | A stronger GAN | Scored worse than the shipped v2 |
| Text v4 | Text model with thin white strokes | Sharper but read 4.3 px capitals worse |
| Photo v1 for 2x | 4x then shrink to 2x | Lost to SPAN 2x on 5 of 6 photos in the full pipeline |

## Text model

0.2.0 used a dedicated text model (RealPLKSR fine-tuned from 4xNomosWebPhoto in three rounds on synthetic Vietnamese and English text: 114 fonts with Vietnamese, random syllables covering every diacritic combination, banners, labels, keyboards). Since 0.2.1 text regions use Photo v1, which reads better; the text model stays in the app as a fallback.

## Tooling

| Script | Does |
|---|---|
| `training/fetch_commons.py` | Downloads CC0 and public-domain photos from Wikimedia Commons with credits |
| `training/prepare_dataset.py` | Cuts tiles and builds low-resolution inputs with a web-like degradation chain |
| `training/make_text_dataset.py` | Generates Vietnamese and English text tiles |
| `training/evaluate.py` | Scores PSNR, DISTS and color drift |
| `training/eval_text.py`, `eval_text_pipeline.py` | Score text with per-line, per-size OCR |
| `tools/convert_extra.py` | Converts checkpoints to Core ML and checks the difference against PyTorch |

Every base model has an open license (CC-BY-4.0, BSD-3-Clause, Apache-2.0, MIT, OpenRAIL-M); CodeFormer is non-commercial only.
