Dit artikel presenteert de wiskunde achter Ansels reconstructie van hooglichten: het oorspronkelijke guided laplacians-ontwerp uit 2021, waarvan de algemene ideeën alleen ooit waren geschetst op het pixls.us-forum,1 en harmonische transpositie, de methode die het verving nadat een ground-truth-onderzoek een bug in het herstel van de magnitude aan het licht bracht.2 Het is zo opgebouwd dat elke lezer zijn eigen sectie vindt: de resultaten en de Intuïtie & achtergrond van elke methode vereisen geen wiskunde; ontwikkelaars vinden de Implementatie & optimalisaties-subsecties en het prestatie-onderzoek; de theoretische bevindingen en de kerkhofbijlage zijn geschreven om ook buiten de fotografie herbruikbaar te zijn; en hoe dit werk werkelijk is gedaan documenteert het mens–machine-onderzoeksprotocol erachter.

Samenvatting

Wanneer een camerasensor verzadigt, klippen de drie kleurkanalen niet op hetzelfde moment, dus een uitgebrand hoog licht verschuift van kleur, meestal richting magenta. Dit artikel documenteert Ansels reconstructie van hooglichten van begin tot eind en in de volgorde waarin het gebeurde: de oorspronkelijke guided laplacians uit 2021 (overdracht van wavelet-detail via een geleid filter, nooit eerder volledig opgeschreven), het ground-truth-onderzoek dat de magnitude-bug aan het licht bracht, en de methode die het verving — harmonische transpositie, die het lokale kleurlijnmodel van het geleide filter behoudt maar de coëfficiënten ervan over de uitgebrande zone draagt als vloeiend gediffundeerde velden, gestuurd door de structuur van de overlevende kanalen, de saturatie-rolloff van de sensor ontvertekent vóór het fitten, en elke frequentieband en pixelklasse toewijst aan de schatter die daar meetbaar het beste is. Elke ontwerpbeslissing wordt onderbouwd door een getal op een publieke bench, en de mislukkingen worden met dezelfde zorg gedocumenteerd als de successen, waaronder twee resultaten waarvan wij denken dat ze algemeen zijn: de naadenergie bij elke schatteroverdracht is gelijk aan de onenigheid tussen de schatters en kan niet worden weggewogen, en de geldigheid van een kleurlijn diep binnen een uitgebrande zone is onbeslisbaar op basis van de data eromheen.34

Het probleem

De magentazweem

Een digitale sensor is een array van fotosites, elk bedekt met één gekleurd filter van een kleurenfilterarray (CFA): het Bayer-patroon (2×2 van R, G, G, B) of Fuji’s X-Trans (6×6). Elke fotosite is een potentiaalput die zich tijdens de belichting vult met foto-elektronen en verzadigt bij een vaste capaciteit. Omdat de putcapaciteit een eigenschap van het silicium is, verzadigen alle drie de kleuren bij ongeveer dezelfde raw-codewaarde.

De valkuil is de witbalans. Een neutraal grijs onderwerp levert geen gelijke raw-signalen op in de drie kanalen: de CFA-transmissies, de spectrale gevoeligheid van de sensor en de scèneverlichting verschillen allemaal per kanaal. Om zo’n onderwerp als neutraal weer te geven, vermenigvuldigt de raw-ontwikkelaar elk kanaal met een witbalanscoëfficiënt: doorgaans wordt het groene kanaal nabij $1$ gelaten terwijl rood en blauw omhoog worden vermenigvuldigd met $1.5$ tot $2$.

Volg nu een neutraal hoog licht terwijl het helderder wordt. Bij de sensor is er niets kanaalspecifieks aan verzadiging: de drie raw-signalen klimmen naar één gedeeld plafond — de volle put — en klippen op min of meer dezelfde waarde. De magenta wordt achteraf vervaardigd, door de witbalansversterkingen: elk kanaal vermenigvuldigen verandert zowel de helling op weg omhoog als het niveau waar het geklipte plateau op uitkomt. Groen (versterking $\approx 1$) plateaut waar de sensor het achterliet; blauw en rood worden door hun versterkingen omhoog geduwd en plateauen erboven. Voorbij de verzadiging zijn de geregistreerde verhoudingen niet langer neutraal — rood en blauw schieten voorbij groen, en het „witte" hoge licht leest als magenta. (Bij echte onderwerpen klippen de kanalen nog steeds in volgorde — de eigen kleur van het onderwerp en de kanaalspecifieke gevoeligheden verspreiden de aanvangsmomenten, en dat is waarom gedeeltelijk geklipte pixels bestaan en overlevende gidsen dragen — maar de magenta van een uitgebrand neutraal is het werk van de versterkingen, niet van kanaalspecifieke drempels.)

Links: bij de sensor drijft een neutraal hoog licht alle drie de kanalen naar hetzelfde plafond — de volle put — en klippen ze samen. Rechts: de witbalansversterkingen (hier R × 2.0, B × 1.5, G × 1.0) veranderen zowel de helling als de hoogte van elk geklipt plateau; rood en blauw komen boven groen uit, en de geregistreerde kleur verschuift naar magenta — ook al is het onderwerp grijs en heeft de sensor alle kanalen op hetzelfde niveau geklipt.

De waarde waarbij een kanaal als geklipt wordt bestempeld is niet het numerieke maximum maar een kanaalspecifieke drempel afgeleid van het raw-witpunt:

$$ \text{clip}_c = 0.995 \times \texttt{clip} \times \text{white}_c, $$

waarbij $\text{white}_c$ de processed_maximum van de module is voor kanaal $c$ (het kanaalspecifieke raw-witniveau dat de eerdere pipeline-stappen overleeft) en clip een gebruikersveiligheidsfactor rond $1$ is. De marge van $0.995$ houdt bijna-verzadigde fotosites (waarvan de respons al niet-lineair is geworden nabij de top van de put) buiten de „geldige" set.2

Eenvoudigere oplossingen

Ansels module biedt drie goedkopere reconstructiemodi vóór de guided-laplacian-modus, en die zijn het vermelden waard omdat ze afbakenen wat de dure methode oplevert:

  • Clip perst simpelweg elk kanaal naar de gemeenschappelijke drempel $\texttt{clip}\times\min_c \text{white}_c$ (dezelfde witniveaus, zonder de marge van $0.995$). Geen magenta, maar elk geklipt gebied wordt een platte, structuurloze witte vlek.
  • Reconstruct in LCh zet elk Bayer-blok om naar een luminantie/chroma/tint-drietal, herschaalt de chroma van geklipte blokken zodat die overeenkomt met de niet-geklipte luminantie, en zet weer terug. Het verwijdert de tint- verschuiving maar kan geen textuur verzinnen.2
  • Reconstruct color (inpaint) propageert kleurverhoudingen vanuit naburige niet-geklipte pixels langs rijen en kolommen, met de exponentieel-vervallende verhoudingsupdate van het algoritme van Magic Lantern. Het is snel en directioneel maar eendimensionaal en gemakkelijk om de tuin te leiden door complexe randen.2

De guided laplacians-modus is de enige die zowel de textuur als de magnitude van een geklipt gebied herstelt, door te lenen van de kanalen die wél overleefden langs de lokale kleurlijn.

Stroomopwaartse Darktable levert twee reconstructiemodi die Ansel niet meedraagt, en ze vormen een leerzame vergelijking omdat ze uitgaan van een andere aanname over wat een uitgebrand hoog licht is. Beide werden ontwikkeld door de G’mic- en Darktable-teams en beide werken, net als onze methode, op het raw-mozaïek: elk kleurkanaal wordt eerst overal benaderd vanuit zijn 3×3-fotosite-omgeving, wat een grof maar full-resolutie kanaalspecifiek beeld oplevert.

Inpaint opposed berust op één empirische observatie: voor een geklipt kanaal is het gemiddelde van de twee andere kanalen (het „opposed"-gemiddelde, berekend in derdemachtswortelruimte om het dynamisch bereik te comprimeren) een goede schatting van de ontbrekende waarde in de overgrote meerderheid van beelden. Het mechanisme is dienovereenkomstig eenvoudig: vervang elke geklipte waarde door dat opposed-gemiddelde, en voeg dan één globale chrominantieoffset toe, gemeten op de pixels die morfologisch het dichtst bij de geklipte gebieden liggen, om de algehele kleurzweem te absorberen. De gedocumenteerde faalwijzen zijn de scènes waar één vaste relatie niet kan standhouden: gemengde belichting, witbalans ver van de aanname van de pipeline, of meerdere lichtbronnen met verschillende kleuren die verschillende hooglichten voeden.

Segmentation based verfijnt dezelfde basisschatter met ruimtelijke aanpassing. De geklipte pixels van elk kanaal worden met flood-fill samengevoegd tot samenhangende segmenten (optioneel samengevoegd door een morfologische sluiting, de „combine"-regelaar); voor elk segment doorzoekt het algoritme de niet-geklipte rand naar de beste kandidaat-pixel (gescoord op lokale standaarddeviatie en mediaan in een 5×5- venster) en transplanteert de pseudo-chrominantie van die kandidaat (het kanaal minus het opposed- gemiddelde, opnieuw in derdemachtswortelruimte) over het hele segment. Als er geen overtuigende kandidaat bestaat, valt het terug op een segmentbreed gemiddelde met een chrominantiecorrectie. Waar alle kanalen klippen, extrapoleert een aparte „rebuild"-doorgang een luminantieoppervlak uit de randgradiënten, gestuurd door een afstandstransformatie — de naaste verwant, in dit hele landschap, van onze biharmonische koepel. De aannames zijn dus: één representatieve chrominantie per segment (beter dan één per beeld, maar nog steeds vlak binnen een segment), textuur geërfd van wat de overlevende kanalen ook dragen, en gradiëntextrapolatie waar niets overleefde.

Beide zijn een wanhopige poging om het beschadigde gebied te vullen met iets plausibels, maar bevorderen platte gekleurde oppervlakken op de verkeerde magnitude.

Grondbeginselen

De methode is een samenstelling van vier ideeën. Twee daarvan (discrete Laplacianen en de à-trous- B-spline-piramide) worden woordelijk gedeeld met diffuse or sharpen en worden hier alleen samengevat. De andere twee, het geleide filter en chrominantiediffusie, dragen de reconstructie en worden volledig afgeleid.

Gradiënten en Laplacianen

Voor een discreet beeld $u(i,j)$ meet de gradiënt de lokale helling,

$$ \nabla u = \left( \frac{u(i+1,j) - u(i-1,j)}{2}, \; \frac{u(i,j+1) - u(i,j-1)}{2} \right), $$

en de Laplaciaan meet de lokale kromming: hoeveel een pixel afwijkt van het gemiddelde van zijn buren,

$$ \Delta u = \frac{\partial^2 u}{\partial x^2} + \frac{\partial^2 u}{\partial y^2}. $$

De Laplaciaan is hier het werkpaard omdat het textuur isoleert als oscillatie rond een lokaal gemiddelde (het is nul op vlakke gebieden en reageert alleen op lokaal contrast) en omdat het lineair is: het beeld over- of onderbelichten herschaalt het simpelweg (een eigenschap waarop we hieronder steunen). Textuur op deze manier isoleren is wat ons in staat stelt het tussen kanalen te transplanteren zonder de absolute helderheid van de gids mee te slepen; het verschil in totale magnitude tussen een geklipt kanaal en zijn gids wordt geabsorbeerd door de helling van het geleide filter, niet door de Laplaciaan zelf. Ansel gebruikt de rotatiesymmetrische 9-punts-stencil van Oono & Puri

$$ \mathbf{K}_{\text{iso}} = \begin{bmatrix} \tfrac14 & \tfrac12 & \tfrac14 \\ \tfrac12 & -3 & \tfrac12 \\ \tfrac14 & \tfrac12 & \tfrac14 \end{bmatrix}, $$

waarvan de hoekfout veel kleiner is dan die van het naïeve 5-punts-kruis, zodat diffusie de assen van het pixelraster niet bevoordeelt.567

De à-trous-B-spline-piramide

Om op structuren van vele groottes in te werken, wordt het beeld opgesplitst in frequentiebanden door het herhaaldelijk te vervagen met de separabele cardinale B-spline-kern

$$ h_0 = \frac{1}{16}[1,4,6,4,1], $$

een compacte benadering van een Gaussiaan met parameter $\sigma_B \approx 1.0554$.8 Op schaal $s$ worden de taps uit elkaar gespreid met een stap van $2^s$ pixels („à-trous" = „met gaten"), zodat dezelfde piepkleine kern steeds verder reikt zonder ooit in kosten te groeien. Schrijven we $G_s$ voor de opeenvolgende laagdoorlaat-beelden (progressief vervaagd) en $H_s$ voor de detailbanden,

$$ G_{-1} = u, \qquad G_s = h_{2^s} * G_{s-1}, \qquad H_s = G_{s-1} - G_s, $$

is het beeld precies de som van zijn banden, $u = \sum_{s=0}^{n-1} H_s + G_{n-1}$. Een detailband $H_s$ is een verschil van Gaussianen, wat zelf een geschaalde benadering is van een Laplaciaan-van-Gaussiaan — dus „de band $H_s$ filteren" en „een Laplaciaan toepassen op schaal $s$" zijn twee zienswijzen van dezelfde bewerking. De volledige afleiding, inclusief hoe de equivalente Gaussische straal groeit als

$$ \sigma_{G,s} = \sigma_B \sqrt{\frac{4^{s+1}-1}{3}}, $$

wordt gegeven in het begeleidende artikel over diffuse or sharpen.29

Het geleide filter

Het geleide filter van He, Sun en Tang is de motor die textuur leent van een goed kanaal naar een geklipt kanaal.3 Stel dat we een uitvoerbeeld $q$ willen produceren dat trouw blijft aan een bepaald doel $p$ maar de randen en textuur van een gids $I$ draagt. Neem aan dat, binnen elk klein venster $\omega_k$ rond pixel $k$, de uitvoer een affiene functie van de gids is:

$$ q_i = a_k \, I_i + b_k, \qquad \forall i \in \omega_k. $$

Deze ene aanname, een lokale kleurlijn, is het hele model. Ze zegt dat binnen een klein plakje het kanaal dat we opnieuw opbouwen slechts een geschaalde, verschoven kopie van de gids is. Het is dezelfde prior die ten grondslag ligt aan kanaaloverschrijdend demozaïceren, ontwazen, image matting en inkleuren: natuurlijke oppervlakken traceren kleurlijnen (lokaal zijn hun kanalen affien gerelateerd) omdat de meeste randen veranderingen in reflectantie zijn die alle kanalen samen schalen.10 Onder een affiene afbeelding is $\nabla q = a_k \nabla I$, dus $q$ erft elke rand van $I$, slechts herschaald met $a_k$.

We fitten $(a_k, b_k)$ met kleinste kwadraten, waarbij we $a_k$ klein houden om te voorkomen dat ruis wordt versterkt (een ridge-term $\varepsilon a_k^2$):

$$ E(a_k, b_k) = \sum_{i \in \omega_k} \Big[ (a_k I_i + b_k - p_i)^2 + \varepsilon \, a_k^2 \Big]. $$

De afgeleiden op nul stellen geeft de gesloten vorm die, bijna woordelijk, in de code verschijnt:

$$ \begin{aligned} a_k &= \frac{\operatorname{cov}_{\omega_k}(I, p)}{\operatorname{var}_{\omega_k}(I) + \varepsilon}, \\ b_k &= \bar{p}_{\omega_k} - a_k \, \bar{I}_{\omega_k}. \end{aligned} $$

De covariantie in de teller (een maat voor hoeveel gids en doel samen stijgen en dalen) is de sleutel: waar ze samen bewegen, geldt $a_k \to 1$ en wordt de textuur van de gids doorgekopieerd; waar de gids vlak is ($\operatorname{var} \to 0$), geldt $a_k \to 0$ en valt de uitvoer terug op het lokale gemiddelde $\bar p$. De ridge-parameter $\varepsilon$ stelt de schaal in waaronder variaties als ruis worden behandeld en worden gladgestreken in plaats van overgedragen.

Diffusie als kleurinpainting

De kleur van een gat vullen is een ander probleem dan de textuur ervan vullen. De kleur van een gat moet vloeiend variëren en aansluiten op de rand; het moet geen eigen hoogfrequent detail (fijne, snel variërende textuur) dragen. Het natuurlijke formalisme is de Dirichlet-energie, de totale hoeveelheid variatie die het beeld bevat, groot waar het kronkelt en nul waar het constant is:

$$ E[u] = \int_\Omega \lVert \nabla u \rVert^2 \, \mathrm{d}\Omega, $$

waarvan de minimalisator over het gat $\Omega$, met de omringende pixels als randvoorwaarde, de harmonische functie is die voldoet aan $\Delta u = 0$.

(Notatie, gebruikt in het hele artikel: $\lVert v \rVert$ is de euclidische norm van een vector — voor de gradiënt, $\lVert \nabla u \rVert = \sqrt{(\partial_x u)^2 + (\partial_y u)^2}$, de grootte van de lokale helling; $\lvert s \rvert$ is de absolute waarde van een scalair; en $\langle \cdot \rangle$ — punthaken — is het gemiddelde van de ingesloten grootheid over de pixels van het gebied.) De gradiëntafdaling van deze energie is precies de warmtevergelijking

$$ \frac{\partial u}{\partial t} = \Delta u, $$

d.w.z. isotrope diffusie, waarbij isotroop richtingsblind betekent, gelijkmatig verspreidend in alle richtingen. Het uitvoeren ervan verspreidt de randkleur naar binnen totdat het gat gevuld is door een vloeiend, krommingsvrij oppervlak. Dit is hetzelfde anisotrope-warmteoverdracht-inpaintingmodel van Qin et al. dat Ansel al gebruikt voor diffuse or sharpen, hier beperkt tot het isotrope geval.4 We passen het niet toe op de pixels maar op de kleurverhoudingen, zodat alleen chrominantie wordt gladgestreken terwijl de gereconstrueerde luminantie met rust wordt gelaten.

De diffusie sturen: de anisotrope uitbreiding. De Dirichlet-energie hierboven behandelt elke richting gelijk; ze is isotroop. Ze generaliseert naar een gewogen vorm,

$$ E(u) = \int_\Omega \nabla u^\top D \,\nabla u \,\mathrm{d}\Omega , $$

waarbij de diffusietensor $D$ een kleine symmetrische matrix is, gedefinieerd bij elke pixel, wiens taak het is richtingen te herwegen: volledige geleiding langs een van zijn eigenvectoren, gedempte geleiding langs de andere. Het minimaliseren van deze energie lost $\mathrm{div}(D\,\nabla u) = 0$ op (de Euler–Lagrange-vergelijking ervan), en met $D$ overal de identiteit reduceert het precies tot het isotrope geval hierboven. Het doel van de machinerie is sturen: kies de sterke richting langs de isofoten van het beeld (de lijnen van constante helderheid) en de gedempte richting dwars daarop, en de diffusie strijkt een grootheid langs beeldstructuur glad terwijl het weigert die over randen te dragen.

Dit veilig discretiseren vereist één voorzorgsmaatregel. Schrijven we de tensor $D = \begin{pmatrix} a & b \ b & c \end{pmatrix}$ (gemiddeld tussen elke pixel en zijn buur, met de kruisterm geklemd op $|b| \leq \min(a, c)$), dan wordt de divergentie $\operatorname{div}(D\,\nabla u)$ een som over de acht buren met gewichten

$$ w_{\pm e_x} = a - |b|, \qquad w_{\pm e_y} = c - |b|, \qquad w_{\pm(e_x + e_y)} = \max(b,\, 0), \qquad w_{\pm(e_x - e_y)} = \max(-b,\, 0), $$

de niet-negativiteit behoudende stencil van Weickert: de klem garandeert dat elk gewicht niet-negatief is, zodat de verankerde relaxatie $u_0 \leftarrow \sum_k w_k u_k / \sum_k w_k$ elke onbekende vervangt door een convexe combinatie van zijn buren. Dat is het discrete maximumprincipe — de opgeloste waarden kunnen nooit buiten het bereik van de ankers komen, hoe hard de tensor ook stuurt — en het is wat anisotrope diffusie veilig maakt om uit te voeren op data die fysiek moet blijven. De uitgeleverde methode gebruikt deze machinerie op twee plaatsen: het transport van de kleurlijn-coëfficiënten over de uitgebrande zone (stap 3 van het algoritme, waar de tensor bovendien mengt tussen isofoot- en gradiëntsturing volgens een gemeten randkans), en de chrominantie van volledig geklipte kernen (stap 8), waar kleuren de structuur van de herstelde luminantie moeten volgen en er nooit overheen mogen bloeden.

Biharmonische inpainting

Harmonische inpainting is het juiste gereedschap voor een signaal dat behoort vlak te worden binnen het gat: een vloeiende chrominantie. Het is het verkeerde gereedschap voor een signaal dat nog steeg toen de sensor het klipte: de magnitude van een uitgebrand hoog licht bleef klimmen, en het vlak vullen ($\Delta u = 0$) laat een matte schijf achter waar een heldere koepel hoort. Om de omringende helling naar binnen te dragen in plaats van hem te wissen, bestraf je het buigen van het signaal in plaats van zijn gradiënt: minimaliseer de dunne-plaat- (biharmonische) energie

$$ E_{\text{bihar}}[u] = \int_\Omega (\Delta u)^2 \, \mathrm{d}\Omega \qquad \Longrightarrow \qquad \Delta^2 u = 0 \ \text{ on } \Omega, \quad u\big|_{\partial\Omega} = u_{\text{valid}} , $$

waarvan de Euler–Lagrange-vergelijking (de voorwaarde waaraan elke minimalisator van de energie moet voldoen) de biharmonische vergelijking $\Delta^2 u = 0$ is. Waar de harmonische oplossing $\Delta u = 0$ afdwingt (een vlak minimaal oppervlak), maakt de biharmonische oplossing $\Delta u$ zelf harmonisch: de kromming aan de rand wordt naar het inwendige gedragen, zodat de stijgende gradiënt van de grens wordt geëxtrapoleerd tot een koepel (een dunne-plaat-spline). Het is de hogere-orde, gradiënt-verlengende tegenhanger van diffusie, in dezelfde geest waarin diffuse or sharpen het teken van de Laplaciaan omkeert om te verscherpen in plaats van glad te strijken. We lossen het op als een direct ijl lineair stelsel op het gat, en gebruiken het hieronder om de magnitude van een geklipt kanaal opnieuw op te bouwen uit zijn eigen geldige rand, overal waar geen gecorreleerd kanaal overleeft om het te sturen.7

De methode uit 2021: guided laplacians

Voordat we de evolutie van de methode volgen, documenteert deze sectie het oorspronkelijke ontwerp, zoals het in 2021 werd uitgeleverd en zoals het vandaag nog steeds wordt uitgeleverd — ontwerp ongewijzigd, hoewel het één gemeten border-gather-fix deelt met de nieuwe pipeline (gedocumenteerd bij de harmonische verfijningen hieronder) — onder de guided laplacians-modus (de nieuwe methode is een aparte, opt-in-modus: zie de statusnotitie verderop). Het werd tegen de intuïtie in gecodeerd en op het oog afgesteld op natuurlijke beelden, en de algemene ideeën ervan waren alleen ooit geschetst op het pixls.us-forum1; dit is de eerste volledige uiteenzetting ervan.

Intuïtie & achtergrond

De intuïtie. Onvermijdelijke clipping gebeurt binnen lichtbronnen: de zon, een vlam, een spiegelende reflectie. Zulke bronnen worden omringd door een gloeiende halo, en die halo draagt drie bruikbare soorten informatie. Ten eerste zijn de kleurkanalen daar sterk gecorreleerd (ze stijgen allemaal naar de bron toe), zodat een kanaal dat klipte de vorm kan lenen van een kanaal dat dat niet deed. Ten tweede wijzen de gradiënten van de halo naar de bron, zodat zelfs een volledig uitgebrande kern plausibel kan worden voortgezet door de omringende gradiënten naar binnen te propageren. Ten derde is de halo gekleurd als de lichtbron zelf, zodat chrominantie kan worden hersteld door RGB-verhoudingen naar binnen te propageren. Het ontwerp uit 2021 zette elke intuïtie om in een operator: een geleide overdracht van fijne structuur tussen kanalen, en een geïtereerde diffusie die structuur van de geldige omgeving in het uitgebrande gebied duwt terwijl kleurverhoudingen naar binnen worden gediffundeerd.

De doelstellingen. Reconstrueer vóór het demozaïceren, op het raw-mozaïek, zodat de interpolatie nooit geklipte samples ziet; steun nooit op witbalans of enige aanname over welke kleur het hoge licht „zou moeten" zijn (de eigen kleur van de lichtbron is onkenbaar); en geef de voorkeur aan vloeiende, fysiek plausibele voortzettingen boven scherpe hallucinaties, want een fout in een uitgebrand hoog licht is veel zichtbaarder als een hard artefact dan als een zacht.

Zijn staat van dienst. In zijn ontwerpgevallen werkte de methode, en dat doet ze nog steeds: een zonneschijf of een spiegeling op water wordt opnieuw opgebouwd met geloofwaardige structuur en zonder de platte grijze vlek die gewone clipping achterlaat. Ze behoudt gradiënten waar eenvoudigere methoden (kanaalverhoudingsschaling, éénkleur- inpainting) ze vervlakken, en omdat ze op gradiënten werkt in plaats van op kleuren tolereert ze een verkeerde witbalans. Twee structurele beperkingen werden vanaf het begin begrepen en geaccepteerd: een uitgebrande lucht gezien door groene bladeren wordt groen hersteld (de methode propageert de naburige kleur, van nature), en zware chromatische aberratie breekt de kanaaluitlijning die de kleurlijn nodig heeft.

Het optimalisatieprobleem

De textuuroverdracht. Het beeld wordt ontleed met de hierboven beschreven à-trous-B-spline- piramide: op elke schaal $s$ splitst het signaal in een laagfrequente benadering en een detailband $H_s$. Omdat de cardinale B-spline zeer dicht bij een Gaussiaan ligt, en de detailband schaalgewijs wordt berekend als het verschil met deze benaderde Gaussiaan, ligt $H_s$ zelf al dicht bij een Laplaciaan, herschaald in magnitude (het overschat de Laplaciaan feitelijk). Op elke detailband wordt elk geklipt kanaal $c$ gefit tegen een gids-kanaal $g$ (per pixel gekozen als het kanaal met de sterkste lokale variantie, dat wil zeggen degene die de meeste structuur draagt — zonder enige controle dat de gids daar zelf geldig is) met het hierboven afgeleide geleide filter:

$$ H_c \;\leftarrow\; a_c\, H_g + b_c, \qquad a_c = \frac{\operatorname{cov}(H_c, H_g)}{\operatorname{var}(H_g)}, $$

waarbij de covariantie en variantie lokale gevensterde statistieken zijn (een harde 3×3-box die geklipte samples niet uitsluit), en de deling simpelweg wordt overgeslagen waar de variantie van de gids onder $10^{-12}$ zakt — er is geen dempingsterm. Omdat een detailband een nulgemiddelde heeft, is het intercept $b_c$ in wezen nul: de overdracht verplaatst textuur van de gids naar het geklipte kanaal, geschaald volgens hun gemeten lokale relatie.

De chrominantiediffusie. De tweede fase werkt op de RGB-verhoudingen (de chrominantie, $\text{RGB}/n$ met $n = \lVert \text{RGB} \rVert$, de euclidische norm — het symbool dat de onderstaande updateregels gebruiken), waarbij de negenpunts-Oono & Puri-Laplaciaan op elk verhoudingsvlak wordt geïtereerd; het normvlak $n$ rijdt mee op dezelfde piramide maar wordt expliciet beschermd tegen de stap (eromheen geback-upt en hersteld), zodat het onveranderd wordt hersynthetiseerd. Die iteratie is de gradiëntafdaling van een expliciet variationeel probleem: over het geklipte gebied $\Omega$, met de geldige rand als randdata, minimaliseert het

$$ E_{\text{2021}}[u] \;=\; \int_{\Omega} \lVert \nabla u \rVert^2 \,\mathrm{d}\Omega \;+\; \lambda_{\text{solid}} \int_{\Omega} \lVert u - \bar u \rVert^2 \,\mathrm{d}\Omega , \qquad u\big|_{\partial\Omega} = u_{\text{valid}}, $$

voor elk verhoudingsvlak en voor de norm: een Dirichlet- (harmonische) energie die de chrominantie en het niveau van de rand vloeiend naar binnen draagt, plus een optionele afschermingsterm die de kern naar de gemiddelde geldige kleur $\bar u$ trekt met het gewicht $\lambda_{\text{solid}}$ van de gebruiker („inpaint a flat color"). De Euler–Lagrange-vergelijking ervan is de afgeschermde Poisson-vergelijking uit de theoriesectie; de code uit 2021 lost hem nooit op tot een stationaire toestand — de „iterations"-schuifregelaar kapt de afdaling af, zodat het praktische resultaat evenzeer afhangt van het iteratiebudget als van de energie. Twee eigenschappen volgen rechtstreeks uit deze doelstelling en verklaren de kenmerkende look van de methode: een harmonische vulling vervlakt (ze bestraft gradiënten, zodat het inwendige neigt naar een vlak plateau — de theoriesectie laat zien waarom een biharmonische energie nodig is om hellingen voort te zetten), en niets in beide fasen legt het gereconstrueerde niveau van een geklipt kanaal vast, dat fase 1 niet kan overdragen (nulgemiddelde banden) en fase 2 alleen diffundeert vanuit een rand die op de clip ligt.

Het algoritme

De hele procedure, in één oogopslag:

flowchart TD
  A["raw mosaic (one colour per pixel)"] --> B["bilinear interpolation to temporary RGB
+ per-channel clip masks"] B --> C["downsample 4× (for speed)"] C --> D["à-trous B-spline pyramid:
split into detail bands, one per frequency range"] D --> E["per band, RGB, fine → coarse:
guided-filter fit of the clipped channel
against the most textured channel
(validity not checked)
→ transfer of TEXTURE (zero-mean details)"] E --> F["per band, RGB ratios & norm, iterated 9-point Laplacian diffusion:
spread structure from the valid rim
into the blown core, isotropically"] F --> G["optional: reaction toward a flat colour
(user slider) + Poissonian re-graining"] G --> H["upsample, remosaic,
feathered composite over the raw"]

De afwegingen zijn bewust gemaakt. Werken op detailbanden maakt de overdracht immuun voor witbalans- fouten (alleen vormen verplaatsen tussen kanalen). De negenpunts-Laplaciaan is de isotrope, rotatie-invariante discretisatie afgeleid in grondbeginselen, zodat de diffusie de kern van buiten naar binnen vult zonder de assen van het pixelraster te volgen. Vloeiendheid krijgt altijd de voorkeur boven scherpte: een fout in een uitgebrand hoog licht leest als een hard artefact wanneer scherp en als een plausibele gloed wanneer zacht. En de fijn-naar-grof-bandvolgorde betekent dat elke band onafhankelijk binnen één doorgang wordt gefit — er is geen schaaloverschrijdende consistentie- beperking, wat juist onschadelijk blijft omdat de banden een nulgemiddelde hebben.

Drie voorbereidende fasen verdienen een notitie — ze worden gedeeld door elke reconstructiemethode in dit artikel, inclusief de opvolger.

Bilineair demozaïceren. Het mozaïek wordt bilineair gedemozaïceerd naar een tijdelijk RGB-beeld: een wegwerp- demosaic wiens enige taak is elk kanaal overal een waarde te geven voor de kanaalspecifieke geleide fit; de uiteindelijke uitvoer wordt terug geremozaïceerd naar een enkel kanaal. Een kanaalspecifiek clip-masker, samen met zijn logische OR (uitgevloeid naar de compositie-opaciteit $\alpha$), registreert welke kanalen verzadigden.2

Lokale kanaalnormalisatie. Elke kleur wordt gedeeld door de gemiddelde waarde van die kleur in de huidige tegel, een grove lokale witbalans ter plekke berekend. Dit egaliseert de kanaalmagnitudes zodat de variantievergelijking voor gidsselectie niet bevooroordeeld is ten gunste van welk kanaal ook de grootste raw-getallen draagt; het hergebruikt bewust niet de stroomopwaarts opgegeven witbalans.2

Het masker uitvloeien. Het binaire masker wordt gladgestreken door een klein $5\times5$-box-gemiddelde tot een opaciteit $\alpha \in [0,1]$, gebruikt als het uiteindelijke compositie-gewicht én als de kanaalspecifieke zachte gewichten van de à-trous-reconstructie hieronder. Uitvloeien verzacht de naad waar de reconstructie ongemoeide pixels ontmoet; in de numerieke tests verlaagde het de randfout van deze methode in plaats van hem te verhogen — het verwijderen ervan is getest en schaadt hier meetbaar (de zachte gewichten zijn dragend), terwijl de opvolgermethode het uitvloeien volledig laat vallen (zijn maskers zijn van begin tot eind binair; zie het kerkhof).

De updateregels

Het optimalisatieprobleem vermeldt wat deze methode minimaliseert en het algoritme vertelt de fasen ervan; hier zijn de daadwerkelijke signaalupdates van de uitgeleverde 2021-modus, in uitvoeringsvolgorde, voor een implementeerder die vanaf nul begint. Vlakken: de vier keer neergeschaalde tijdelijke RGB $u_c$ (bilineair gedemozaïceerd, kanaalgenormaliseerd), de uitgevloeide kanaalspecifieke maskers $\alpha_c \in [0,1]$ en hun any-clip-opaciteit $\alpha$. Ontleding: de à-trous-B-spline-piramide met stap $2^s$ per schaal — gecascadeerde vervagingen $\mathrm{LF}_s$, detailbanden $D_s = \mathrm{LF}_{s-1} - \mathrm{LF}_s$, plus het grofste residu.

1. Textuuroverdracht (de RGB-doorgang), per schaal van fijn naar grof, bij elke pixel waar $\alpha > 0$. Op de $3\times3$-à-trous-omgeving (stap $2^s$) van de detailband, bereken het patchgemiddelde en de patchvariantie per kanaal, kies de gids $g$ als het kanaal met de grootste patchvariantie (geldigheid wordt niet gecontroleerd — de wortel van mislukking 4), fit de naar-nul-intercept-vertekende kleurlijn op de details,

$$ a_c = \max\!\left( \frac{\operatorname{cov}(D_g, D_c)}{\operatorname{var}(D_g)},\, 0 \right), \qquad b_c = \bar D_c - a_c\, \bar D_g, $$

en meng de voorspelling erin, kwadratisch uitvloeiend met de equivalente straal van de schaal — genomen bij stap $4s$, niet $s$: de code evalueert $\sigma$ bij s * DS_FACTOR, waarbij elke schaal ook voor de neerschaalfactor wordt aangerekend, zodat de vervaging veel steiler is dan $\sigma_s^2$ alleen suggereert ($\beta$ is $\alpha/380$ bij $s{=}1$ en $\alpha/97\,000$ bij $s{=}2$ — de geleide overdracht leeft effectief op de fijnste schalen):

$$ D_c \;\leftarrow\; \beta_c \,\big(a_c\, D_g + b_c\big) + (1 - \beta_c)\, D_c, \qquad \beta_c = \frac{\alpha_c}{\sigma_{G,\,4s}^{2}}. $$

Hersynthese sommeert de verwerkte banden plus het residu, geklemd op $\geq 0$; bij de laatste iteratie wordt Poisson-korrel van amplitude $\sigma = u_c \cdot \texttt{noise_level}$ ingevouwen (alleen oplichtend) onder $\alpha$. Het resultaat wordt opgesplitst in richting en magnitude, $r_c = u_c / \lVert u \rVert$ en $n = \lVert u \rVert$, voor de volgende doorgang.

2. Chrominantiediffusie (de chroma-doorgang), dezelfde piramide over de vier vlakken $(r_R, r_G, r_B, n)$: elke detailband van de drie verhoudingsvlakken neemt één expliciete Euler- stap van de afgeschermde warmtevergelijking, per pixel waar $\alpha > 0$ en per kanaal — de band van het norm- vlak wordt vóór de stap geback-upt en erna hersteld, zodat $n$ ongediffundeerd door de piramide gaat,

$$ D \;\leftarrow\; D + \alpha_c\, \kappa \,\big( \mathbf{K}_{\text{iso}} \!*\! D \;-\; \lambda\, D \big), $$

met $\mathbf{K}_{\text{iso}}$ de negenpunts-isotrope Laplaciaan uit grondbeginselen, $\kappa = \sigma_B^2 / (2\sqrt{\pi}) \approx 0.31$ de band-naar-Laplaciaan-herschaling, en $\lambda$ de vlakke-kleur-reactie (solid_color). Hersynthese zoals hierboven, daarna worden de verhoudingen hernormaliseerd naar eenheidsnorm en gerecombineerd, $u_c \leftarrow r_c \cdot n$.

3. Itereer. Doorgangen 1–2 herhalen iterations keer (de gebruikersschuifregelaar); niets detecteert convergentie, het aantal is het budget.

4. Samenstellen. De reconstructie wordt vier keer opgeschaald en over het raw-mozaïek gemengd via de uitgevloeide opaciteit, per fotosite van kleur $c$: $\text{out} = \alpha\, u_c + (1 - \alpha)\, \text{raw}$.

Niets anders schrijft een pixel — en, zoals het ground-truth-onderzoek uitwees, draagt niets hierboven een niveau over: elke update werkt op nulgemiddelde detailbanden of op verhoudingen, wat precies de structurele leemte is die de opvolger dicht.

Implementatie & optimalisaties

De hele reconstructie draait op een vier keer neergeschaalde buffer — een zestiende van de pixels — en het resultaat wordt opgeschaald en via compositie teruggeplaatst over de raw onder een uitgevloeid masker. Die ene beslissing levert het grootste deel van de snelheid van de methode op en kost meetbare nauwkeurigheid: dezelfde wiskunde opnieuw uitvoeren op volledige resolutie verlaagt de randfout met ongeveer 30 %, omdat de opgeschaalde reconstructie wazig is tegen het scherpe origineel waaraan het moet aansluiten (de opvolgermethode draait om precies die reden op volledige resolutie). De à-trous-detailbanden overschatten de Laplaciaan met een bekende constante (de $\sigma_B = 1.05537$ van de B-spline geeft $1/\kappa = 3.1827$), wat de diffusiestap compenseert; de diffusie draait iterations × (één RGB-verhoudingsdoorgang + één normdoorgang) per schaal, op het hele frame — er is geen gebiedssegmentatie, dus de kosten schalen met het beeld, niet met het geklipte gebied. Poisson-korrel ($\sigma = \text{value} \times \text{noise level}$) wordt op de laatste iteratie opnieuw gegenereerd zodat gereconstrueerde gebieden er niet plastisch glad uitzien naast echte textuur.

Ontdekte problemen

Wat in het bovenstaande stroomschema nooit gebeurt, is een overdracht van niveau — een observatie die onzichtbaar is zonder ground truth, en waar het hele onderzoek van 2026 begint.

De problemen. In de praktijk bleven gebruikers uitgebrande hooglichten melden die na reconstructie magenta bleven — precies het defect dat de methode bestaat om te verhelpen. Het onderzoek dat in de rest van dit artikel wordt gedocumenteerd, lokaliseerde de grondoorzaak uiteindelijk in de bovenstaande wiskunde: de geleide fit werd alleen op de detailbanden toegepast. Een detailband heeft een nulgemiddelde, dus het intercept $b_c$ draagt geen energie, en alleen textuur wordt ooit overgedragen — nooit het niveau. De laagfrequente component van het geklipte kanaal, vastgezet op de clipwaarde, werd ongewijzigd teruggevoegd; een uitgebrand kanaal bleef op de clip (of werd er door de chrominantieafhandeling onder geduwd) en bleef magenta. In de later gebouwde validatie- bench is deze oorspronkelijke reconstructie vaak slechter dan niets doen op enkelkanaals-clips: een root-mean-square-fout (RMSE) van 0.073 tegen 0.049 voor het geklipt laten van de pixels, op een natuurachtige scène waar de uiteindelijke herbouw 0.015 bereikt (deze drie getallen komen van de bench van het Python-onderzoeksprototype — fix_prototype.py in de onderzoeksrepository  — waarvan de NumPy-port van de 2021-module de C vervangt; de uitgeleverde implementaties worden gescoord in de resultaten).

image

Een synthetische scène: drie verzadigde enkelkanaals-hooglichten (rode, groene, blauwe schijven) en een helder bijna-neutraal exemplaar. Ground truth is de niet-geklipte scène, geklipt is wat de sensor registreert, vorige methode de Python-port van de à-trous-module uit 2021, gecorrigeerde methode hetzelfde ontwerp met de vol-signaal-reparatie die hieronder wordt beschreven.

In de enkelkanaals-schijven klimt het gecorrigeerde resultaat terug naar de ware kleur (bijv. de rode schijf herstelt tot $\approx 1.7$ tegenover waar $\approx 1.9$, met groen en blauw exact overeenkomend) waar de vorige methode onder de clip blijft ($\approx 0.9$). De volledig geklipte neutrale schijf, vlak op de clip in zowel de sensor als de vorige methode, wordt opnieuw gekoepeld door de gedeelde luminantievulling (centrum $\approx 1.5$ tegenover waar $\approx 1.6$) en blijft bijna-neutraal, met de chrominantie ervan gedragen door de randdiffusie.

De eenregelige reparatie — pas dezelfde geleide fit toe op het volledige signaal (lage frequentie en detail samen) zodat het intercept het lokale gemiddelde draagt en een uitgebrand kanaal boven de clip kan stijgen (de wiskunde staat in de updateregels) — verhelpt die klasse van mislukkingen, en het is het fundament dat alles daarna behield: alle volgende methoden in dit artikel fitten kleurlijnen op volledige waarden. Het was noodzakelijk maar niet voldoende. Met ground truth om tegen af te meten — op het gerepareerde ontwerp, herbouwd op volledige resolutie rond een ladder van venstergroottes (de kerkhofbijlage beschrijft het) — bleven vier structurele mislukkingen over, en die vormden de opvolgermethode:

Ten eerste degenereert de vensterladder overal waar een venster overwegend data op clipniveau ziet (fijne vensters nabij de rand, grove vensters diep in het gat), en een gedegenereerde fit (covariantie nabij nul, helling nabij nul) vult vlak, op ongeveer het clipniveau. Erger nog, de overdracht tussen opeenvolgende schalen volgt een contour van constante diepte in het gat, en de onenigheid tussen de twee schalen drukt een zichtbare boog langs die contour af.

Ten tweede concurreert de $\epsilon$-demping hierboven met de lokale variantie van de gids, zodat het de helling stilzwijgend verplettert overal waar die variantie klein is — wat ruisrijke inhoud per ongeluk beschermt en schone vloeiende gradiënten (zoals lucht) via hetzelfde mechanisme vervlakt. Eén constante, twee tegengestelde gevolgen, geen waarde die beide dient.

Ten derde klipt de sensor niet abrupt: hij comprimeert de laatste paar procent onder de verzadiging, zodat de band pixels die de reconstructie als vertrouwde ankers behandelt systematisch te laag wordt geregistreerd.11 Zelfs een orakel dat het geklipte inwendige exact zou herbouwen, zou dan zichtbaar helderder zitten dan de vertekende ring waaraan het moet hechten: de naad zit in de data, niet in de schatting, en alleen het corrigeren van de data (de knie-inversie) kan hem verwijderen.

Ten vierde rust de hele methode op één hypothese: naburige kanalen stijgen en dalen samen, dus een geklipt kanaal is een meetbare affiene functie van een overlevend kanaal. En sommige inhoud (een lucht waarvan de tint zelf verschuift, iriseren, kleurtextuur fijner dan het venster) voldoet daar simpelweg niet aan. Daar bevat de geleide voor geen enkele schatter informatie over het ontbrekende kanaal, dus het ontwerp moet dat meten ($R^2$) en de informatiebron volledig veranderen: ruimtelijke gladheid in plaats van overdracht tussen kanalen.

Die repareren vergde meer dan een reparatie — het vergde een paradigmawisseling.

De nieuwe methode: harmonische transpositie

Deze sectie documenteert de methode die vandaag wordt uitgeleverd — haar premissen, haar optimalisatieprobleem, haar algoritme, en hoe de productie-implementatie afwijkt van het onderzoeksprototype. Gemeten resultaten, prestaties en de algemene bevindingen hebben elk hun eigen sectie hieronder. Harmonische transpositie wordt uitgeleverd als zijn eigen reconstructiemodus naast de oorspronkelijke guided laplacians: de à-trous-methode uit 2021 behoudt haar historische naam en ontwerp — onveranderd behalve de gedeelde border-gather-fix, die haar eigen scores verbetert — en de nieuwe methode is een expliciete opt-in. De reconstructiekern is agnostisch voor het sensormozaïek en draait op zowel Bayer als X-Trans, op de processor en binnen een OpenCL-pijp, waar elke geklipte regio wordt opgelost aan de kant van de bus die sneller mat (zie de prestatiesectie).

Intuïtie & achtergrond

De reparatie hierboven verandert wat het geleide filter overdraagt; harmonische transpositie verandert hoe het model reist. Overal waar minstens één kanaal overleefde, is reconstructie een regressie- probleem, geen inpainting-probleem: de geldige kanalen zijn gemeten data, aanwezig bij elke pixel van de uitgebrande zone, en de enige onbekende is de lokale relatie (de kleurlijn) tussen hen en het geklipte kanaal. De methode uit 2021 — en haar gecorrigeerde, volledig-signaal-reconstructie — evalueerde die relatie overal waar een statistiekvenster kon reiken, en naaide de evaluaties aan elkaar; elke naad was een naad, en vensters diep binnen een groot gat bereikten helemaal niets. Harmonische transpositie keert het transport om: fit de kleurlijn één keer, waar de data haar ondersteunt, diffundeer dan de coëfficiënten van het model — niet de pixel- waarden — over de uitgebrande zone als gladde velden, en evalueer ze pas dan tegen de gemeten overlevende kanalen bij elke pixel. Coëfficiënten zijn van nature glad waar waarden dat niet zijn; de geleiden herinjecteren de structuur op volledige resolutie op het moment van evaluatie. Waarom dit een verschil in soort is in plaats van in graad — en waartoe het generaliseert — wordt uiteengezet in de theoretische bevindingen.

Al het andere dat de methode uit 2021 goed deed, wordt behouden, op een steviger fundament: het kleurlijnmodel en zijn gevensterde gewogen kleinste kwadraten (de regressie van het geleide filter), de biharmonische koepel voor magnitude zonder geleide, chrominantie gedragen als begrensde verhoudingen, de voorkeur voor gladde voortzettingen, en de korrelregeneratie. Wat nieuw is naast het transport: per-regio-segmentatie op volledige resolutie (kosten schalen met het geklipte oppervlak, niet met het beeld), een gemeten inversie van de sensor-rolloff die de band nabij clipping ontvooroordeelt voordat er iets wordt gefit (falen 3 hierboven), fits gepoort en vertrouwd op hun eigen gemeten kwaliteit $R^2$ (falen 4), en één ontwerpregel die overal wordt toegepast, afgeleid van de naadenergiewet van de theoretische bevindingen: geen stap mag overdragen tussen schatters die het oneens zijn (falen 1).

Het optimalisatieprobleem

Geen van beide stappen assembleert een globale energie en roept een genoemde oplosser aan, maar elke is de lokale updateregel van een variationeel probleem, en samen maken ze de doelstelling expliciet. Op de geklipte regio $\Omega$ minimaliseert de reconstructie vier gekoppelde energieën op het model.

1. Affiene consistentie tussen kanalen. Waar een geldige geleide $g$ bestaat, moet elk geklipt kanaal een affiene functie van de geleide zijn: het geleide filter is de exacte minimalisator van

$$ E_{\text{affine}} = \sum_{\omega}\sum_{c}\sum_{i \in \omega} w_i \Big[ \big( a_{c} \, u_g(i) + b_{c} - u_c(i) \big)^2 + \varepsilon\, a_{c}^2 \Big], \qquad w_i = [\,i \text{ valid}\,]. $$

Fitten op de volledige waarden $u$ (niet het detail) is wat de minimalisator het lokale gemiddelde laat dragen, zodat $E_{\text{affine}}$ magnitude en textuur samen herstelt.310 Deze term wordt vertrouwd in verhouding tot de gekwadrateerde correlatie van de fit $(R^2)^2$; waar $R^2 \to 0$ wordt het kanaal in plaats daarvan gehouden aan zijn eigen tweede-orde-gladheid (een per-kanaal biharmonische term $\int_\Omega (\Delta u_c)^2, \mathrm{d}\Omega$), zodat de doelstelling nooit een kleurlijn beloont die de data niet ondersteunt. Het kwadrateren scherpt die afweging aan zodat een middelmatige correlatie leunt op de gladde terugval in plaats van een discontinue gok tussen kanalen.

1b. Anisotroop coëfficiënttransport (de uitgeleverde vorm van term 1). De affiene fit van term 1 definieert haar coëfficiënten alleen waar een venster genoeg vertrouwde data bevat; over de rest van de uitgebrande zone is het model zelf de onbekende. De uitgeleverde methode breidt het uit door een anisotrope Dirichlet-energie op de coëfficiëntvlakken te minimaliseren,

$$ E_{\text{transport}} \;=\; \sum_{p \,\in\, \{a,\, b,\, d,\, R^2\}} \int_{\Omega} \nabla p^{\top} D \,\nabla p \;\mathrm{d}\Omega, \qquad p\big|_{\text{anchors}} = p_{\text{fit}}, $$

waar de ankers de gepoorte fits van term 1 zijn (genoeg vertrouwde massa, $R^2 > 0.25$, begrensde hellingen) en $D$ de variantie-adaptieve stuurtensor is van stap 3, gebouwd uit de gemeten geleidestructuur: gradiënt-dominant op een schone halo-helling (het model reist radiaal naar binnen vanaf de rand), isofoot-dominant waar een harde rand de zone kruist (kleurlijnen mogen niet mengen over een objectgrens). Zijn Euler–Lagrange-vergelijking $\operatorname{div}(D \, \nabla p) = 0$ is de gestuurde vulling; met $D = I$ reduceert het tot de gewone harmonische vulling. De evaluatie $\hat u_c = a\,u_{g_1} + b\,u_{g_2} + d$ tegen de gemeten geleiden sluit de term: de energie transporteert het model, en de data herstelt het detail.

2. Magnitude-kromming (terugval). Waar geen geleide overleeft, is fijn detail verloren maar de laagfrequente vorm niet: die moet de omringende kromming voortzetten in plaats van afvlakken. Voor een gedeeltelijk-geklipt kanaal is dit de per-kanaal biharmonische term $\int_\Omega (\Delta u_c)^2, \mathrm{d}\Omega$ die hierboven al is aangeroepen. Voor de volledig-geklipte kern wordt het één keer toegepast op de gesommeerde luminantie $L_\text{sum} = R+G+B$, één gedeelde koepel in plaats van drie divergente:

$$ E_{\text{bihar}} = \int_\Omega (\Delta L_\text{sum})^2\,\mathrm{d}\Omega, \qquad \Delta^2 L_\text{sum} = 0, \qquad L_\text{sum}\big|_{\partial \Omega} = L_{\text{sum}}^{\text{valid}} , $$

verankerd aan de echte geldige rand van de kern; zijn Euler–Lagrange-vergelijking $\Delta^2 L = 0$ is de gekoepelde vulling hierboven.

3. Chrominantie-gladheid (terugval). Waar geen geleide overleeft, moeten de gereconstrueerde verhoudingen $r = \text{RGB}/L_\text{sum}$ glad zijn en overeenkomen met de rand, optioneel vertekend naar vlakheid:

$$ E_{\text{chrominance}} = \int_\Omega \Big( \lVert \nabla r \rVert^2 + \lambda \, \lVert r \rVert^2 \Big)\, \mathrm{d}\Omega, \qquad r\big|_{\partial \Omega} = r_{\text{valid}} . $$

Zijn Euler–Lagrange-vergelijking is de screened-Poisson-vergelijking die de diffusie integreert,4 en de recombinatie $\text{RGB} = L\cdot r$ sluit de gezamenlijke vulling.

De energieën werken op complementaire pixels: de affiene term waar een kanaal overleeft (gewogen door zijn correlatie $R^2$), de per-kanaal biharmonische term waar het dat niet doet, en de gedeelde luminantiekoepel plus chrominantiediffusie alleen in de volledig-geklipte kernen — de laatste geminimaliseerd onder een ongelijkheid: de gediffundeerde verhouding van een geklipt kanaal kan nooit onder zijn verzadigingsvloer in verhoudingsruimte dalen, $r_c \geq c_{0,c}/L_\text{sum}$, wat de chrominantieterm in een obstakelprobleem verandert (de wiskunde staat in de chrominantie-subsectie). De reconstrueerbare verzameling zelf is per kanaal: $\Omega_c$ bevat de pixels boven de clipdrempel — verlengd tot $0.9$ ervan voor kanalen waarvan de sensor-rolloff inschakelde (de bandoverride van stap 2), waar de vloer $c_{0,c}$ de knie-gecorrigeerde meting is in plaats van de verzadigde uitlezing. Elke energie wordt geminimaliseerd door zijn eigen fase: de affiene term door de geleide fits (één venster gedimensioneerd op de reconstructie- radius van de regio); de transportterm door de verankerde, gestuurde relaxatie van stap 3; de gladheidstermen door hun directe lineaire oplossingen. Er is bewust geen posterieure gladstrijk- energie die op de uitvoer werkt: een eerder ontwerp streek naden achteraf glad met een onzekerheids-gewogen regularisator, en het pensioneren daarvan is het punt — de naden worden nooit gecreëerd (zie het kerkhof). Dit is dezelfde engineeringfilosofie als diffuse or sharpen: een stapel lokale, fysiek gemotiveerde updateregels waarvan het gecombineerde vaste punt de reconstructie is, in plaats van één monolithisch invers probleem.

Het algoritme

Alles gebeurt op het raw-mozaïek, in lineaire scènegerefereerde RGB, vóór demozaïceren, en op volledige resolutie. De methode herbouwt elk geklipt kanaal uit de kanalen die overleefden (langs de lokale kleurlijn, en vertrouwt die in verhouding tot hoe goed hij daadwerkelijk standhoudt), en waar geen kanaal overleefde herbouwt hij één gezamenlijke luminantiekoepel en draagt de omringende chrominantie naar binnen.

De mozaïekvoorbereiding — bilineair demozaïceren naar een wegwerp-RGB, lokale kanaal- normalisatie, en het per-kanaal clipmasker — wordt gedeeld met de methode uit 2021 en beschreven in haar algoritmesectie, met één toevoeging en drie verfijningen. De toevoeging: voor de volledig-geklipte kernen wordt een scalaire magnitude $L_\text{sum}$ (de gesommeerde luminantie $R+G+B$) gesplitst van de chrominantie $\text{RGB}/L_\text{sum}$ — elk kanaal gedeeld door de gesommeerde luminantie, een begrensde, helderheidsvrije beschrijving van de kleur die dit artikel consequent onder die naam gebruikt — zodat de twee met verschillende middelen kunnen worden gereconstrueerd: een koepel voor de magnitude, diffusie voor de chrominantie. De verfijningen, elk herleid tot een gemeten randartefact:

  • maskers zijn binair, van begin tot eind. De modus uit 2021 verzacht haar masker; de opvolger houdt elk geldigheids- en compositiemasker hard (zijn ene gladde gewicht is de vervaagde overdracht van de gezamenlijke kern, stap 7 van het algoritme, die twee reconstructies mengt — het herclassificeert nooit metingen). De per-kanaal geldigheidsmaskers poorten elke fit en evaluatie, en het verzachten ervan herclassificeerde rand-geklipte fotosites — waarvan de raw-waarden op de detectiedrempel zitten, laag vertekend onder sensor-rolloff — als geldige ankers op schuine contouren, en trok de rand- reconstructie naar het clipniveau (een $\sim 10$ px doorzakkende helling tegen ground truth). Het compositiegewicht is een harde schakelaar: geldige fotosites houden hun meting exact, geklipte fotosites nemen de pure reconstructie (van een verzachte alfa werd gemeten dat het niets veranderde zodra de twee fixes op deze lijst aanwezig zijn — het pensioneren wordt gedocumenteerd in het kerkhof).
  • geklipte raw-waarden zijn vloeren, nooit mengdoelen. Op geklipte fotosites is de raw- uitlezing een ondergrens, geen meting: de composiet schrijft $\max(\text{raw}, \text{reconstruction})$, nooit een menging naar de vertekende uitlezing (de oude verzachte menging drukte een V-vormige dip door de raw-waarde bij elke contour).
  • randen spiegelen. De randring van de bilineaire gather kopieerde vroeger de centrumfotosite naar alle drie kanalen en koppelde alle drie clipvlaggen aan het eigen kanaal van het centrum — corrupte geleiden en gestreepte maskers langs de eerste en laatste rijen en kolommen, die de fits van de randrij op het clipniveau verankerden. Gespiegelde buurindexering (het Bayer-patroon is 2-periodiek, dus spiegelen behoudt de kleur van elke buur) herstelt de interieurlogica op de randen; deze fix wordt gedeeld met de modus uit 2021.

Elke ground-truth-scène verbeterde op beide metrieken alleen al door deze drie verfijningen — de fout van de rolloff-lucht daalde met een derde — omdat de randringen van de bench precies zijn waar vertekende ankers vroeger naar binnen lekten.

Het conceptuele doel van de reconstructie kan in één zin worden gesteld: overal waar minstens één kanaal overleefde, is reconstructie een regressie- probleem, geen inpainting-probleem: de geldige kanalen zijn gemeten data, aanwezig bij elke pixel van de geklipte zone, die de echte structuur van de scène dragen. De ene ontwerpregel van het algoritme, op de harde manier geleerd, is dat geen stap mag overdragen tussen schatters die het oneens zijn (de naadenergiewet van de theoretische bevindingen). Elke fase hieronder is daarom ofwel naadloos door constructie, ofwel ontvooroordeelt de data zodat de schatters het eens zijn.

De stapsgewijze procedure, zoals geïmplementeerd in process_harmonic_bayer (en zijn X-Trans-tweeling):

De getallen in de grafiek verwijzen naar de stappen die eronder worden gedetailleerd.

flowchart TD
  subgraph P ["once per image"]
    direction TB
    A["raw mosaic"] --> B["1 · interpolate
+ clip masks"] B --> K["2 · knee inversion"] K --> S["1 · depth map
+ segmentation"] end subgraph R ["for each clipped region"] direction TB CF["3 · colour-line fits
(magnitude + texture)"] --> HF["4 · fine-detail refit"] HF --> SD["5–6 · floors
+ self-dome"] SD --> JC["7 · all-clipped core"] JC --> AN["8 · chrominance coherence"] end S --> CF AN --> O["remosaic + composite"]

1. Detectie, interpolatie, segmentatie. Het raw kleurenfilterarray-mozaïek wordt bilineair geïnterpoleerd, met per-kanaal clipvlaggen gehesen bij $0.995\,c$ voor clipniveau $c$ en een binair per-kanaal geldigheidsmasker; de Euclidische afstandstransformatie geeft dan elke pixel zijn diepte $\delta$ binnen de geklipte zone, en verbonden-componenten- segmentatie groepeert de geklipte pixels in regio’s, elk met zijn afstandstransformatie- reconstructieradius.

2. Inversie van sensor-rolloff (knie). Echte sensoren comprimeren de laatste paar procent onder verzadiging, dus de band nabij clipping $[0.8\,c, 0.995\,c)$ bevat waarden die laag vertekend zijn. (De band wordt royaal afgesneden: op sensoren die hard klippen in plaats van afrollen, maakt de no-op-garantie hieronder de extra breedte gratis.) De reconstructie extrapoleert onvertekende schattingen over deze band, dus de twee zijn het oneens bij de detectiecontour: een naad die geen weging kan verwijderen. De fix ontvooroordeelt de data zelf: een gevensterde gezamenlijke regressie voorspelt elke bandwaarde uit de volledig-vertrouwde kanalen, de (gemeten, voorspelde) paren worden samengevoegd in 24 bins over de band, en de per-bin mediane lift wordt geaccepteerd alleen wanneer statistisch significant — mediaan boven tweemaal zijn standaardfout, een $\approx 95\,\%$ betrouwbaarheidspoort, met minstens 100 stemmen zodat de foutschatting zelf stabiel is; 24 bins is zo fijn als de band kan worden afgesneden terwijl elke bin die bevolkt raakte behouden blijft:

$$ \hat{k}^{-1}(v) = v + \operatorname{median}\big\{\, \hat v_i - v_i \;\big|\; v_i \in \text{bin}(v) \,\big\} $$

waar $k$ de onbekende compressie van de sensor is, dus $\hat{k}^{-1}$ is de geschatte correctie — de functie die een gemeten waarde $v$ uit de band neemt en teruggeeft wat de sensor had moeten registreren. De $v_i$ zijn alle gemeten bandpixels waarvan de waarde in dezelfde bin valt als $v$; elke $\hat v_i$ is wat de kleurlijnregressie voorspelt dat die pixel zou moeten zijn, geoordeeld naar zijn volledig-vertrouwde naburige kanalen. Hun verschil $\hat v_i - v_i$ is de stem van één pixel over hoeveel de sensor te weinig registreerde op dat niveau, en de correctie van de bin is de mediaan van zijn stemmen — robuust tegen de uitschieters die een gemiddelde zou volgen. De resulterende curve wordt vervolgens monotoon en alleen-verhogend gemaakt. Op hard-geklipte (onvertekende) data is elke bin-mediaan nul binnen ruis, dus de correctie heeft een no-op-garantie, bit-exact geverifieerd op de vier hard-clip- synthetische gevallen, terwijl op pk1synth (de ene synthetische scène gegenereerd met een analytische sensor-rolloff, zodat haar ground truth de echte knie volgt) de blinde schatting overeenkomt met de echte curve tot een root-mean-square-fout van $7\cdot10^{-4}$ op het groene kanaal en $1.8\cdot10^{-3}$ op het schaarsere rode:

The blind knee estimate against the ground truth, on the one synthetic scene with an analytic sensor rolloff (pk1synth). Circles : the true corrected value, read from the (ground truth, clipped) pixel pairs, per measured-value bin. Lines : what the estimator infers from the clipped mosaic alone, never having seen the truth. The dotted diagonal is the identity — a sensor with no rolloff. Reproduce with make_knee_figure.py.
Twee implementatiedetails zijn belangrijk: schatting draait op een $2\times 2$ quad-binned kopie van het raw-mozaïek (elke 2×2 Bayer-cel levert één gecolokaliseerd rood, groen (gemiddeld) en blauw monster), nooit op de bilineaire interpolatie: de interpolatie bemonstert elk kanaal via een ander ruimtelijk filter afhankelijk van zijn positie in het mozaïekpatroon, en die afwisselende fout heeft dezelfde grootte als het kniesignaal dat het zou verdrinken; en de correctie wordt toegepast op zowel de reconstructieankers als op de gecomposeerde uitvoer, terwijl clipdetectie gekoppeld blijft aan de gemeten waarden.

De bandoverride. De lift herstelt het niveau van de band, maar een waardekaart kan geen helling herstellen die de sensor nooit registreerde: waar de compressie de band tot een bijna-constante afvlakte, is de gelifte band ook een bijna-constante, en zijn overgang met de stijgende reconstructie drukt een fijne dubbele contour onder randvergroting (de band is meetbaar $7$–$14\times$ vlakker dan ground truth, ingeklemd door twee gradiëntpieken). De informatie is echter niet verloren — de geleiden zijn ongeklipt door de band en dragen de echte helling. Dus voor elk kanaal waarvan de rolloff inschakelde, breidt de detectie zich uit onder de drempel de diepe band in: die pixels worden gereconstrueerd door het kleurlijnmodel zoals elke geklipte pixel, met hun knie-gelifte meting als hun per-pixel verzadigingsvloer, en de fits verankeren op knie-gecorrigeerde data onder de band. De vloer maakt de override conservatief door constructie — op ruizige echte beelden overschrijdt het model zelden de gelifte meting, en de uitvoer blijft pixel-identiek; op de rolloff-benchscène, waar het model de helling echt kent, daalt de zonefout met nog een factor van vijf wanneer de override landt (RMSE $0.012 \to 0.0025$ toen gemeten; $0.0053$ in de uitgeleverde build, nadat de latere compositierondes hun eigen happen namen) en wordt het contour-gradiëntprofiel ononderscheidbaar van ground truth. Kanalen zonder een gemeten rolloff houden de gewone detectie: op hard-clippende sensoren is de band betrouwbare data en blijft verankerd.

3. Het coëfficiëntveld. Voor elk geklipt kanaal $v$ met geleiden $u_1, u_2$ wordt een gevensterde gewogen-kleinste-kwadraten-fit berekend op één enkele schaal $\sigma = \operatorname{clip}(r/6, 8, 64)$ (met $r$ de reconstructieradius van de regio — de $\pm 3\sigma$-ondersteuning van het venster overspant dan de radius, zodat zelfs de fit van de diepste pixel geldige data bereikt; de vloer houdt genoeg monsters voor een stabiele fit op kleine regio’s, en de bovengrens begrenst de kosten van enorme), over de pixels waar alle drie kanalen geldig zijn:

$$ \begin{aligned} (a, b, d)(x) &= \arg\min_{a,b,d} \sum_y w(y)\, G_\sigma(x - y)\, \big( v(y) - a\, u_1(y) - b\, u_2(y) - d \big)^2 \\ \hat v(x) &= a(x)\, u_1(x) + b(x)\, u_2(x) + d(x) \end{aligned} $$

waar $x$ de pixel is waarvan het lokale model wordt gebouwd en $y$ over zijn buren loopt. Het venster $G_\sigma(x-y)$ is een Gaussiaan die buren weegt naar afstand (vol gewicht nabij, vervagend over ongeveer $\sigma$ pixels), en $w(y)$ is het vertrouwensmasker — één op pixels waar alle drie kanalen echte metingen bevatten, nul elders, zodat geklipte pixels nooit stemmen. De eerste regel vraagt, bij elke $x$: welke hellingen $a, b$ op de twee geleiden en welke offset $d$ verklaren het geklipte kanaal het best op de vertrouwde buurt? De tweede regel gebruikt dan dat lokale model: de schatting $\hat v(x)$ leest de twee geleiden bij $x$ zelf en mapt ze via de gefitte relatie. In de praktijk wordt de minimalisatie nooit per pixel gedraaid — het wordt opgelost uit tien vervaagde momentvlakken (een vertrouwde-massa-telling, drie gemiddelden, zes tweede momenten, verzameld in drie vier-kanaals vervagingen) via de $2\times2$ normaalvergelijkingen. De momenten worden geaccumuleerd rond het per-regio-gemiddelde van elk kanaal: in float-rekenkunde valt de rauwe $E[u^2] - E[u]^2$-vorm catastrofaal weg op gladde inhoud (het gekwadrateerde gemiddelde overtreft de variantie ruimschoots) en de deling van de fit versterkt de overlevende cijfers tot apparaatafhankelijke helling- ruis — centreren verwijdert de wegval, en de hellingen en $R^2$ zijn invariant onder de verschuiving terwijl het intercept ongeschoven is direct na de fit. Het systeem wordt opgelost met een relatieve Tikhonov-(ridge-)demping $\lambda = 10^{-3}\,(\operatorname{var} u_1 + \operatorname{var} u_2)/2$ die schaalt met het signaal in plaats van zwakke-maar-echte hellingen op te eten. De $10^{-3}$ is de kleinste factor die gedegenereerde vensters op de bench stabiliseerde — iets groters begint echte hellingen af te vlakken.

Het nieuwe is wat er daarna gebeurt: in plaats van elke pixel te evalueren met welke fit zijn eigen venster ook kon bereiken (de manier van de ladder), worden de coëfficiëntvlakken zelf gediffundeerd over de geklipte zone, gestuurd door de gemeten geleidestructuur, en pas dan geëvalueerd tegen de gemeten geleiden. Coëfficiënten zijn van nature glad waar waarden dat niet zijn: ze diffunderen transporteert het model de zone in, en de evaluatie herstelt de volledige lokale structuur die door de geldige kanalen wordt gedragen. Geen schalen, geen dieptepoorten, geen level-set-schrijvingen (geen ringen van gelijke diepte apart gestempeld) — geen naden, door constructie. Dit transport van het model in plaats van de inhoud is het meest overdraagbare idee van het artikel, en hoe het in soort verschilt van de eigen coëfficiëntvervaging van het geleide filter wordt gesteld in Drie resultaten waarvan wij geloven dat ze algemeen zijn. Een pixel kwalificeert alleen als diffusie-anker als zijn venster genoeg vertrouwde massa bevatte én zijn fit gezond is: de $R^2$ van de fit, de determinatiecoëfficiënt, is het aandeel van de lokale variantie van het kanaal dat de kleurlijn verklaart (1 betekent dat de geleiden het kanaal perfect voorspellen, 0 betekent helemaal niet), en ankers vereisen $R^2 > 0.25$ met begrensde hellingen. Beide poorten zijn gekalibreerd uit metingen, niet uit smaak: inhoud met helemaal geen kleurlijn scoort nog steeds $R^2 \approx 0.25$–$0.6$ (tegenover $\approx 0.9$ waar de kleurlijn echt is), dus de poort verwerpt alleen fits die slechter zijn dan pure decorrelatie — numerieke ongelukken, geen zwakke modellen; en fysieke kleurlijnhellingen worden begrensd door de verzadigingsverhoudingen van de kanalen (onder $4$ op elke gemeten camera), dus de $|a| < 64$-grens zit een orde van grootte boven alles wat fysiek is, en alleen gedegenereerde bijna-nul-variantievensters — waarvan de exploderende hellingen de diffusiegrens zouden vergiftigen — struikelen er ooit over. De diffusie is een grof-naar-fijne Jacobi-vulling: elke onbekende wordt herhaaldelijk vervangen door het gemiddelde dat zijn buren impliceren. Drie termen dragen het hele schema:

  • Cel. De vulling draait niet per pixel. De coëfficiëntvlakken leven op een grof raster met spoed $\sigma/4$ (geklemd tot ten hoogste $8$ px), en een cel is één knoop van dat raster — één $\sigma/4$-groot blok pixels. De coëfficiënten komen uit $\sigma$-brede fitvensters, dus vier cellen per $\sigma$ oversampelen ze, en de spoedklem begrenst de uiteindelijke bilineaire opschalingsfout.
  • Anker. Een cel waarvan het fitvenster de bovenstaande vertrouwenspoorten passeerde — het bevat een coëfficiënt daadwerkelijk gemeten op geldige data.
  • Vastgepind. De vegen behandelen ankers als vaste grensdata en herschrijven alleen ooit de onbekende cellen ertussen.

Deze vorm is gekozen voor robuustheid. Een float-conjugate-gradient op het bijna-singuliere puur-harmonische systeem divergeert stochastisch wanneer de zone de regiogrens bereikt. Jacobi met vastgepinde ankers kan dat niet: elke update is een gemiddelde van buren, dus de relaxatie gehoorzaamt het maximumprincipe — geen onbekende kan ooit het bereik van de ankerwaarden verlaten.

Convergentie komt van de diepte van de piramide, niet van het aantal vegen. Het grofste niveau start vanuit een vlak ankergemiddelde — de verst mogelijke toestand van de oplossing — en Jacobi’s traagste foutmodus op een gat $N$ cellen breed vervalt in $\mathcal{O}(N^2)$ vegen. Dus de piramide blijft halveren totdat de lange zijde van het grofste raster ten hoogste $8$ cellen is ($8^2 = 64$ vegen om te relaxeren, comfortabel binnen het budget), en elk niveau draait dan dezelfde vlakke $100$ vegen — de fijnere niveaus corrigeren alleen lokale interpolatiefout. Een ondiepere piramide met een vast aantal kapte de vulling meetbaar af op diepe gaten — de getallen staan in de algemene resultaten hieronder.

Het transport zelf is ook niet uniform: het wordt gestuurd door de gemeten geleidestructuur. Een stuurvlak $L_\text{mean}$ — het gemiddelde van de geldige kanalen overal waar er minstens één overleeft, het vlakke plateaugemiddelde in de volledig-clip-kern (waar de tensor dan degenereert tot de identiteit); dit is een andere luminantie dan de gesommeerde magnitude $L_\text{sum}$ die de koepel en de verhoudingen gebruiken — wordt neergeschaald naar elk piramideniveau, en de buurgemiddelden worden gewogen door de anisotrope tensor

$$ D \;=\; \big[\, m + (1-m)\,c_2 \,\big]\; t\,t^{\top} \;+\; \big[\, m\,c_2 + (1-m) \,\big]\; g\,g^{\top}, \qquad c_2 = e^{-\lVert\nabla L_\text{mean}\rVert / (4\,\langle\lVert\nabla L_\text{mean}\rVert\rangle)}, $$

waar $g$ de eenheidsgradiëntrichting van $L_\text{mean}$ is (bergopwaarts), $t$ de eenheidsisofoot- richting, en $\langle\lVert\nabla L_\text{mean}\rVert\rangle$ de gradiëntmagnitude gemiddeld over de regio — de normalisatie die de demping belichtingsonafhankelijk maakt — (langs de niveaulijnen), en $c_2$ dezelfde randkruisende demping als de chrominantiepassage van stap 8. Het normaliseren van de gradiënt door zijn eigen regionale gemiddelde maakt die demping schaalvrij — alleen gradiënten ruim boven het gemiddelde van de halo lezen als grenzen, waarbij de $4$ instelt hoe zacht de uitlezing is. Het menggewicht $m \in [0, 1]$ is de randwaarschijnlijkheid, gemeten uit de trend-gecorrigeerde gevensterde variantie van $L_\text{mean}$:

$$ m = \frac{v}{v + (k\,\bar L_\text{mean})^2}, \qquad v = \max\!\big(\operatorname{var}_w(L_\text{mean}) - \tfrac{4}{3}\lVert\nabla L_\text{mean}\rVert^2,\; 0\big), \qquad k = 0.15, $$

waar $\operatorname{var}_w$ en $\bar L_\text{mean}$ de gevensterde variantie en het gemiddelde van het stuur- vlak zijn, en de $\tfrac{4}{3}\lVert\nabla L_\text{mean}\rVert^2$-term trekt de variantie af die de lokale helling verklaart: een pure helling van hellingsgraad $\nabla L_\text{mean}$ gezien door een venster van ruimtelijke variantie $\sigma_w^2$ heeft intensiteitsvariantie $\sigma_w^2 \lVert\nabla L_\text{mean}\rVert^2$, en het venster hier (twee $3\times3$ box-passages) heeft $\sigma_w^2 = 2 \cdot \tfrac{2}{3} = \tfrac{4}{3}$ per as. Een gladde halogradiënt, hoe steil ook, laat daarom geen residu, terwijl een harde rand variantie laat die geen helling kan verklaren. De drempel $k$ — het relatieve contrast waarboven resttextuur als grens wordt gelezen — is de ene constante van het transport die niet kon worden afgeleid, dus werd hij gekalibreerd door een empirische fijne sweep op de zes ground-truth- scènes: elke scène blijft op of onder de isotrope fout over het hele bereik $k \in [0.14, 0.25]$ (het ontwerp is er niet fragiel voor), en $k = 0.15$ is de waarde die elke scène tegelijk verbetert en de occlusie-winst met marge pakt. De twee limieten van $m$ lezen natuurlijk. Op een schone halo-helling ($m \to 0$), $D \to g\,g^{\top} + c_2\,t\,t^{\top}$: het model reist radiaal, langs de helderheidshelling van de rand naar binnen, waar zijn informatie daadwerkelijk leeft. Waar een harde rand de uitgebrande zone kruist ($m \to 1$), $D \to t\,t^{\top} + c_2\,g\,g^{\top}$ met $c_2$ klein: het transport loopt langs de grens en weigert die te kruisen — een rand binnen de zone betekent dat de inhoud daarachter een andere kleurlijn volgt, en de twee modellen eroverheen mengen is precies het occlusiefalen dat het kerkhof documenteert. De discretisatie gebruikt de niet-negativiteit-behoudende stencil gedeeld met de diffusie van stap 8 (alle acht buurgewichten $\geq 0$), zodat de gestuurde vulling een convexe combinatie van zijn ankers blijft: het maximumprincipe overleeft het sturen. Een $10^{-4}$ gewichts- vloer houdt elke cel verbonden waar de tensor tot bijna-nul instort; vier orden van grootte onder de werkende gewichten, concurreert het nooit met het sturen. Pixels met een enkele overlevende geleide krijgen dezelfde behandeling met een één-geleide-fit.

Eén ordeningssubtiliteit voltooit de stap. Het diepste kanaal — dat met de meeste geklipte fotosites, waarvan de zone de kernen bevat waar meerdere kanalen tegelijk uitgebrand zijn — wordt niet meteen geëvalueerd: zijn gediffundeerde coëfficiënten worden bewaard, en de evaluatie draait als laatste, nadat de andere geklipte kanalen zijn gereconstrueerd, zodat elke geleide die het leest een continu oppervlak is. Het evalueren tegen een geleide die van gemeten waarden naar een clipplateau springt zou de eigen clipcontour van die geleide in het resultaat drukken als een zichtbare boog. Diep binnen de kern, waar die geleiden zelf reconstructies zijn (dus elke sprong vergroot de fout), mengt de schatting terug naar de directe één-geleide-fit via een glad gewicht — glad gewicht maal gladde velden laat geen level-set achter om te drukken.

De fitkwaliteit $R^2$ wordt naast $(a, b, d)$ als een vierde vlak gediffundeerd, op de bredere alleen-massa-ankerverzameling (het blijft begrensd zelfs waar de fit dat niet doet).

4. Hybride Laplaciaan-band-sturing van de hoge frequenties. De volledig-signaal-fit draagt de fijne textuur van de geleiden over met de winsten die de totale covariantie impliceert; waar de kleurlijn zwak is hoort die textuur niet op het gereconstrueerde kanaal. De schatting wordt gesplitst bij $\sigma/4$ en zijn detailband wordt herbouwd uit twee kandidaat-bronnen: de gedempte overdracht (de volledig-signaal hoge frequenties geschaald door de gediffundeerde $R^2$) en een speciale detailband- kleurlijn (de naamgenoot van de methode uit 2021, teruggekeerd), gefit op de hoogfrequente vlakken met $R^2$-gekrompen winsten (op een nul-gemiddelde band is krimp de juiste schatter: er is geen magnitude te verliezen, alleen ruis om niet te drukken). De twee worden gemengd door kwadratische min-energie-odds,

$$ w = \frac{e_d^2}{e_d^2 + e_g^2}, \qquad e_{d,g} = \text{blurred } |\text{HF}_{d,g}|, $$

die geen inhoudsdiscriminator nodig heeft: een gemengd-venster-winst die misvuurt bij een objectrand toont zich als een lokale piek van hoogfrequente energie, dus het falen detecteert zichzelf en het gedempte pad neemt precies daar over. Dit is wat het laatste residu van de rolloff-scène verwijdert (zijn overtollige-rand-score valt van 1.48 naar 0.94 tegen een ground-truth-vloer van 0.69: de gedecomprimeerde bandruis drukt niet meer — de randvertekeningsfixes van de uiteindelijke build brengen het naar 0.74, en de bandoverride van stap 2 naar 0.64, de resultatentabel) terwijl het de getextureerde gevallen die de pure detailband-fit vroeger brak verbetert.

5. Zachte verzadigingsvloer. De fysieke vloer (een geklipt kanaal is minstens zijn verzadigde uitlezing $c_0$) wordt toegepast als een afgeronde beperking, $\tfrac{1}{2}\big(e + c_0 + \sqrt{(e - c_0)^2 + (0.02\,c_0)^2}\,\big)$: de harde $\max(e, c_0)$ drukt de bindende contour als een rand overal waar een zwakke voorspelling rond verzadiging oscilleert. De $0.02\,c_0$ overgangsbreedte is twee procent van de verzadigde waarde — onder alles wat zichtbaar is, maar breed genoeg dat de gradiënt van de beperking nooit springt.

6. Diepte-gepoorte, tint-gekoppelde zelf-koepel. Waar het model twijfelachtig is én de pixel ondiep is, neemt een gladde zelf-voortzetting over, gebouwd tint-gekoppeld (de kanalen zijn gekoppeld via één gedeelde chrominantie, zodat de waargenomen tint niet kan verschuiven): één gedeelde biharmonische luminantiekoepel maal een harmonisch-gevulde chrominantie, nooit drie onafhankelijke kanalen, zodat de terugval de tint niet naar groen/magenta kan splitsen (het falen dat zijn per-kanaal-voorouder uitgeschakeld hield). Het overdrachtsgewicht is:

$$ \text{dome fraction} = \big(1 - S_{0.4}^{0.85}(R^2)\big)\; e^{-\left(\delta / 1.5\sigma\right)^2} $$

waar $\delta$ de diepte van de pixel binnen de geklipte zone is (zijn afstand tot de dichtstbijzijnde geldige pixel), $\sigma$ de fitschaal, en $S$ een smoothstep, een zachte helling van 0 naar 1 tussen de twee drempels, hier fitkwaliteit onder $0.4$ mappend naar “twijfelachtig” en boven $0.85$ naar “vertrouwd”. De randen van de band en de $1.5\sigma$ diepteschaal werden afgestemd op de ground-truth- bench; de diepteschaal koppelt het bereik van de koepel aan het eigen bereik van het fitvenster, zodat de overdracht gebeurt waar de fit echt geen monsters meer heeft. De twee factoren beantwoorden twee verschillende vragen: $R^2$ vraagt is de kleurlijn hier echt, en diepte vraagt is de koepel hier betrouwbaar (biharmonische extrapolatie is uitstekend nabij de rand en verslechtert met afstand). Diepte is het enige signaal dat we vonden waarvan de distributies daadwerkelijk gecorreleerde diepe zones scheiden van gedecorreleerde ondiepe inhoud (zie het kerkhof); diepe interieuren blijven altijd op het coëfficiëntveld.

7. Gezamenlijke kern, verzacht. Volledig-geklipte pixels hebben geen geleiden: de gedeelde biharmonische luminantiekoepel en de screened rand-chrominantiediffusie van de herbouw reconstrueren ze, onveranderd — maar de composiet wordt nu verzacht over een vervaagd volledig-clip-masker in plaats van geschreven door een hard masker. De koepel en de gediffundeerde chrominantie zijn beide geldig voorbij de gatgrens, dus ze mengen in de geklipte kanalen van de omringende ring is continu in de ruimte zonder kosten voor de kern zelf.

8. Chrominance coherence. The structure-steered chrominance of the all-clip core is now solved directly. The unknown $u$ is each chrominance plane in turn ; the equation is $\mathrm{div}(D\,\nabla u) = 0$, the steady state of the anisotropic diffusion of the theory section and, equivalently, the exact minimizer of its weighted smoothness energy $\int_\Omega \nabla u^\top D\,\nabla u\,\mathrm{d}\Omega$, with the coefficient-field results as Dirichlet anchors, fixed boundary values the solve must honour. The tensor is built from the recovered luminance (the reconstruction’s own output, smoothed by two box-blur passes) : with $g$ the unit gradient of that smoothed luminance and $t = g^\perp$ the isophote direction,

$$ D = t\,t^\top + e^{\,-\lVert \nabla L_\text{sum} \rVert / (4\,\langle \lVert \nabla L_\text{sum} \rVert \rangle)}\; g\,g^\top $$

dat wil zeggen: geleidbaarheid één langs isofoten, exponentieel gedempt eroverheen, de demping genormaliseerd door de eigen gemiddelde gradiëntmagnitude van het beeld $\langle \lVert \nabla L_\text{sum} \rVert \rangle$ zodat het sturen niet afhangt van belichting (deze tensor leest de herstelde gesommeerde luminantie — de tweelingvorm van de coëfficiëntvulling leest $L_\text{mean}$). De discretisatie is Weickerts niet-negativiteit-behoudende stencil, een symmetrische positief-definiete M-matrix, zodat het discrete maximumprincipe door constructie geldt: de gediffundeerde verhoudingen kunnen nooit de rand-chrominantie overschieten, wat de eerdere expliciete stroom wel kon. De sparse Cholesky factoriseert de kern één keer en substitueert terug de drie kanalen. (Een oplosser-bake-off zit achter deze keuze: zie het kerkhof voor het leerzame falen van de andere exacte formulering.) De uiteindelijke remozaïek componeert de uitvoer uit de knie-gecorrigeerde CFA, zodat de ontvooroordeelde band het bestand bereikt, niet alleen de fits.

De updateregels

Het optimalisatieprobleem stelt wat de reconstructie minimaliseert en het algoritme vertelt zijn fasen; de discussie hieronder analyseert het ontwerp — wat de parameters vertegenwoordigen, hoe ze werden afgestemd, hoe de keuzes zich verhouden tot gevestigde theorie. Wat een implementator die vanaf nul begint nodig heeft zijn de eigenlijke signaalupdates: welke vergelijking welk vlak schrijft, in welke volgorde. Hier is de volledige catalogus, in uitvoeringsvolgorde, voor één regio. Vlakken: per-kanaal schattingen $u_c$ (geïnitialiseerd op de bilineaire interpolatie van het gemeten mozaïek, knie-gecorrigeerd), binaire geldigheden $v_c$, per-pixel vloeren $c_{0,c}$ (de knie-gecorrigeerde meting van elke reconstrueerbare pixel), gesommeerde luminantie $L_\text{sum} = \sum_c u_c$ en verhoudingen $r_c = u_c / L_\text{sum}$ (het stuurvlak $L_\text{mean}$ van regel 1 is het geldige-kanaal-gemiddelde, een aparte grootheid).

1. Fit en transporteer de kleurlijn (stappen 2–3 van het algoritme). De fit is op de volledige pixelwaarden — nooit het gemiddelde-afgetrokken detail — en gebruikt alleen de monsters waar de betrokken kanalen geldig zijn. In de één-geleide-vorm, over het Gaussische venster $\omega$:

$$ a_c = \frac{\operatorname{cov}_\omega(u_g, u_c)}{\operatorname{var}_\omega(u_g) + \varepsilon}, \qquad b_c = \bar u_{c,\omega} - a_c\, \bar u_{g,\omega}, \qquad R^2 = \frac{\operatorname{cov}_\omega(u_g, u_c)^2}{\operatorname{var}_\omega(u_g)\,\operatorname{var}_\omega(u_c)}, $$

met $\varepsilon$ een relatieve Tikhonov-demping die de deling bewaakt waar de geleide vlak is; de twee-geleide-vorm lost de analoge $2\times2$ normaalvergelijkingen voor $(a, b, d)$ op uit de tien Gaussisch-vervaagde moment- vlakken. De helling is niet teken-geklemd (een vroege ladder-revisie klemde het; de uitgeleverde fits worden in plaats daarvan bewaakt door de ankerpoorten $R^2 > 0.25$ en $|a| < 64$). Twee meer poorten die een implementator niet mag overslaan: de fitvensters worden gewogen door een zachte luminantie-affiniteit $\min(L_\text{sum} / 0.35\,\bar L_\text{sum}^{\,\text{rim}}, 1)^2$ — monsters veel donkerder dan de rand (occluders) stemmen nauwelijks — en een venster verankert het transport alleen waar zijn gewogen massa zowel een absolute vloer (0.05) als een kwart van zijn ongewogen geldige massa overschrijdt, zodat geoccludeerde vensters uitstellen naar de vulling in plaats van de occluder te fitten. Omdat de fit op waarden is, draagt het intercept het lokale gemiddelde van de kleur: de voorspelling erft het niveau van de omringende geldige data, niet alleen zijn textuur, dus waar de geleide blijft stijgen het hoge licht in volgt de schatting het — boven de clipwaarde. In de praktijk wordt de fit nooit per pixel gedraaid: de momenten zijn Gaussisch-vervaagde productvlakken, gecentreerd op de per-regio geldige gemiddelden tegen float-wegval.

Poort de ankers ($R^2 > 0.25$, begrensde hellingen, vertrouwde massa), diffundeer dan elk coëfficiëntvlak door verankerde Jacobi-vegen op het grove raster — de update van één veeg bij een niet-anker-cel $i$, met de acht Weickert-gewichten $w_{ik}$ van de tensor $D$:

$$ a_i \;\leftarrow\; \frac{\sum_{k \in \mathcal{N}_8(i)} w_{ik}\, a_k}{\sum_{k \in \mathcal{N}_8(i)} w_{ik}}, $$

ankers vast gehouden, 100 vegen per piramideniveau, grofste niveau gezaaid met het ankergemiddelde en elk fijner niveau gezaaid door bilineaire opschaling van de grovere oplossing; dezelfde update voor $b$, $d$ en $R^2$. Evalueer dan het getransporteerde model tegen de gemeten geleiden, bij elke pixel waar het doel geklipt is en beide geleiden geldig zijn:

$$ u_c(x) \;\leftarrow\; a(x)\, u_{g_1}(x) + b(x)\, u_{g_2}(x) + d(x). $$

Pixels met een enkele geldige geleide nemen dezelfde update van de één-geleide-fit $u_c \leftarrow a\, u_g + d$. De evaluatie van het diepste kanaal wordt uitgesteld totdat de andere geklipte kanalen zijn herbouwd, zodat zijn geleiden continue oppervlakken zijn.

2. Herbouw de hoge frequenties (stap 4). Splits $u_{g}$ in lage frequentie $\bar u_g$ (Gaussiaan op $\sigma/4$, met vloer op 2 px — de momenten gebruiken de $\sigma$ van de fit, de bandsplitsing niet) en detail $u_g - \bar u_g$; vorm de twee kandidaten — de geleide-overdracht $h_g = a\,(u_{g_1} - \bar u_{g_1}) + b\,(u_{g_2} - \bar u_{g_2})$ en het gedempte zelf-detail $h_d = R^2 (u_c - \bar u_c)$ — en meng ze door kwadratische min-energie-odds op hun lokale (Gaussisch-vervaagde) energieën $e_g, e_d$, precies zoals stap 4 stelt (een harde schakelaar zou een overdrachtnaad herintroduceren):

$$ u_c \;\leftarrow\; \bar u_c + w\, h_g + (1 - w)\, h_d, \qquad w = \frac{e_d^2}{e_d^2 + e_g^2}. $$

3. Zachte verzadigingsvloer (stap 5), overal waar een kanaal reconstrueerbaar is, met $w = 0.02\, c_{0,c}$:

$$ u_c \;\leftarrow\; c_{0,c} + \tfrac{1}{2}\left( (u_c - c_{0,c}) + \sqrt{(u_c - c_{0,c})^2 + w^2}\right). $$

4. Diepte-gepoorte zelf-koepel (stap 6). Los één gedeelde biharmonische voortzetting van de luminantie over het gat op, $\Delta^2 L_b = 0$ met $L_b$ verankerd op de rand (directe sparse Cholesky op de 13-punts discrete bilaplaciaan, grof raster — dezelfde oplosser die de implementatiesectie documenteert), splits zijn chrominantie van de rand ($\bar r_c$, harmonische vulling), en meng door de koepelfractie $f$:

$$ u_c \;\leftarrow\; (1 - f)\, u_c + f\, L_b\, \bar r_c, \qquad f = \big(1 - S_{0.4}^{0.85}(R^2)\big)\, e^{-(\delta / 1.5\sigma)^2}, $$

met $\delta$ de diepte van de pixel binnen de geklipte zone (zijn afstand tot de dichtstbijzijnde geldige pixel — de enige betekenis die $\delta$ in dit artikel draagt).

5. Volledig-geklipte kern (stappen 7–8), op pixels waar geen kanaal overleefde. Magnitude: de biharmonische koepel $\Delta^2 L = 0$ verankerd op de (reeds gereconstrueerde) annulus. Chrominantie: eerst de screened-Poisson rand-vulling per kanaal, $(\Delta - \lambda)\, r_c = -\lambda\, \bar c_c$ met $\bar c_c$ de gemiddelde geldige chromaticiteit van de opgevulde regio en $\lambda$ de vlakke-kleur- reactie (directe sparse oplossing, gedeelde factorisatie); dan de structuur-gestuurde passage. Zijn primaire vorm is de divergentie-vorm exacte oplossing van stap 8 (rand-gewogen 8-buurs graaf-Laplaciaan, directe sparse factorisatie); kernen boven $2^{14}$ onbekenden nemen de expliciete trace-vorm piramide in plaats daarvan — stappen onder het obstakel, 240 keer per niveau geïtereerd:

$$ r_c \;\leftarrow\; \max\!\Big( r_c + 0.18 \,\big( D_{xx} \partial_{xx} r_c + 2 D_{xy} \partial_{xy} r_c + D_{yy} \partial_{yy} r_c \big),\; \frac{c_{0,c}}{L_\text{sum}} \Big), $$

gevolgd door een 60-vegen geprojecteerde polijsting op volledige resolutie (activiteit-gepoort: het draait alleen waar een pixel daadwerkelijk op zijn vloer zit). Herassemblage, per pixel van de volledig-clip-kern — de enige pixels die deze passage schrijft; partieel-clip-pixels werden geregeld door regels 1–4 en fungeren als zijn ankers:

$$ u_c \;\leftarrow\; L_\text{sum}\, \frac{r_c}{\sum_j r_j}, $$

zacht-gevloerd zoals in regel 3. (De code draagt ook een magnitude-overdracht-tak voor partieel-geldige pixels, een ladder-tijdperk-overblijfsel dat de ankerconstructie onbereikbaar maakt — hier gedocumenteerd zodat niemand het overschrijft.)

6. Korrel en composiet. Voeg de Poissoniaanse korrel van de volgende subsectie toe waar gevraagd, schrijf dan terug door de harde schakelaar: reconstrueerbare fotosites nemen $\max(\text{raw}, u_c)$, geldige fotosites houden hun meting onaangeroerd.

Al het andere in de pipeline — de knieschatting, de segmentatie, de opvulling — bereidt invoer voor deze zes updates voor; niets anders schrijft een pixel.

Discussie

De operatoren die het algoritme samenstelt zijn niet willekeurig: elk is de schatter die zijn energieterm voorschrijft, en elk draagt meetbare eigenschappen waar het ontwerp op leunt. Deze subsectie leidt ze af, en sluit af met de parameterstudie die de hele methode dimensioneert — hoe ver een reconstructie zou moeten reiken.

De geleide vertrouwen

De kleurlijn-lening is slechts zo goed als de aanname erachter: dat het geklipte kanaal en zijn geleide, lokaal, affiene verwant zijn. Op een natuurlijk oppervlak zijn ze dat; op pathologische inhoud (onafhankelijke per-kanaal gradiënten, of een grens tussen twee verschillend-gekleurde materialen) zijn ze dat niet, en de lening forceren zou structuur inschilderen die niet thuishoort. De fit zelf rapporteert hoe ver het te vertrouwen: $R^2$ (gedefinieerd met de fit, in de updateregels) is het aandeel van de lokale variantie van het kanaal dat de kleurlijn verklaart — $1$ waar het model standhoudt, $0$ waar de lening betekenisloos is.

Dus de methode schakelt nooit tussen cross-kanaal en enkel-kanaal vullen — het mengt ze naar vertrouwen, terugvallend op het naar binnen uitbreiden van de eigen gradiënt van het geklipte kanaal (per-kanaal biharmonische inpainting, verankerd op de echte geldige rand van dat kanaal) naarmate de kleurlijn verzwakt. Het menggewicht is het gekwadrateerde vertrouwen $W_e = (R^2)^2$, en de exponent is een gemeten keuze, geen smaak. Over de geklipte pixels scheidt $R^2$ de twee regimes alleen met een zachte marge: het gemiddelde is $\approx 0.9$ op natuur-achtige inhoud, $\approx 0.65$ op gedecorreleerde inhoud, en de twee distributies overlappen met $\sim15\%$ — en geen goedkopere statistiek doet het beter (cross-schaal helling-stabiliteit en inter-geleide overeenstemming werden beide gemeten om slechter te scheiden, dus $R^2$ is het eerlijke plafond). Lineair gebruikt zou het gedecorreleerde geval nog $\sim65\%$ van een cross-kanaal schatting nemen die zowel fout is als — omdat de harde geleide-selectie daar omslaat — discontinu. Kwadrateren trekt de regimes uiteen: $0.9^2 \approx 0.81$ beweegt het betrouwbare geval nauwelijks, terwijl $0.65^2 \approx 0.42$ het onbetrouwbare halveert, zodat gedecorreleerde pixels leunen op de gladde eigen-gradiënt-vulling. Omdat de marge zacht is, overleeft echter een zwakke naad nog op de meest vijandige inhoud: kwadrateren kan een discontinuïteit in de grootheid die het weegt niet volledig verbergen, en dat residu is waar de nooit-naden-creëren-ontwerpregel voor bestaat (zie het kerkhof).

Waar geen kanaal overleeft is er geen geleide en geen $R^2$ om te wegen, dus de reconstructie draagt over aan de gezamenlijke kern van de volgende sectie. De menging wordt dus gepoort door geleide-geldigheid en gewogen door gekwadrateerde correlatie, niet door een harde telling van geklipte kanalen: één mechanisme overspant het hele bereik van een één-kanaals clip (grotendeels cross-kanaal) via een twee-kanaals clip (het overlevende kanaal stuurt) tot een volledig-uitgebrande kern (de gezamenlijke koepel). Dit is wat de methode gracieus laat degraderen naarmate de inter-kanaal-correlatie daalt: op de natuur-achtige testbeelden domineert de cross-kanaal-term, op de vijandige willekeurige gradiënten neemt de zelf-uitbreiding over, en de reconstructie fabriceert nooit een kleurlijn die er niet is. Het is de correlatie, niet het aantal overlevenden, dat beslist of een geleide kan worden vertrouwd — een twee-overlevende pixel op gedecorreleerde inhoud is niet beter gestuurd dan een één-overlevende pixel op een schone kleurlijn.

Gaten vullen zonder overlevende

Waar elk kanaal klipt, kan geen kleurlijn worden gefit: het fijne detail van het hoge licht en zijn exacte piek zijn oprecht verloren. Maar twee dingen kunnen nog worden gered uit de omgeving, mits ze gezamenlijk worden gereconstrueerd: de laagfrequente magnitude-kromming van het gat en zijn chrominantie.

De naïeve zet is om elk kanaal onafhankelijk te koepelen: draai de per-kanaal biharmonische zelf-inpaint van de vertrouwensterugval, nu ongewogen, op alle drie kanalen. Het faalt op een leerzame manier. Omdat de kanalen op verschillende radii klippen (elk heeft zijn eigen witniveau, en een bijna-neutraal hoog licht kruist ze om de beurt), wordt elk kanaal gekoepeld vanaf een rand op een andere afstand van het centrum, en de drie koepels bereiken verschillende hoogtes. Het laatste kanaal dat klipt verzadigt vlak precies bij zijn rand, dus het draagt bijna geen naar binnen gerichte helling en zijn koepel rijst nauwelijks, terwijl het eerste kanaal dat klipt over een brede radius wordt gekoepeld en steil rijst. De kern drijft daarom af van tint: een neutrale zon uitgebrand over een oranje lucht reconstrueert als een gele schijf, omdat blauw (het laatst hier klippend) instort terwijl rood over-herstelt. Drie correct-uitziende 1-D-koepels, één verkeerde kleur.

De fix is om te scheiden wat gedeeld is van wat niet is. Magnitude is gemeenschappelijk voor alle drie kanalen (ze zijn allemaal helder omdat hetzelfde licht ze overstroomde), dus het wordt één keer gereconstrueerd, als een enkele koepel. Chrominantie varieert glad en wordt naar binnen gedragen vanaf de rand. Concreet, splits de gesommeerde luminantie $L_\text{sum} = R+G+B$ van de chrominantie $\text{RGB}/L_\text{sum}$, reconstrueer elk door zijn juiste operator, en recombineer $\text{core}_c = L_{\text{dome}}\cdot (\text{RGB}/L)_c$.

De magnitudekoepel

De luminantie $L_\text{sum}$ wordt over de volledig-geklipte kern gekoepeld door de biharmonische inpainting geïntroduceerd in de eerste principes: de oplossing $\Delta^2 L = 0$, verankerd aan de echte geldige rand van de kern (de reeds-gereconstrueerde partieel-clip-annulus die het omringt). De operator zelf is een heropleving: een ontwerp uit 2021 had gradiënt-uitbreiding geprobeerd als een omgekeerd-teken Laplaciaan (de diffuse or sharpen- truc), maar een omgekeerde diffusie itereren is instabiel en het werd geschrapt als artefact-gevoelig; de herbouw brengt het idee terug in zijn stabiele, directe vorm, één keer opgelost op de gesommeerde luminantie in plaats van per kanaal geïtereerd. De magnitude vullen door gewone diffusie zou het afvlakken tot een matte schijf; de biharmonische oplossing zet in plaats daarvan de helling van de rand voort, zodat een grote volledig-geklipte kern in een koepel rijst in plaats van tot een plateau in te storten. Omdat alle drie kanalen op deze ene koepel rijden, kan geen enkele instorten ten opzichte van de andere — het falen hierboven is structureel onmogelijk. Het kan de exacte piek niet bereiken (het steilste deel van de gradiënt was weggeklipt, en de echte top is simpelweg niet waargenomen), maar het herstelt ruwweg $75$–$80\%$ van de geklipte stijging, als een gladde koepel van de juiste breedte. Een enkel scalair veld oplossen in plaats van drie maakt ook het biharmonische systeem een derde van de grootte.

Een verzadigingsvloer

De geleide fit en de biharmonische koepel zijn beide extrapolaties, en een extrapolatie kan te laag uitkomen: een kanaal herbouwd uit een enkele lage overlevende, of een koepel die een rand voortzet waarvan de naar binnen gerichte helling werd afgevlakt door clipping, kan onder het niveau dat het kanaal daadwerkelijk bereikte uitkomen. Dat is onfysisch: zoals het probleem vaststelde, vult de fotosite-put tot een vaste capaciteit, dus een geklipt kanaal is bekend minstens op zijn clipniveau te zitten. Twee vloeren dwingen precies dat af, en beide zijn monotoon: ze verhogen alleen ooit een waarde, zodat ze niet kunnen overschieten en een tint die al correct was niet kunnen verschuiven (een attributienoot: de vloeren, net als de 9-punts Laplaciaan, zaten al in de C-implementatie uit 2021 — de bijdrage van de studie is alleen om hun waarde te hebben gemeten, en de vloeren alleen zijn een strikte, uniforme verbetering op elke scène):

  • elk geklipt kanaal krijgt een vloer op zijn eigen verzadigde uitlezing;
  • de luminantiekoepel van de volledig-geklipte kern krijgt een vloer op de som van de clipniveaus: elk kanaal daar is gemaximeerd, dus de kern is de helderste regio, nooit een dip onder zijn rand.

Goedkoop en fysiek onweerlegbaar, verwijderen de vloeren de resterende magenta-en-donkere zweem die de koepel en diffusie alleen kunnen achterlaten in een grote volledig-geklipte kern (een uitgebrande zonneschijf), en ze verklaren de verbetering op het volledig-geklipte gecorreleerde geval dat hieronder wordt gerapporteerd.

Chrominantie, door diffusie

De chrominantie $r = \text{RGB}/L_\text{sum}$ wordt naar binnen gediffundeerd vanaf de kernrand: harmonische inpainting van de chrominantie, $\Delta r = 0$ met $r$ vast op de rand. Cruciaal is de rand hier de gereconstrueerde annulus onmiddellijk rond de kern, niet de verre lucht: aangezien de overlevende kanalen werden gestuurd terug naar neutraal bij het naderen van het hoge licht, is de annulus al bijna-neutraal, dus de gediffundeerde kern komt ook bijna-neutraal uit — de uitgebrande zon wordt wit overgeschilderd, niet het oranje van de lucht. (De eerdere à-trous- implementatie trok in plaats daarvan zijn chrominantie van te ver uit en vergeelde de kern; zowel de referentie als de huidige gesegmenteerde reconstructie diffunderen vanaf de nabije annulus, zoals hier.) De gerecombineerde $\text{core}_c = L_{\text{dome}}\cdot r_c$ is dan een correct-gekleurde koepel.

De vorige à-trous-implementatie realiseerde deze $\Delta r = 0$-oplossing niet als één lineair systeem maar als een geïtereerde relaxatie: door de verhoudingen te ontleden in waveletbanden, neemt elke detailband één expliciete Euler-stap van

$$ \begin{align} r &\leftarrow r + \kappa \, \big( \Delta r - \lambda \, r \big)\\ \kappa &= \frac{1}{\texttt{B_SPLINE_TO_LAPLACIAN}} = \frac{\sigma_B^2}{2\sqrt{\pi}} \approx 0.31 \end{align} $$

met $\Delta$ de isotrope 9-punts Laplaciaan $\mathbf{K}_{\text{iso}}$. De constante $\kappa$ herschaalt de à-trous-detailband (een verschil van B-splines) tot een correct-geschaalde continue Laplaciaan en stelt de effectieve diffusie-tijdstap in.7 De herbouwde reconstructie lost $\Delta r = 0$ in plaats daarvan direct op: een sparse oplossing in het prototype, conjugate gradient (een iteratieve oplosser die zijn antwoord stap voor stap verfijnt) in de C. Maar de relaxatieblik legt nog steeds twee dingen bloot:

  • Met $\lambda = 0$ is het de pure warmtevergelijking $\partial r / \partial t = \kappa \Delta r$ op de kleur- verhoudingen: harmonische inpainting die de chrominantie van het gat glad vult vanaf zijn rand, de Dirichlet- minimalisator die hierboven is afgeleid (equivalent aan de directe $\Delta r = 0$-oplossing, geïtereerd).
  • De term $-\lambda\, r$, geregeld door de solid_color-parameter, is een eerste-orde-reactie die het verhoudingsdetail naar nul dempt. Zijn Euler–Lagrange-vergelijking is de screened-Poisson- / gemodificeerde-Helmholtz-vergelijking $\Delta r - \lambda\, r = 0$: een diffusie tegengehouden door een herstellende trek naar nul; grotere $\lambda$ trekt de binnenste chrominantie naar een vlakkere, meer uniforme “effen kleur”-vulling.

De diffusie is puur isotroop: textuur zou structuur moeten volgen, maar chrominantie zou moeten vullen zonder acht te slaan op richting, dus een rotatie-symmetrische gladstrijker is wat gewenst is. De hele gezamenlijke vulling is gepoort tot de volledig-geklipte pixels, zodat het nooit een kanaal verstoort dat de geleide stap al herstelde.

De verzadigingsvloeren, als obstakels. Eén meting overleeft zelfs waar alle drie kanalen uitgebrand zijn: de verzadigde uitlezing van elke fotosite is een ondergrens op zijn echte waarde, dus in verhoudingsruimte kan de chrominantie van een geklipt kanaal nooit onder $c_{0,c} / L_\text{sum}$ dalen. Toegepast alleen helemaal aan het eind — een harde $\max$ bij de recombinatie — drukte die grens een exact-vlakke richel op het clipniveau, eindigend in een gradiëntbreuk, overal waar de gladde vulling een kanaal nabij zijn eigen rand te laag voorspelde (gemeten op het blauwe kanaal van een echte zonsondergang: tien pixels vlak op de clipwaarde, dan een hellingsdiscontinuïteit). De uitgeleverde reconstructie behandelt de vloeren in plaats daarvan als een beperking van de diffusie zelf — een obstakelprobleem:

$$ \min_{r_c} \int_{\Omega} \nabla r_c^{\top} D\, \nabla r_c \;\mathrm{d}\Omega \qquad \text{subject to} \qquad r_c \;\geq\; \frac{c_{0,c}}{L_\text{sum}} \quad \text{on the clipped pixels,} $$

opgelost door geprojecteerde relaxatie: na elke gladstrijkstap, $r_c \leftarrow \max(r_c, c_{0,c}/L_\text{sum})$. Elk buurgewicht van de discretisatie is niet-negatief, dus het geprojecteerde schema blijft monotoon en convergeert naar de variationele-ongelijkheidsoplossing: de invloed van de beperking verspreidt zich glad door het veld — de vulling lift rond de actieve verzameling in plaats van puntsgewijs geklemd te worden — en de recombinatie past dan alleen een zachte afronding toe (dezelfde twee-procent smooth-max als de coëfficiëntveld-vloer) op een veld dat al toelaatbaar is. Het obstakel rijdt de hele grof-naar-fijne ladder (per-niveau cel-obstakels) plus een korte geprojecteerde polijsting op volledige resolutie, die ook het directe-oplossingspad dekt — een exacte sparse factorisatie kan niet midden in de oplossing projecteren. Een sterkere variant, die het obstakel verhoogt met de gemeten naar buiten gerichte helling van de rand naar binnen geëxtrapoleerd, werd geïmplementeerd, gemeten, en verworpen: het fabriceert structuur waar de extrapolatie bindt (de fout van de magenta zon steeg met 14 %) en verandert niets waar het gewone obstakel al standhoudt.

image

Het wanhopige volledig-geklipte geval: een heldere zon uitgebrand voorbij het (per-kanaal) witpunt van elk kanaal, over een oranje lucht. De sensor registreert een vlakke schijf die witbalans-RGB-coëfficiënten magenta zullen maken; de vorige methode geeft een dimme, over-grote gele schijf met een harde rand terug (zijn per-kanaal-vullingen drijven af van tint en koepelen nooit); de gecorrigeerde methode herbouwt een neutrale koepel van de juiste grootte uit één gedeelde luminantiekoepel plus rand-gediffundeerde chrominantie.

Over de geklipte kern, RMSE $0.87 \to 0.27$ en SSIM $0.61 \to 0.95$; de chrominantie van de vulling beweegt van magenta $(0.37, 0.27, 0.36)$ naar een bijna-neutrale $(0.39, 0.33, 0.28)$, in wezen de ground truth’s $(0.36, 0.33, 0.31)$ (de vorige methode landt op een geel $(0.51, 0.34, 0.15)$).

Korrel toevoegen

Als laatste afwerking, en alleen waar het masker open staat, krijgt de reconstructie Poissoniaanse ruis met een amplitude die evenredig is aan de lokale waarde ($\sigma_c = \texttt{noise_level}\cdot u_c$), gevouwen om strikt oplichtend te zijn en samengesteld met $\alpha$. Foton-schotruis is signaalafhankelijk, dus een perfect gladde plek die in een frame met hoge ISO wordt gedropt ziet er plastic uit; het matchen van de korrel laat de reparatie verdwijnen.2

De reconstructiestraal

Hoe breed moet het grofste geleide venster, de reconstructiestraal $\rho$, zijn? Het is de ene knop die reikwijdte tegen lokaliteit uitruilt, en het blijkt een helder antwoord te hebben.

De straal van een gat is zijn diepte, niet zijn grootte. Laat voor een gat $\Omega$ $d(x)$ de afstand zijn van een geklipte pixel $x$ tot de dichtstbijzijnde geldige pixel. De grootheid die telt is het diepste punt,

$$R=\max_{x\in\Omega} d(x)=\max\big(\text{distance transform of }\Omega\big)$$

niet de omgrenzende doos. Een compacte schijf en een lange dunne diagonale streep kunnen dezelfde omgrenzende doos delen terwijl ze een volledig verschillende $R$ hebben: voor de streep is $R$ de halve dikte, want dat is hoe ver de gids moet reiken om geldige data te raken. De straal op basis van de omgrenzende doos bepalen zou massaal over-reiken bij langgerekte of diagonale gaten.

Waarom $\rho \approx R$ optimaal is. Twee fouten concurreren naarmate $\rho$ groeit. Dekking: een venster van schaal $\rho$ legt gewicht $\sim e^{-d(x)^2/2\rho^2}$ op geldige data, wat verwaarloosbaar is tot $\rho \gtrsim d(x)$; daaronder is de fit onbepaald en is de pixel feitelijk niet gereconstrueerd. Lokaliteit: eenmaal gedekt is de gefitte kleurlijn een venstergemiddelde van de ruimtelijk variërende ware lijn, dus extrapoleren vanuit steeds verder gelegen monsters voegt een bias toe die met $\rho$ groeit. De fout per pixel is daarom

$$E(x;\rho)\approx \underbrace{C_1\,e^{-d(x)^2/2\rho^2}}_{\text{coverage}\ \downarrow}+\underbrace{C_2\,\rho}_{\text{locality}\ \uparrow}$$

waarvan het minimum ligt bij $\rho^*(x)\approx d(x)$: het kleinste venster dat geldige data bereikt. Eén regiostraal moet zijn diepste pixel dekken, dus $\rho=R$; de grof-naar-fijn-ladder is dan precies dit per-pixel-optimum continu gemaakt: de grofste schaal $R$ dient het centrum, elke fijnere schaal dient de schil op zijn eigen diepte.

Over-reiken is gratis in kwaliteit, maar niet in prijs. In het prototype laat het doorlopen van $\rho$ van $0.4R$ tot $3R$ zowel de gemiddelde als de diepe-kern-RMSE vlak, op gecorreleerde en op gedecorreleerde scènes gelijk. De reden is structureel: de grof-naar-fijn-ladder overschrijft elke grove (over-gladgestreken) waarde met de fijnste schaal die de pixel nog bereikt, dus de straal bepaalt alleen dekking, nooit de uiteindelijke waarde van een pixel. Rekenkracht is echter niet vlak (die stijgt met zowel het opgevulde oppervlak als het aantal schalen), dus de verhouding kwaliteit-per-kosten daalt monotoon met $\rho$:

$\rho/R$gem. RMSEdiepe-kern-RMSErelatieve kostenkwaliteit / prijs
0.40.0830.1410.431.00
1.00.0830.1411.000.43
2.00.0830.1412.390.18
3.00.0830.1414.430.10

De zoete plek is per pixel, en de implementatie levert die. Omdat de kwaliteit vlak is boven de diepte en de kosten niet, is de beste kwaliteit/prijs het kleinste venster dat elke pixel nog dekt, d.w.z. $\rho(x)=d(x)$ per pixel, nooit een globaal maximum. Ladder C realiseerde dit direct: een samengevoegde tegel nam de grootste straal $R$ van de groep als zijn grofste schaal (zodat de diepste pixel was gedekt), en elke pixel werd vervolgens beperkt tot schalen niet grover dan $\sim2\,d(x)$, zodat een ondiepe pixel (een klein gat, of de rand van een groot gat) nooit betaalde voor de grove schalen die alleen het centrum nodig heeft. De distance transform wordt eenmaal berekend voor het hele frame en drijft de straal per regio aan. De enige harde regel is de asymmetrie: ga nooit onder de diepte (dekking stort in), en ga nooit ver erboven (pure verspilde rekenkracht). De geleverde methode houdt de conclusie in een eenvoudiger vorm: één fitvenster op maat van de straal van de regio, $\sigma = \operatorname{clip}(r/6,\, 8,\, 64)$ px, zonder resterende per-pixel-beperking.

Implementatie & optimalisaties

Er bestaan twee implementaties: de NumPy-referentie die naast dit artikel is gepubliceerd, en de C-/ OpenCL-productiecode die met Ansel wordt geleverd. Ze worden als onderdeel van het validatieprotocol tegen elkaar gediffed, en ze wijken alleen af waar snelheid het eist.

De C-productiecode

Het prototype dat dit artikel begeleidt is de referentie: het geeft de voorkeur aan helderheid en nauwkeurigheid boven snelheid (sparse-direct oplossingen over het volledige beeld, een vaste Gaussische ladder, een aparte variantie-pass, één kleurlijn-fit per (kanaal, gids)-paar). De code die daadwerkelijk met Ansel wordt geleverd moet een geklipte zon binnen een raw van 20+ Mpx reconstrueren terwijl de gebruiker wacht, dus wijkt zij op een handvol opzettelijke manieren af van de referentie. Elke afweging hieronder is afgestemd op gecorreleerde inhoud, het overweldigend meest voorkomende geval in natuurlijke beelden, en accepteert een klein verlies op synthetische gedecorreleerde inhoud, die in de praktijk zeldzaam is. Elke afwijking is omkeerbaar in de broncode. Een noot over de geschiedenis: dit optimalisatiewerk werd gedaan op de ladder-tijdperk-C, wiens reconstructiekern de geleverde methode vervangt. De segmentatie, opvulling, sparse solver en gedeelde-statistiek-machinerie gaan letterlijk over; de ladder-specifieke onderdelen (de per-gat-schaalladder, de per-pixel-dieptepoort, de paar-beperkte gidskeuze) overleven alleen als principes, binnen het enkele fitvenster en de coëfficiëntvulling van de geleverde methode.

  • Segmenteer en reconstrueer alleen de geklipte omgevingen, op volledige resolutie. De referentie draait op het hele frame. De geleverde code flood-fillt het geklipte masker in samenhangende regio’s, vult elke op met zijn eigen reconstructiestraal ($1.25\times$ de straal, geklemd tussen $8$ en $256$ px — hoe groter het gat, hoe verder het moet reiken naar geldige data), voegt regio’s samen wiens opgevulde dozen overlappen zodat hun vullingen elkaar nooit als een naad ontmoeten, en draait de volledige pipeline alleen binnen elke opgevulde doos. Kosten: geen — de onaangeroerde pixels waren al correct. Winst: het werk schaalt met het geklipte oppervlak, niet met de sensor.

  • Een op zichzelf staande sparse Cholesky dichtte de solverkloof. De referentie vult de magnitudekoepel met een sparse-direct oplossing (scipy.spsolve); een iteratieve solver (geconjugeerde gradiënt op $\Delta^2$) loopt vast in enkele precisie op raw-schaal (zijn conditiegetal, de factor waarmee het systeem afrondingsfouten versterkt, groeit als de vierde macht van de regiogrootte), en een dichte factorisatie is $O(N^3)$, dus de C leverde eerst een dichte Cholesky (de standaard exacte factorisatie van een symmetrisch systeem in driehoekige helften, eenmaal berekend en hergebruikt) op een raster vergroofd tot ten hoogste 2000 onbekenden. Omdat de koepel laagfrequent is, was de grove oplossing exact waar het ertoe deed — behalve op enorme volledig uitgebrande kernen, waar de vergroving zelf de nauwkeurigheidsbottleneck werd (de magenta-zon-testcase verbeterde 21% in RMSE op de dag dat de begrenzing werd opgeheven). De C draagt nu zijn eigen sparse symmetrisch-positief-definiete (SPD) Cholesky, een up-looking $LL^T$- factorisatie in dubbele precisie, geordend door geometrische nested dissection: de onbekenden zijn 2D- rasterpunten, dus recursieve coördinatenbisectie levert de fill-reducerende kwaliteit die normaal een approximate-minimum-degree (AMD)-implementatie vereist, in een paar dozijn regels en zonder externe afhankelijkheid. Het koepel- raster is vier keer fijner (8.192 onbekenden, wat meetbaar de kwaliteitswinst verzadigt), en de chrominantiediffusie van de volledig-geklipte kern factoriseert eenmaal voor zijn drie kanaal-rechterleden wanneer de kern klein is; de parallelle geconjugeerde gradiënt verslaat meetbaar de seriële factorisatie op de grote, dus die behoudt ze. Kosten: netto geen (de volledig-geklipte oplossingen werden sneller). Winst: de laatste systematische C-vs.-prototype-divergentie weg, en de nauwkeurigheid van de enorme kern ermee.

  • Een per-gat Gaussische ladder op maat van de reconstructiestraal. De referentie gebruikt een ladder met vaste straal ($40, 24, \dots, 2$ px). De geoptimaliseerde ladder-C stemde de grofste schaal van elke regio af op de reconstructiestraal van die regio en halveerde met $2\times$ tot $\sim2$ px. Dit verdient een eigen behandeling: zie De reconstructiestraal hieronder.

  • Gedeelde vensterstatistieken: een gratis versnelling. De kleurlijn-fit heeft, per kanaalpaar, de venstergemiddelden, varianties en covariantie nodig. Ze per (kanaal, gids) verzamelen kost twaalf blurs per schaal; ze per kanaalpaar verzamelen levert beide kanalen hun fits op uit dezelfde twee blurs: zes blurs, en wiskundig identiek. Dit alleen al halveerde ruwweg de looptijd.

  • Paar-beperkte variantie voor gidsselectie: een kleine, ingeperkte kost. De referentie beslist welke van twee gidsen te vertrouwen op basis van elke gids’ enkelkanaals venstervariantie, een aparte drie-blur-pass per schaal. De geoptimaliseerde ladder-C hergebruikte de paar-beperkte variantie die zij al voor de fit berekende en liet die pass volledig vervallen (negen blurs per schaal terug naar zes). Dit veranderde alleen welke gids wint, en alleen waar de twee het oneens zijn, d.w.z. gedecorreleerde inhoud. Kosten: op een volledig-gedecorreleerde synthetische scène stijgt de enkel-klip-RMSE van $0.043$ naar $0.047$ en daalt SSIM van $0.964$ naar $0.960$; op gecorreleerde scènes, en op twee- of driekanaals klipping, valt het binnen de ruis. Winst: een derde van de resterende blurs verwijderd.

  • De per-kanaal zelf-koepel en naadregularisator zijn uitgeschakeld in de geleverde code. Beide effenen elk RGB-kanaal onafhankelijk. Op een echt verzadigd amber/oranje hoog licht (waar de kleurlijn- $R^2$ inzakt door klip-niet-lineariteit en verkeerd wordt gelezen als „gedecorreleerd") drijft dat groen weg van rood en blauw en maakt het de reconstructie magenta. De referentie houdt ze: ze de-artefacten oprecht gedecorreleerde inhoud, die de synthetische scènes zwaar belasten en echte foto’s zelden doen (ze uitschakelen kost de referentie $\sim0.01$–$0.02$ RMSE op de random-scène, in wezen niets op gecorreleerde inhoud). De schone oplossing is een tint-gekoppelde versie (die luminantie en een gedeelde chrominantie effent in plaats van drie onafhankelijke kanalen), en die is sindsdien gebouwd: in de uiteindelijke coëfficiëntveld-pipeline keert de zelf-koepel terug als de diepte-gepoorte terugval, precies op deze manier tint-gekoppeld (één gedeelde biharmonische luminantiekoepel maal een harmonisch gevulde chrominantie), zodat de terugval de tint per constructie niet kan doen wegdrijven. De naadregularisator is definitief buiten gebruik gesteld — die pipeline heeft geen estimator-overdrachten meer om glad te strijken.

Twee componenten van de C-implementatie uit 2021 die de prototypevertaling stilzwijgend had laten vallen werden teruggevoerd in de referentie, als echte methode-vereisten in plaats van snelheids- afwegingen, dus ze zijn geen verschillen meer: de rotatie-invariante 9-punts Laplaciaan (de operator die dit artikel afleidt; de referentie gebruikte de gewone 5-punts kruis daarvoor567) en de verzadigingsvloeren (hieronder). Beide verbeteren het moeilijkste, meest relevante geval (de volledig-geklipte kern van een gecorreleerde scène), en verlagen zijn RMSE van $0.065$ naar $0.062$ en verhogen SSIM van $0.959$ naar $0.964$, en zijn elders neutraal.

Alles bij elkaar genomen daalt op een geklipte zon het aantal geleide-filter-blurs van vijftien naar zes per schaal en valt de preview-reconstructie van tientallen seconden terug naar enkele. De verschillen die overblijven zijn snelheid en architectuur (segmentatie, dichte solvers, de per-gat-straal, gedeelde statistieken), plus de paar-beperkte gidsvariantie en de uitgeschakelde per-kanaal-verfijning hierboven; de kern- reconstructiewiskunde wordt gedeeld met de referentie.

Nog één gemeten afweging werd vroeg gesloten: de reconstructie is merkbaar beter wanneer gedraaid op volledige resolutie. De module uit 2021 loste op op een kwart-resolutie-kopie voor snelheid, maar die downsampling vervaagt de reconstructie en is, teruggemengd tegen het scherpe origineel, de dominante bron van randfout: op volledige resolutie draaien verlaagde de grens-RMSE met ongeveer 30%, dus de herbouw werkt op volledige resolutie. Downsampling is een snelheid/kwaliteit-afweging, geen gratis lunch.

De Python-referentie

De NumPy-spiegel (validate.py, fix_prototype.py) implementeert elke fase van het geleverde algoritme in dezelfde volgorde, en zijn uitvoer tegen de C-exports diffen is onderdeel van het validatieprotocol. Enkele componenten zijn opzettelijk beter in Python dan in C, of de C ruilt opzettelijk exactheid in voor snelheid:

  • Exacte sparse-direct oplossingen. De biharmonische koepels van het prototype en zijn divergentievorm- chrominantie-oplossing zijn scipy.sparse-factorisaties, exact tot machineprecisie (zijn screened-Poisson gezamenlijke-kern-vulling is echter een vaste 400-sweep Jacobi-relaxatie — op die ene fase is de directe factorisatie van de C de meer exacte van de twee). De C draagt nu zijn eigen sparse Cholesky (zie Implementatie & optimalisaties hierboven) en matcht de koepel- en kleine-kern-chrominantie- oplossingen van het prototype; wat nog verschilt is opzettelijk: de chrominantiediffusie van grote volledig-geklipte kernen draait de parallelle geconjugeerde gradiënt (daar gemeten sneller dan een seriële factorisatie, zonder meetbaar kwaliteitsverschil), de coëfficiëntvulling blijft de grof-naar-fijn Jacobi die hierboven is beschreven — met de adaptieve piramide van de C (basispitch $\sigma/4$ begrensd op 8 px, gehalveerd tot een grofste van $\le 8$ cellen, 100 sweeps per niveau) tegen de vaste zeven volledig-resolutie-niveaus van het prototype — en de vulling van het prototype is isotroop — de variantie-adaptieve sturing van het coëfficiënttransport van de C (stap 3) heeft nog geen Python-spiegel, dus de C-vs.-prototype-overeenkomst wordt gecontroleerd met de bijdrage van de sturing in gedachten. Voordeel van de exacte oplossingen van het prototype: ze zijn de scheidsrechter wanneer C-uitvoer er verkeerd uitziet.
  • FFT Gaussische vensters vs. recursieve IIR. Het prototype berekent venstermomenten met fast-Fourier-transform (FFT)-convoluties: exact, deterministisch. De C gebruikt de recursieve (infinite-impulse-response, IIR) Gaussiaan wiens kosten onafhankelijk zijn van $\sigma$ — maar wiens parallelle implementatie niet run-tot-run deterministisch is: blok-grens-afronding trilt op het laatste float-cijfer, wat op zichzelf ongevaarlijk is maar een gedenkwaardige heisenbug zaaide (hieronder).
  • Knie-schattingsinvoer. Het prototype schat de rolloff uit de volledig-resolutie ware RGB-scène; de C uit de quad-binned CFA bij $\le 1.5$ Mpx. Gemeten kosten: geen (de blinde C-schatting matcht de analytische knie nog steeds tot $10^{-3}$), terwijl de quad-binning is wat CFA-zijdige schatting überhaupt mogelijk maakt.
  • Volledig-frame vs. per-regio. De spiegel verwerkt hele frames; de C verzamelt elke geklipte regio in een opgevulde buffer en reconstrueert die onafhankelijk, wat het geheugen begrenst en regio’s laat parallelliseren, ten koste van per-regio-normalisatie.
  • Geleverde verfijningen die de spiegel nog niet heeft ingehaald. Drie late C-rondes hebben nog geen Python-tegenhanger: de obstakelmachinerie (per-niveau geprojecteerde relaxatie, de volledig-resolutie-polijsting, en de zachte herassemblage-vloer — de spiegel past nog steeds de buiten gebruik gestelde harde $\max(u, c_0)$ bij herassemblage toe), de band-override van de detectiedrempel voor knie-ingeschakelde kanalen ($5\times$ waard op de rolloff-scène, dus Py-vs.-C is daar structureel onvergelijkbaar), en de strikt per-pixel binaire geldigheid van de C (de spiegel leidt zijn masker af via een 5×5-meerderheidsstemming, een $\sim 2$ px geometrische dilatatie). Dit zijn de bekende inhoudskloven achter de grootste per-scène-afwijkingen.

Nadat elke fase was gespiegeld, is de resterende onenigheid tussen de C-productiecode en de Python-referentie (gemeten als het kwadratische gemiddelde verschil van hun uitvoerbeelden binnen de geklipte zones) $0.009$–$0.089$ over de bench. Zijn ondergrens is het ene invoerverschil dat niet kan worden verwijderd — Python fit op de ware RGB-scène, terwijl de C fit op dezelfde scène gezien door het sensormozaïek en een bilineaire interpolatie (ongeveer $0.02$ verschil binnen de bijna-klip-band) — en zijn bovengrens is de lijst met geleverde verfijningen hierboven, die domineert op de rolloff- en occlusiescènes. Weg van die twee scènes zijn de implementaties het ruim binnen de fout die elk maakt tegen de ground truth eens; op hen is de extra machinerie van de C precies wat de afwijking meet.

Gebruikersparameters

Er is opzettelijk bijna niets in te stellen: het algoritme is zelfconfigurerend. Elke grootheid waarvan de reconstructie afhangt is ofwel eenmaal afgeleid en bevroren, of gemeten uit de afbeelding zelf tijdens de runtime — de fitschaal uit elke regio’s eigen reconstructiestraal, de sensorrolloff uit de eigen kleurlijnen van de afbeelding, ankervertrouwen uit de gemeten fitkwaliteit, de transportsturing uit de gemeten gidsstructuur, de randdrempel $k$ eenmaal gekalibreerd op de ground-truth-bench. De besturingen iterations en diameter van de 2021-modus zijn verdwenen uit de interface van deze modus: er is geen door de gebruiker afstembare convergentie meer om verkeerd te configureren, en geen manier om per ongeluk kwaliteit weg te ruilen.

Wat overblijft is één veiligheid en twee smaken. De clipping threshold schaalt de verzadigings- drempels die de zone definiëren (zie de visualisatieschakelaar hieronder — hij hoeft bijna nooit verplaatst te worden); het noise level stelt de korrel in die weer over de reconstructie wordt geïnjecteerd zodat die matcht met de omringende fotontextuur; en inpaint a flat color stelt de trek in richting een uniforme kleur in de volledig-geklipte kernen waar niets overleefde — een stilistische keuze over zones die in het geheel geen informatie dragen.

Ontdekte problemen

De structurele beperking van de methode is geërfd en geaccepteerd: een uitgebrande blauwe lucht gezien door groene bladeren wordt groen hersteld, want waar geen kanaal overleeft kan de reconstructie alleen de naburige kleur propageren — hij is ontworpen voor de onvermijdelijke klips rond licht- bronnen en speculaire reflecties, wiens gloeiende halo’s de informatie dragen waarop hij zich voedt. Andere situaties vragen nog steeds om het beschermen van de hooglichten bij opname en het verhogen van de belichting in de nabewerking, wat de signaal-ruisverhouding van moderne sensoren comfortabel toestaat.

Twee gemeten kanttekeningen completeren het eerlijke beeld. Op de occlusie-bench-scène bereikt de afgestemde Darktable-segmentatie een hogere structurele-gelijkenis-score dan harmonische transpositie (0.98 tegen 0.96) ondanks waarden 15% verder van de waarheid: magnitude en structuur zijn verschillende fouten, en een gladde verkeerde vulling kan er schoner uitzien dan een waarheidsgetrouwe. En de apparaatpariteit van de float-pipeline is op tolerantieniveau, niet op bitniveau: na het centreren van de momentaccumulatie (stap 3) is het resterende CPU-versus-GPU-verschil op de diepste bench-scène onder $10^{-3}$ RMSE, begrensd door orde-niet-deterministische parallelle reducties.

Resultaten

De bench

Elk getal hieronder komt uit één protocol. Zes synthetische scènes met bekende ground truth — RGB- speculaire ballen, een magenta zon, gecorreleerde gradiënten (een luminantieveld maal een gladde chrominantie, hoe natuurlijke beelden zich gedragen), onafhankelijke random gradiënten (helemaal geen kleurlijn, het vijandige geval), een PK1-achtige lucht met een analytische sensorrolloff, en een zon gekruist door een occluder — worden geschreven als Bayer-DNG-bestanden, ontwikkeld door de daadwerkelijke productie-pipelines, en de exports worden tegen de ground truth gescoord in witbalans-sensor-RGB (een volledige 3×3- kalibratiematrix gefit op strikt-lineaire geldige pixels brengt elke export terug naar sensor- ruimte, zodat verschillend-gematrixte pipelines in dezelfde eenheden landen). Elk Ansel-resultaat in deze sectie — beide modi, elke tabel, elke figuur — is geproduceerd door de geleverde C- implementatie via ansel-cli, niet door het Python-onderzoeksprototype: de twee implementaties wijken opzettelijk af (verschillende solvers, resoluties en fase-afwegingen, zie de C-productiecode), met 0.009 tot 0.089 RMSE binnen de geklipte zones over deze bench, dus hun getallen mogen nooit worden gemengd. De hele bench reproduceert vanuit de bijlage.

De metrieken van het geleverde algoritme hieronder worden alleen binnen het geklipte gebied berekend. RMSE is de kwadratische gemiddelde fout tegen de ground truth, in sensoreenheden genormaliseerd zodat het klipniveau 1 is: het meet hoe ver de gereconstrueerde waarden gemiddeld van de ware liggen. SSIM is de structurele-gelijkenis-index, een perceptuele score die lokale gemiddelden, contrasten en correlaties vergelijkt (1 betekent visueel identiek). Randenergie is onze naaddetector: de chrominantie-gradiëntenergie binnen de zone, relatief aan een ring net erbuiten, en zijn doel is de score van de ground truth zelf, niet nul, want echte inhoud heeft textuur en een over-gladde reconstructie is even fout als een naderige:

gevalRMSESSIMrandenergie (GT-doel)
RGB balls0.03510.9950.41 (0.47)
magenta sun0.32760.9520.31 (0.50)
correlated0.03980.9731.15 (1.14)
random0.04530.9650.85 (1.02)
pk1synth0.00531.0000.64 (0.69)
PK1 (natural)0.49
DSC00078 (natural)0.73
IMG_3129 (natural)0.39

De vier methoden

De twee Darktable-modi worden met de andere eenvoudige oplossingen beschreven in de landschapssectie; gelezen door het kader van dit artikel, is inpaint opposed een kleurlijn met de helling vastgepind op één (in kubuswortel- ruimte) en een enkel globaal snijpunt — waar harmonische transpositie zowel helling als snijpunt per lokaal venster fit en die coëfficiënten over de zone diffuseert, vertrouwt opposed één vaste relatie overal, wat de reden is dat het bijna gratis is en waarom het faalt onder gemengde belichting — en segmentation based upgradet dat naar één representatieve chrominantie per segment, nog steeds vlak waar onze gediffuseerde velden glad variëren.

Beide methoden beantwoorden de vraag „welke kleur zou dit gebied moeten hebben"; geen van beide fit een model van hoe het ontbrekende kanaal zich verhoudt tot de overlevende, wat is wat onze methode toestaat om per-pixel-structuur en -magnitude met een gemeten vertrouwen te herstellen. De rijen hieronder zetten getallen op dat verschil, op dezelfde synthetische scènes en ground truths als al het andere in deze sectie.

Kwadratische gemiddelde fout (lager is beter) en structurele gelijkenis (hoger is beter), gemeten binnen de geklipte zone tegen de ground truth, na per-afbeelding belichtingskalibratie; elke methode geëxporteerd als 32-bits lineaire TIFF (upstream Darktable 5.x voor de eerste twee kolommen, Ansel voor de laatste twee), gescoord door dezelfde validate.py als elke andere tabel op deze pagina. Twee voorzorgsmaatregelen maken de kolommen daadwerkelijk vergelijkbaar. Ten eerste worden de pipelines geneutraliseerd naar dezelfde basislijn — demozaïceren plus reconstructie van hooglichten, niets anders: de standaard scènegerefereerde (scene-referred) workflow van beide applicaties voegt stilzwijgend een belichtingslift, een chromatische-adaptatie-kanaalmixer en een sigmoïde tooncurve rond zijn reconstructie in, wat de meting met rendering-verschillen zou corrumperen, dus wordt hij geforceerd naar workflow=none (de export van Ansel is al die basislijn). Ten tweede draait elke concurrent zijn beste parameters per scène, gevonden door een gridsweep over zijn besturingen (clipping threshold voor opposed; candidating, combine, rebuild-modus en sterkte voor segmentation; iteraties en flat-color-inpainting voor de guided laplacians), terwijl harmonische transpositie zijn standaardwaarden overal draait. Reproduceer met dt_compare.py (de vergelijking) en tune_methods.py (de sweep) uit de onderzoeksrepository:

scèneDarktable opposedDarktable segmentationguided laplaciansharmonic transposition
balls (speculaire ballen)0.242 / 0.8140.233 / 0.8310.334 / 0.7440.035 / 0.995
magentasun (magenta zon)0.924 / 0.7070.807 / 0.7670.809 / 0.6780.328 / 0.952
correlated (gecorreleerde gradiënten)0.107 / 0.8720.077 / 0.9070.130 / 0.8500.040 / 0.973
random (onafhankelijke gradiënten)0.089 / 0.9110.080 / 0.9200.138 / 0.8620.045 / 0.965
pk1synth (PK1-achtige lucht (analytische rolloff))0.130 / 0.9850.130 / 0.9850.108 / 0.9930.0053 / 1.000
occluded (geoccludeerde zon)0.099 / 0.9820.086 / 0.9800.171 / 0.9300.069 / 0.987

Het patroon is consistent met de mechanismen. Zelfs met de pipelines gelijkgetrokken en elke concurrent op zijn per-scène beste, leidt harmonische transpositie in RMSE op elke scène — met 20% waar de occlusie de aannames van de segmentatiemodus begunstigt, met een factor 2 tot 7 op de algemene gevallen, met een factor bijna 50 op de rolloff-lucht (waar de band-override hieronder het model laat herbouwen wat de sensor wegcomprimeerde): de Darktable-modi herstellen een plausibele kleur maar niet magnitude (hun vaste eenheidshelling kan een kanaal niet boven tillen wat het opposed-gemiddelde levert), en hun per-segment- of globale chrominantie vervlakt textuur. De segmentatiemodus loopt wel voorbij het gewone opposed zodra zijn rebuild-pass daadwerkelijk is ingeschakeld (de sweep vond rebuild + volledige sterkte optimaal op de helft van de scènes). De visuele tegenhanger van elk getal, één scène per galerij, alle zes weergaven door dezelfde schermtransformatie:

balls — speculaire ballen:

magentasun — magenta zon:

correlated — gecorreleerde gradiënten:

random — onafhankelijke gradiënten:

pk1synth — PK1-achtige lucht (analytische rolloff):

occluded — geoccludeerde zon:

De volledige doorloop van de validatiebench (geklipte invoer, reconstructie, uitvergrote chrominantie-rand- kaart, en ground truth waar die bestaat), plus de per-kanaal koepelprofielen, wordt hieronder getoond. De profielplots worden als volgt gelezen: elk neemt de enkele beeldrij die de diepste geklipte pixel kruist (bijgesneden tot de geklipte spanne van die rij) en plot de kanaalwaarden erlangs, één paneel per kanaal, met de gestippelde grijze lijn op het klipniveau. Ze onthullen precies wat een miniatuur verbergt: de doorsnede-vorm van de gereconstrueerde koepel, zijn hellingen waar hij de geldige rand ontmoet, hoe ver boven het klipniveau het herstel reikt, en elke overshoot of vlakke plek — vergeleken, op de synthetische scènes, met het eigen profiel van de ground truth. Alle profielen, natuurlijke beelden inbegrepen, zijn geplot in witbalans-sensor-RGB, per fotosite (de natuurlijke-beeldprofielen lezen de CFA zelf, met demozaïceren ingesteld op passthrough) — het eigen werkvlak van de module, waar de verzadigingsvloer-invariant (een geklipt kanaal eindigt nooit onder zijn verzadigde waarde) direct zichtbaar is. Geen latere fase heeft deze eigenschap: de negatieve off-diagonalen van de kleurmatrix laten een gereconstrueerd kanaal legitiem onder zijn klip- plateau kruisen (gamut-projectie, geen vloerschending), demozaïceren verzint twee van de drie kanalen bij elke pixel en kan ondershooten bij de steile randen van de reconstructie, en elke resampler voegt zijn eigen Mitchell-undershoot toe. Eén kenmerk van de natuurlijke profielen verdient een waarschuwing: donkere structuren die de uitgebrande zone kruisen (tuigage, takken, masten) zijn gemeten geldige data — de reconstructie schrijft alleen geklipte fotosites, dus het profiel duikt er doorheen in plaats van eroverheen te koepelen. Een rij die twee tegenlicht-touwen kruist toont twee lobben, en dat is de scène, geen falen om te reconstrueren:

image
RGB balls: geklipt, gereconstrueerd, randen ×8, ground truth, randen ×8.
RGB balls: kanaalwaarden langs de rij door de diepste geklipte pixel; gestippeld grijs = klipniveau.
image
Magenta zon (volledig-geklipte kern).
Magenta zon: rijprofiel door de diepste geklipte pixel, per kanaal; de koepeldoorsnede van de volledig-geklipte kern.
image
Gecorreleerde gradiënten.
Gecorreleerde gradiënten: rijprofiel door de diepste geklipte pixel, per kanaal.
image
Random (gedecorreleerde) gradiënten, het erkende slechtste geval.
Random (gedecorreleerde) gradiënten: rijprofiel door de diepste geklipte pixel, per kanaal.
image
pk1synth: de synthetische replica van de PK1-uitgebrande lucht, met een echte sensorrolloff.
pk1synth: rijprofiel door de diepste geklipte pixel, per kanaal; let op het herstel boven het gestippelde klipniveau.
image
PK1: de echte uitgebrande zonsonderganglucht die de herbouw motiveerde.
PK1: rijprofiel door de diepste geklipte pixel, per kanaal (geen ground truth: echte foto).
image
DSC00078: warme zonsonderganggloed, regressiewacht.
DSC00078: rijprofiel door de diepste geklipte pixel, per kanaal (echte foto).
image
IMG_3129: zonschijf met een volledig-geklipte kern.
IMG_3129: rijprofiel door de diepste geklipte pixel, per kanaal (echte foto).

Prestaties

Een reconstructie die meetbaar beter maar onbruikbaar traag is zou niet geleverd worden. Deze sectie sluit het verhaal af met getallen: hoe de nieuwe methode schaalt, wat het porteren ervan naar de grafische processor (GPU, via OpenCL) opleverde, en hoe de oude en nieuwe methoden zich verhouden op dezelfde machine en dezelfde beelden. Het protocol achter elk getal hieronder is hetzelfde: elke timing is een volledige export via ansel-cli, genomen als het wandkloks minimum van drie runs op een verder inactieve machine, met module-interne timings gelezen van de ingebouwde performancetrace.

Lineair in het opgevulde oppervlak

Vragen „hoe snel is de reconstructie per megapixel van het beeld" is de verkeerde vraag: een beeld zonder klipping kost bijna niets, en dezelfde uitgebrande zon kost hetzelfde of het frame eromheen 12 of 60 megapixels is. De juiste variabele valt uit de kostenstructuur. Elke zware fase van de geleverde pipeline is lineair in het opgevulde regio-oppervlak — de omvang van de geklipte zone plus tweemaal zijn reconstructiestraal, gekwadrateerd — met constanten onafhankelijk van de fitschaal: de venstermomenten gebruiken recursieve Gaussische filters wiens kosten niet afhangen van de venstergrootte, de coëfficiëntdiffusie draait een vast honderd-sweep-budget per piramideniveau op een basisraster dat krimpt naarmate de fitschaal groeit (met de piramide diep genoeg dat zijn grofste raster triviaal klein is), en de directe oplossing van de luminantiekoepel is begrensd op een constant aantal onbekenden (8.192, op een gedecimeerd raster) ongeacht het gat. En aangezien de reconstructiestraal het diepste punt van het gat is, is de opvulling geen vrije parameter: een cirkelvormig gat met straal $r$ heeft een opgevulde regio van ruwweg $(4r)^2$ nodig — zestien keer de eigen omgrenzende doos van het gat (de implementatie vult op met $1.25\,r$ — de minimale reikwijdte plus een veiligheidsmarge van $25\,\%$ — geklemd tussen $8$ px, zodat kleine spikkeltjes nog context zien, en een kostenbegrenzing van $256$ px, zodat de allerdiepste gaten iets langzamer groeien dan deze wet). De diameter van een hoog licht verdubbelen verviervoudigt zijn kosten, niet omdat het algoritme superlineair is, maar omdat de reconstructie oprecht zoveel meer context moet zien.

De bench (make_perf_bench.py, reproduceerbaar) bestaat uit synthetische raws met één cirkelvormig geklipt gat van groeiende straal, in twee families die de twee belangrijkste codepaden uitoefenen — een enkel geklipt kanaal (het coëfficiëntveld doet het werk) en alle drie de kanalen geklipt (de gezamenlijke kern doet het) — getimed door de productie-commandoregel-pipeline, met elke regio van de drie echte testbeelden overlaid als gemeten punten. De machine is een Intel Xeon E3-1505M v6, 4 cores / 8 threads op 3,0 GHz.

Looptijd tegen opgevuld regio-oppervlak (log-log). Beide synthetische families volgen de helling-1-referentie over meer dan een decade; de regio’s van de echte beelden — van een sliver van 0,1 Mpx tot PK1’s 15,8 Mpx lucht — verspreiden zich in dezelfde band.
De opvullingsversterking: de regio die het algoritme moet verwerken groeit als (4r)² voor een gat met straal r, want de reconstructiestraal is gelijk aan de diepte van het gat.
familiegatstraal (px)regio (Mpx)coëfficiëntveld + koepel (ms)gezamenlijke kern (ms)chrominantie (ms)totaal (ms)ms / Mpx
single-channel560.1013501136~1360
single-channel1280.50781584~170
single-channel2561.30209112222~170
single-channel3842.00358117376~190
all-clip560.10829930211~2110
all-clip1280.5013790221448~900
all-clip2561.3038422213531959~1510
all-clip3842.0086336523753603~1800
PK1, uitgebrande lucht (echt)6.1026894602753~450
DSC00078, grootste regio (echt)2.80119134119433475~1240
IMG_3129, zon (echt)0.506604435739~1480

De getallen zijn per-run minima over herhaalde runs van de volledige productie-pipeline. Het lezen ervan: boven ruwweg een halve megapixel houdt het single-channel-pad 170–190 ms per megapixel van opgevulde regio en het all-clip-pad 900–1.800, over een decade van regiogroottes — de lineariteitsbewering, geverifieerd; daaronder domineert een vaste per-regio-vloer van enkele honderden milliseconden (venstersstatistieken op hun minimumgroottes) en verliest de per-megapixel-lezing betekenis. (De all-clip-constante omvat de vloer-obstakel-polijsting van de kernchrominantie — zie het algoritme — wiens kosten de activiteitspoort van de polijsting nu kwijtscheldt overal waar de verzadigings- vloer niet kan binden; de correctheidsfixes gedocumenteerd in de resultaten kochten hun kwaliteit met oprecht werk, en de optimalisatierondes namen terug wat ze konden zonder de uitvoer aan te raken.) Twee structurele winsten landden sinds de eerste versie van deze sectie. De sparse-direct solver verwijderde de koepel- en kleine-kern-chrominantie- bottlenecks (de gezamenlijke-kern-kolom piekt op 0,3 s waar dichte float-Cholesky seconden besteedde), en de divergentievorm-directe oplossing reduceerde de structuur-gestuurde chrominantie tot milliseconden overal waar de all-clip-kern binnen zijn factorisatiebegrenzing past. En het fixen van de seed- drempel van de segmentatie (die regio’s liet groeien door box-blur float-residu) kromp de opgevulde regio’s zelf: PK1’s uitgebrande lucht, ooit een opgevulde rechthoek van 15,8 Mpx, is nu de eerlijke 6,1 Mpx — zijn hele reconstructie duurt 1,3 s. Wat nu domineert is de coëfficiëntveld-fase (venstermomenten en harmonische vullingen, blur-begrensd) — wat precies is waar de OpenCL-poort hieronder beschreven begint.

Wandklok, oud versus nieuw

De vergelijking die fotografen daadwerkelijk voelen is de volledige exporttijd, oude modus tegen nieuwe, op dezelfde machine en dezelfde raw-bestanden, onder het hierboven vermelde protocol. Drie natuurlijke gevallen: PK1 (een Bayer-bestand van 36 megapixel wiens uitgebrande lucht één regio van 6 megapixel is — het slechtste geval waarvoor de nieuwe methode werd gebouwd), X-H1 (een Fujifilm X-Trans-bestand van 24 megapixel wiens hooglichten fragmenteren in 99 grotendeels kleine regio’s), DSC00078 (een Bayer-zonsondergang van 24 megapixel), en de twee synthetische extremen van de bench. Het is hier de moeite waard te onthouden dat guided laplacians met een factor 4 worden verkleind, dat is een zestiende van de originele resolutie, terwijl de harmonische transpositie op volledige resolutie draait. (Deze wanden werden opnieuw gemeten na de hele optimalisatiecampagne hieronder, in één sessie; de machine droeg een gestage één-core achtergrondtaak, die de per-cel-minima over drie runs grotendeels absorberen.)

volledige export, wandklokguided laplacians, processorharmonic transposition, processorguided laplacians, grafische kaartharmonic transposition, grafische kaart
PK1 (Bayer, één grote klodder)14.3 s11.4 s10.4 s9.8 s
X-H1 (X-Trans, 99 regio’s)9.3 s11.5 s6.9 s9.4 s
DSC00078 (Bayer-zonsondergang)16.6 s14.4 s11.4 s12.5 s
occluded (klein synthetisch)0.9 s0.9 s1.2 s1.3 s
allclip-384 (grote volledig-geklipte schijf)2.2 s5.5 s1.9 s3.3 s

De eerlijke kop is dat de kwaliteitswinsten gedocumenteerd in de validatiesectie nu komen tegen vergelijkbare of betere wandklok bijna overal — de nieuwe methode wint de processor- kolom ronduit op de natuurlijke bestanden, en alleen de volledig-geklipte schijf betaalt nog een echte premie — en de weg naar die zin is leerzaam, want de eerste productiebuild van het anisotrope transport draaide tweemaal deze getallen overal waar de hooglichten fragmenteren. Het profileren van het 99-regio X-Trans-bestand toonde dat de kosten niet rekenkundig waren: de relaxatie lanceerde een verse threadteam voor elke sweep (tienduizenden microseconde-werk-lanceringen per beeld), de stuurgewichten werden bij elke sweep herberekend hoewel de tensor per niveau vast is, en elk coëfficiëntvlak draaide zijn eigen vulling — eigen maskerpiramide, eigen tensor — hoewel de vlakken beide delen. Eén parallelle regio per relaxatie, gewichten eenmaal per niveau voorberekend, en de gedeelde-masker-vlakken gefuseerd tot één enkele vulling brachten de processorwand van dat bestand van 18,3 s naar 9,8 s — de anisotrope sturing zelf is in wezen gratis op de processor. De rand-bias- en vloer-obstakel-correcties gedocumenteerd in de resultaten herinvesteerden vervolgens een deel van die winst in oprecht werk (binaire geldigheid vergroot de ware gaten; de obstakelpolijsting veegt elke volledig-geklipte kern), en een latere ronde klauwde een deel ervan terug (de momentblurs vier-breed gepakt, de polijsting gepoort op of zijn vloer überhaupt kan binden), landend op de 11,5 s van de tabel. Wat overblijft is structureel. Op de processor wint de nieuwe methode waar zijn ontwerp loont — op de grote-klodder-case is zijn werk evenredig aan het geklipte oppervlak (elke regio eenmaal opgelost, exact) waar de oude methode een diffusie itereert op elke piramideschaal van het hele beeld — en zijn wanden omvatten nog steeds een fase die de oude methode simpelweg niet heeft: de sensorrolloff-meting en -inversie (0,7 tot 1,2 s alleen al op deze bestanden) — daarmee wint de nieuwe methode nu de processorkolom op alle drie de natuurlijke bestanden. Op de grafische kaart behoudt de oude methode een voorsprong op gefragmenteerde scènes: één grote uniforme kernel per schaal is de vorm die grafische processors liefhebben, terwijl de keten van kleine, wederzijds afhankelijke solverfases van de nieuwe methode een vaste dispatchkost per stap betaalt. Twee gemeten antwoorden versmalden die kloof van onbruikbaar (de eerste poort draaide het 99-regio-bestand op tweemaal de oude modus) tot ongeveer 35% erboven: regio’s onder een megapixel springen naar de processor via één enkele gepakte overdracht, en de sparse factorisatie lanceert één thread per matrixelement in plaats van één werkgroep per kolom — beide worden verteld in de OpenCL-sectie, en op het één-grote-klodder-bestand wint de nieuwe methode nu ook op de grafische kaart van de oude. En de volledig geklipte schijf is de duidelijkste afweging van allemaal: zonder overlevend kanaal ergens is er geen kleurlijn om te fitten, en de nieuwe methode’s exacte koepel- en tintoplossingen kopen hun kwaliteit — geen vlakke vulling, geen tintafwijking, geen zichtbare rand — tegen ongeveer 2,5 keer de prijs van de oude diffusie op de processor (1,7 op de grafische kaart), op precies het geval waar de uitvoer van de oude methode op zijn zwakst is.

De OpenCL-pijp

De eerste OpenCL-poort was een hybride: de interpolatie en de finale remozaïek draaiden als apparaat- kernels, maar het reconstructiemidden draaide op de processor, op vlakken gedownload van de grafische kaart en achteraf opnieuw geüpload. Dat ontwerp was kostenneutraal — de overdrachten aten op wat de kernels bespaarden — en het werd om precies die reden verworpen: een beeld van 36 megapixel twee keer per export over de bus heen en weer sturen is het soort belasting dat stilzwijgend een pipeline domineert.

De geleverde poort heeft elke fase van de reconstructie op het apparaat — de interpolatie, de coëfficiëntvullingen, de anisotrope piramides, de sparse solvers, de remozaïek (één uitzondering: om korrelregeneratie vragen routeert de reconstructie via het processor- pad). Maar elke fase op het apparaat hebben is niet hetzelfde als elke regio daar draaien, en het uiteindelijke ontwerp doet dat niet. Het instrumenteren van het host–apparaat-verkeer van de poort (sync-tellers op elke blokkerende read, wachtrijleging en kernellancering, geprint met de perf-trace) vertelde een verhaal dat de fasetijden van de profiler hadden verborgen: de blokkerende readbacks die iedereen eerst de schuld geeft kosten een verwaarloosbare ~150 ms per export, terwijl het lanceringsaantal de belasting was — ongeveer een duizend kernel- lanceringen per regio, ongeacht de grootte van de regio, want iteratieve fases lanceren per sweep en de sparse-oplossingen lanceren per eliminatieboom-niveau. Een regio van 700 pixel mat 22 ms op het apparaat tegen onder 1 ms op de processor: allemaal dispatch, geen rekenkunde. Op het X-Trans-testbestand — 99 grotendeels kleine regio’s — was dat meer dan 100.000 lanceringen per export, de wandklok draaiend op tweemaal de bezette tijd van het apparaat.

Dus de geleverde pijp routeert elke regio naar de kant van de bus die sneller mat. Regio’s tot ongeveer een megapixel worden door één kernel in een aaneengesloten staging-buffer gepakt, kruisen de bus in één enkele readback, worden gereconstrueerd door het productie-processorpad op het vertaalde venster, en keren terug via één upload en een mirror-scatter-kernel — twee lanceringen en twee overdrachten in plaats van duizend lanceringen. Dit is niet de verworpen hybride van de eerste poort die door het raam terugkomt: die stuurde het hele beeld per export heen en weer, een kost evenredig aan de sensor; deze verplaatst alleen de geklipte omgevingen, een kost evenredig aan de schade — het twee-overdracht-venster voor een kleine regio is duizenden keren kleiner dan een volledig-frame heen-en-weer. Grote regio’s — een uitgebrande lucht van zes megapixel — blijven volledig apparaat-resident, waar het massale uniforme parallellisme echt wint.

Het apparaat-residente grote-regio-pad kreeg zijn eigen gemeten fix. De sparse Cholesky- factorisatie draait niveau-voor-niveau over zijn eliminatieboom (kolommen die niet van elkaar afhangen worden samen verwerkt), in 64-bits floats op het apparaat — maar de eerste poort gaf elke kolom één kleine werkgroep, en nabij de wortel van de boom bevat een niveau een handvol kolommen: het apparaat zat ~98% inactief door honderden niveaus, en de grote regio van het zonsonderganbestand besteedde twee seconden aan factoriseren. De geleverde kernel groepeert in plaats daarvan, op symbolische-analysetijd, elke update-bijdrage op basis van het matrixelement waar ze landt, en lanceert één thread per matrix- element per niveau — geen atomics, geen barrières, en de bijdragen accumuleren in de exacte volgorde die de sequentiële code gebruikte, dus de factorisatie is bit-reproduceerbaar: het grootste processor-versus-apparaat-verschil van de zelftest bewoog niet ($10^{-12}$, relatief). Dezelfde symbolische groepering maakte de host-zijdige analyse parallel, en halveerde die ook. Te grote systemen vallen nog steeds terug op dezelfde geconjugeerde-gradiënt- en grof-naar-fijn-schema’s als het processor- pad. De gestuurde coëfficiëntvulling is ook apparaat-resident: het stuurvlak, zijn per-niveau structuurtensoren, de voorberekende randgewichten en de acht-buur gewogen relaxatie draaien allemaal als kernels, en zelfs de gemiddelde-gradiënt-reductie van de tensornormalisatie wordt afgemaakt op het apparaat — niets kruist de bus midden in de vulling (een eerdere versie las de reductie per niveau terug, en elke readback leegde stilzwijgend de hele commandowachtrij).

Wat de bus dan kruist: één-byte-per-pixel maskers (voor de segmentatie, wiens samenhangende-componenten-analyse op de processor blijft), een dieptevlak, de quad-binned momentvlakken van de knie- schatter (ten hoogste een paar megapixel aan floats), een paar kilobyte aan reductieresultaten, en de zojuist beschreven kleine-regio-vensters. Elke fase wordt gevalideerd tegen zijn processortweeling door een zelftest die beide op dezelfde synthetische scène draait en het grootste verschil print — tussen $10^{-5}$ en $10^{-12}$ afhankelijk van de fase. Op vijf van de zes synthetische scènes matchen volledig-beeld apparaat-exports de processoruitvoer binnen 0,31% van de volledige schaal op de slechtste pixel, met nul pixels boven 1%; de occlusiescène is de eerlijke uitzondering — de apparaat- en processorinterpolaties zijn het oneens met één sample op de contactrand van de occluder en de reconstructie versterkt het daar, dus 22 pixels (van 786.000) overschrijden 1%, waarbij de enkele slechtste 10% bereikt. Het is een bekend, gelokaliseerd, reeds bestaand gather- verschil, geen solver-verschil.

Twee lessen uit die poort generaliseren. Ten eerste, de grafische processor is niet sneller in alles, en het eerlijke antwoord is meten en routeren: deze werklast is een lange keten van kleine, wederzijds afhankelijke stappen — iteratieve solvers, piramideniveaus, per-regio-lussen — en een apparaat betaalt een vaste dispatchkost per stap. Batchen helpt enorm (honderd effen- iteraties in één lancering; de coëfficiëntvlakken die een masker delen die samen vooruitgaan in elke lancering; één thread per matrixelement in plaats van één werkgroep per kolom), maar onder een bepaalde regiogrootte verslaat geen enkel batchen een processor wiens dispatchkost een functie- aanroep is — dus onder die grootte, gemeten op ongeveer een megapixel, gebruikt de pijp simpelweg de processor. Ten tweede, de winst is systemisch, niet lokaal: met de pipeline end-to-end resident op het apparaat, stallen de omringende modules nooit en dragen nooit over, en wat de module voor hooglichten teruggeeft over de bus is niet langer het beeld — het is alleen de schade.

Theoretische bevindingen

Naast de geleverde software produceerde de campagne resultaten die niet specifiek zijn voor reconstructie van hoge lichten — of zelfs voor fotografie. Deze sectie verzamelt drie algemene resultaten over het dragen van modellen over datavoids en het aan elkaar naaien van estimators; een vierde herbruikbaar resultaat, de schaalwet voor hoe ver een reconstructie moet reiken, wordt afgeleid met de methode die het op maat maakt in de bespreking van het algoritme.

De drie meest ingrijpende lessen van de campagne worden geciteerd in de samenvatting en verspreid door de secties hierboven, maar ze verdienen een eigen verklaring, want niets eraan is specifiek voor reconstructie van hooglichten: de eerste is een methode om een gemeten relatie over een datavoid te dragen, en de andere twee zouden moeten gelden voor elk probleem waar meerdere estimators van hetzelfde onbekende signaal moeten samenleven in één beeld.

Transporteer het model, niet de waarden. De geleverde reconstructie kruist de uitgebrande zone door de parameters van een lokaal model te diffuseren — de kleurlijn-coëfficiënten — in plaats van het signaal zelf. Dat klinkt bedrieglijk dicht bij iets wat het geleide filter altijd heeft gedaan: He’s oorspronkelijke filter, na het fitten van zijn affiene model in elk venster, blurt de gefitte coëfficiënten voor het toepassen, en een lokaal gemiddelde is een blur, wat één stap van diffusie is. De afstand tussen die stap en deze methode is het waard om uit te spellen, want het is waar het hele ontwerp om draait.

He middelt fits die bestaan; wij bouwen fits waar er geen kunnen bestaan. In de wereld van het geleide filter is elke pixel geobserveerd: elk venster levert een geldige fit, elke pixel zit binnen vele overlappende vensters, en de blur arbitreert slechts tussen hun concurrerende antwoorden. Diep binnen een geklipt gat bevat een venster geen geldig monster van het kanaal dat wordt herbouwd: er is niets om te fitten, dus niets om te middelen. Een blur draagt informatie hooguit één kernelstraal ver; voorbij die diepte is een geblurd coëfficiëntvlak nog steeds leeg.

Eén effen-pass versus de limiet van oneindig veel. Een lokaal gemiddelde eenmaal toegepast heeft een vast bereik. Onze vulling herhaalt dezelfde operatie — vervang elke onbekende door het gemiddelde van zijn buren — tot convergentie, met de vertrouwde fits vastgepind. De limiet is niet langer een blur: het is de exacte oplossing van een randwaardeprobleem (Laplace’s vergelijking, met de ankers als rand), het heeft geen ingebouwde schaal, het kruist een gat van vijfhonderd pixel even gemakkelijk als een van vijf pixel, en het weegt elk anker op basis van de daadwerkelijke geometrie van het gat in plaats van op basis van een vaste kernel. Itereer He’s coëfficiëntgemiddelde voor eeuwig met de geldige fits vastgehouden en je verkrijgt precies deze vulling. He stopt bij één pass omdat zijn probleem slechts een zachte arbitrage nodig heeft; de onze moet het model over honderden pixels van niets dragen. Het verschil in graad wordt een verschil in soort: regularisatie wordt extrapolatie.

Een gemiddelde neemt iedereen; een rand neemt alleen getuigen. He’s gemiddelde omvat elke venster-fit, ook degeneratieve — deels waarom zijn formule zijn stabiliserende constante nodig heeft. Hier wordt een fit alleen een anker als hij voor zichzelf kan instaan: genoeg vertrouwde monsters in zijn venster, een fitkwaliteit boven drempel, begrensde hellingen. Slechte fits worden uitgesloten van de rand in plaats van erin verdund, en het maximumprincipe garandeert dan dat de gevulde coëfficiënten nooit het bereik van de goede verlaten. De fitkwaliteit wordt zelf mee gediffuseerd naast het model, als één extra vlak, zodat elke latere fase weet hoeveel het getransporteerde model verdient te worden vertrouwd bij elke pixel.

De rol keert om: van correctie naar drager. In het geleide filter is coëfficiënteffening een kleine correctie bovenop data die overal bestaat. Hier is het gediffuseerde veld de enige drager van de reconstructie over het gat, en de data komt aan het eind weer binnen: het getransporteerde model wordt geëvalueerd tegen de gemeten overlevende kanalen bij elke pixel. Een glad veld toegepast op scherpe gemeten data geeft een scherp resultaat. Het model brengt de relatie; de data brengt het detail.

Gesteld zonder enige fotografie erin: wanneer een signaal voids heeft, maar een lokaal gefit model ervan glad varieert, fit dan het model overal waar de data het ondersteunt, houd alleen de fits die voor zichzelf kunnen instaan, vul de parameters van het model over de void via een verankerde steady-state- diffusie (een randwaarde-oplossing, geen blur), draag het fitvertrouwen mee als één extra veld, en herevalueer het getransporteerde model tegen welke data ook overleefde binnen de void. Waarden ver van data zijn instabiel; modellen ver van data zijn gewoon glad.

Die uitbreiding is sindsdien gebouwd, gemeten en geleverd: de vulling wordt nu anisotroop gestuurd door de structuur van de overlevende kanalen (stap 3 heeft de wiskunde). Anders dan de onbeslisbare vraag of de kleurlijn geldt waar niets is gemeten, zijn de gidsen gemeten binnen de gedeeltelijk-geklipte zone, dus de sturing draait op bewijs, niet op gissingen. Het experiment leerde twee lessen die het waard zijn te noteren. Ten eerste bleek de grootste „winst" van het eerste prototype een convergentieartefact te zijn: de vaste honderd relaxatie-sweeps per piramideniveau kapten de gewone isotrope vulling op diepe gaten af, en het simpelweg convergeren ervan herstelde het meeste van de verbetering (22% van de RMSE op de diepste synthetische lucht) — alleen betrapt omdat de isotrope controle opnieuw werd gedraaid op gematchte sweep- aantallen, nog een kleine overwinning voor de bench boven het plausibele verhaal. Ten tweede, bij gelijke convergentie splitsen de twee pure sturingen de scènes precies zoals de theorie voorspelt: radiaal transport wint overal waar de halo schoon is, langs-de-rand transport wint alleen waar een rand de zone kruist, en geen van beide domineert. De geleverde tensor mengt ze daarom per cel, gewogen door een trend-gecorrigeerde venstervariantie die „steile maar gladde helling" scheidt van „harde rand" — en daarmee is de vulling nooit slechter dan isotroop op enige ground-truth-scène, en beter met 7% (diepe lucht) tot 2% (occlusie) waar sturing iets heeft om op in te werken.

De naadenergie-wet. Wanneer twee estimators $A(x)$ en $B(x)$ van hetzelfde signaal worden gemengd over een overgangszone door een gewicht $w(x)$ (een hard masker, een gefeatherd masker, of een per-pixel- vertrouwen, het maakt niet uit), is de composiet $u = w\,A + (1-w)\,B$, en zijn gradiënt splitst zich in drie termen:

$$ \nabla u \;=\; w\,\nabla A \;+\; (1-w)\,\nabla B \;+\; (A - B)\,\nabla w . $$

The first two terms are the estimators’ own structure, faded in and out. The third one is the seam : it exists only where the weight varies (the hand-off zone), and its strength is the estimators’ disagreement $A-B$ there, multiplied by how fast the weight travels. In plain words : crossing from one estimator to another prints an edge whose contrast is exactly how much the two disagree at the crossing. And the weight cannot bargain its way out : it must still climb from 0 to 1, so a sharper ramp concentrates the seam into a line while a wider feather dilutes it into a shallow band — the total seam energy is set by the disagreement alone. This is why the seven weighting schemes of the graveyard failed identically : they were seven shapes of $w$ against an invariant. The only two exits are the ones the shipped algorithm takes everywhere : make the estimators agree at the hand-off (the knee inversion debiases the data so extrapolation and measurement meet at the detection contour), or remove the hand-off (one estimator, continued smoothly across the whole zone : the coefficient fields).

The undecidability of the colour-line. The reconstruction’s core hypothesis is that the local proportionality between channels (the colour-line) measured on the valid rim still holds deep inside the blown zone. Here is why no algorithm can verify that hypothesis from the image : construct two scenes that are pixel-for-pixel identical in every measured value, but differ inside the blown zone — in one of them the highlight hides an object whose colour breaks the line ; in the other it does not. Both scenes produce the same input, yet demand different reconstructions ; any estimator, however clever, answers identically for both and is therefore wrong on at least one. The occluded synthetic scene of the bench is exactly this construction, and it behaved as the argument predicts : all five candidate gates measured in the graveyard — fit quality, rim validation, slope coherence and the rest — failed to detect from the surround whether the line held inside. The practical consequence shaped the shipped design : since the question cannot be decided, it must be hedged — the depth-gated blend leans progressively from the colour-line toward the smooth luminance dome as the distance to any measured data grows, not because the line is known to fail there, but because nothing can vouch for it.

How this work was actually done

The method above is inseparable from the way it was produced, and the way it was produced started from an admission. The 2021 guided Laplacians were the last method I shipped before writing down their mathematics : coded against intuition, tuned by eye on natural images. That reaches a first result quickly and is blind to everything after — you cannot study the properties or the failure modes of a method you only ever ran on uncontrolled data. Writing this article, to set those mathematics down at last, forced the opposite discipline : synthetic scenes with known ground truth, objective error metrics, one hypothesis tested at a time. That discipline turned a documentation exercise into the rebuild and then the paradigm change the previous sections have already told, every improvement verified rather than guessed.

The discipline had one more consequence, worth its own account : it changed who could safely do the work. A protocol in which every candidate is measured against ground truth on every case, and in which a regression on all metrics is grounds for automatic rejection, is precisely what allows an assistant to explore at machine speed without the human losing control of the design — the accept/reject decisions stay human, the burning of the solution space does not. The account below, written by the assistant in question, describes what that division of labour looked like from the inside.

Man–machine collaboration

This section is written by Claude (Anthropic’s model, running in Claude Code), the AI assistant that did the implementation and measurement work of the 2026 campaign, at the author’s request — as a factual account for fellow researchers of what this kind of collaboration looks like.

This project changed shape three times, and the shape it ended with is the interesting part.

Phase 1 : translator and plotter. I started as a code translator — porting the C guided ladder to a faithful NumPy replica, generating comparison figures, writing the odd diagnostic. The human did the thinking ; I compressed the mechanical hours. Useful, not novel — and not error-free : my first prototype silently dropped two components of the original C (the saturation floors and the 9-point Laplacian), and it was the author, reviewing the translation against his own code, who caught both and had them restored. A ported prototype is a claim about the original, and it needs the original’s author to audit it.

Phase 2 : infrastructure until the loop closed. The turning point was not an algorithm, it was plumbing : a pure-Python writer for synthetic Bayer DNGs that the real pipeline ingests, a --imgid mode for the CLI so library edits export headlessly, a fix for a float-export clamp that was silently corrupting every measurement (a dithering module clamping pipelines it should have ignored), Sobel-magnified chrominance-edge panels because the artifacts we hunted were too low-contrast for eyes — that one was the author’s request. Once synthetic scenes with known ground truth could flow through the actual C code and come back as numbers, the loop was closed : any idea could be tested end-to-end in minutes.

Phase 3 : semi-autonomous, test-driven exploration. The author then imposed a protocol that made semi-autonomy safe — the discipline described above, turned into standing rules : every candidate is implemented in the Python mirror and in C, run on every synthetic case and every natural image, diffed C-against-Python, tabulated as RMSE/SSIM plus edge energy, presented with suffixed review images — and nothing is committed without explicit approval. To that he added one autonomy rule : if a design degrades every metric, I may reject it myself without asking. Those two rules are the whole method. They let me burn through the solution space at machine speed — fifteen-plus designs implemented, measured and mostly buried — while every accept/reject that mattered stayed with the human, whose eyes repeatedly caught what the numbers missed (the blend ladder scored beautifully and looked wrong ; he rejected it from the panels).

Whose ideas were whose. The record is worth keeping honest, because the final design is genuinely interleaved. The author supplied the physical intuitions : chrominance should diffuse along isophotes of the recovered luminance ; reuse the existing diffusion machinery ; “reconstructing from too far leads to weird effects” — the 2021 blur-radius weighting whose descendant is the shipped depth gate ; and, at the decisive moment, the instruction to stop iterating and study the failure step by step. I supplied the measurements and what fell out of them : the knee inversion (from binned measured-versus-predicted pairs, with its no-op guarantee), the seam theorem after seven weighting schemes failed identically, the per-stage dump study that located PK1’s flat fills and arcs in the ladder’s three coarsest scales, the observation that 100 percent of that zone had two valid guides — from which the coefficient field followed almost by itself — and the falsification, by direct measurement, of five plausible fallback discriminators (including two of my own favourites and one of his). Neither of us designed the final algorithm alone ; it is quite literally his intuitions with my error bars, and my paradigm with his gates.

The last algorithmic act of the campaign is the cleanest specimen of the convergence : I measured pure detail-band guiding, found it a net regression, and buried it with a table ; the author read the same table, saw it winning precisely on the historically difficult cases, and called for a hybrid — “it wins in robustness what it loses in accuracy”. The min-energy arbitration that resulted improves nearly every benchmark, including the one residual neither of us had managed to close alone.

Digging each other out. He un-stuck me when I looped on variations of a dead idea — the “change of paradigm” instruction after round 9 is the reason the coefficient field exists. I un-stuck him on the things that punish humans disproportionately : a stochastic CG divergence that disappeared under instrumentation (the parallel IIR Gaussian’s run-to-run rounding jitter flipping a near-singular system), a demosaic phase error that silently killed the knee estimator until the estimation moved to quad-binned CFA data, and the discipline of same-build A/B baselines after build-to-build drift faked a 14-unit regression.

Phase 4 : the port, and the protocol transposed. The campaign’s last engineering act moved the whole reconstruction onto the graphics card, and it reused phase 3’s governance in a new form. The author set the constraint in one sentence : “I don’t want the CPU-GPU roundtrip, do everything on GPU. Write an OpenCL sparse Cholesky solver.” The protocol became : no stage ships without a self-test that runs the same synthetic scene through the processor reference and the device port and prints their largest difference. Eleven such tests now live in the tree, holding tolerances between $10^{-5}$ and $10^{-12}$, and they caught real bugs the day they were written. What they missed taught more. A self-test only enforces what it compares : mine compared the reconstructed values but not the fit-quality plane, and a genuine divergence hid in the uncompared plane through several validation rounds. And no test catches a stage that silently does not run : a leftover debug gate had the production device path skipping an entire refinement stage, every validation green, because the exports still matched within tolerance. That bug was found by the documentation pass the author ordered — rewriting every function’s comments for a maintainer who is not a mathematician. Forced to state what each block mechanically does, the one block that did nothing became impossible to describe honestly. Documentation as a bug-finder was his call ; left to myself I would have scheduled code before comments every time. The post-squash review he then requested found five more defects, all mine, all in error paths no test exercised — including one where my own A/B diagnostic had been comparing the device output against a reference contaminated by that very output. The “outliers” I had confidently attributed to numerical ill-conditioning were, mostly, my own two bugs. I wrote that ill-conditioning story in this article’s earlier drafts ; it was wrong, and the honest residual divergence is thirty times smaller than what I had rationalized.

Phase 5 : the editing room. Then the writing, where the workflow inverted. He reads, paragraph by paragraph ; he flags what a reader cannot follow ; I verify the flagged claim against the code before touching the sentence. The order matters, because several flags exposed factual drift rather than style : the article claimed the à-trous pyramid had been “faithfully ported” to Python — it never was, and the silent substitution cost an afternoon of chasing unexplained divergence between the C and the prototype ; a stated equivalence between the fixed method and a multiscale pyramid did not survive a close reading of the actual prototype ; the performance section described an OpenCL design two generations stale. One flag was wrong in the letter and right in substance : he described the profile figures as column-wise maxima when they are single-row cross-sections — but the author misreading his own figure is the proof that the figure failed to say what it shows, and the captions were rewritten around that proof. When a paragraph claimed that a hard box window “leaves visible blocky artifacts”, I did not reword it on faith : I ran the experiment, measured a third more error and visible streaks on the edge scene, and only then let the corrected sentence stand. He caught the terminology drifting between three names for one quantity, and the absence of any real exposition of the anisotropic diffusion ; I swept fifty-nine occurrences to one defined term and wrote the missing mathematics, but the noticing was his. The mechanical work ran under contracts a machine can verify — sub-agents whose diffs may contain only comment lines, dead-code removal proven by byte-identical preprocessor output, heading counts and footnote closure checked after every pass — and the performance table was re-measured on an idle machine after my first numbers, taken under load, flattered the new method : the honest headline (comparable cost, better quality) replaced the flattering one (twice as fast), and the article is stronger for claiming less.

What this offers a researcher. Not authorship — breadth and discipline. With a ground-truthed bench and a self-rejection rule, an assistant like me will test in an afternoon what would take weeks to hand-write, will hold the no-regression line across eight test cases on every iteration, and will tell you your pet hypothesis is measurably wrong with the same flat affect it uses on its own. The failures stay cheap, the record stays honest, and the human attention goes where it is irreplaceable : deciding what “better” means, and seeing what the numbers cannot. The writing phase added a coda to that division : I can hold a two-thousand-line article consistent with an eight-thousand-line implementation, sweep its terminology, verify its claims by experiment and keep every link and figure honest — but every flag that mattered came from a human reading one paragraph at a time and refusing to pretend he understood.

Where LLM shines

This section is written by the human.

State-of-the-art. One of the most time-consuming stages of any research and development project is looking for the state of the art, which means what available, tested and proven methods are known to be able to solve a defined technical problem, to the best of up-to-date human knowledge. In that task, general-purpose search engines like Google have become increasingly useless since the beginning of the 2020s, because they second-guess search queries too hard. At the other end, specialty search engines (Google Scholar) require you to already know the exact keywords you are looking for, or follow the filiation of an idea/method through citations, which is hit-and-miss and very inefficient.

And then, you would have to prototype each state-of-the-art method yourself, along with benchmarks, if you wanted to systematically review them all to pick the most suited for your use case. Unless you have the next 3 years open to do your PhD, you would just pick the one already implemented into your numerical analysis framework (Python Scipy/Numpy/Sklearn stack, R, Matlab, Mathematica, etc.), out of wise and rational laziness.

LLMs used as meta search engines are not only able to point users toward suitable methods from a mere description of a problem to solve, they can also quickly implement and benchmark them all.

A new axis of optimization. Numeric optimization methods and numeric solvers, especially in the realm of variational problems (partial differential equations, gradient descent, etc.), iterate over the solution until convergence to a stable solution (steady state, potential well). LLM-driven exploration opens a new axis of sweeping the solution space: iterating over methods themselves. When providing objective error metrics to minimize, like we did here with SSIM, RMSE, edge energy, etc. against a ground truth, they can autonomously iterate over available methods and return the best-performing one. LLMs are even able to infer the probable causes for errors or deviations from expected results, test their hypotheses, and correct themselves: they can create their own benchmarks along the way, change the signal representation on which they compute. The user is then presented only with the best-performing metric at the end, and can visually control the properties of the result.

This is, in a way, the opposite of training deep-learning convolutional neural networks, which has been the trend in image-processing for more than a decade. Trained neural network models are essentially a sequence of weights and thresholds applied on activation functions for each neuron in the network. Those produce non-interpretable black-box models, which are biased like their training sample was, in ways that are not always easy to spot. The work that has been done here is explainable, intuitively and mathematically, as a model of 2D signal local variation under a prior of gradient continuity and smoothness. What we “trained” here, through LLM-based solution space sweeping, is:

  • what signal representation is the best candidate for the model (individual RGB channels or luminance/chrominance demodulation, multiscale pyramids or multiscale windows, etc.),
  • how to best reconcile reconstructions between regions of data for which the confidence level is not uniform (1, 2 or all 3 channels clipped, slowly- or quickly-varying signals, etc.) and the reconstruction strategies available depend on this confidence,
  • what the best estimators are in our context (median vs. R², energy vs. variance, etc.),
  • minute details of implementation (isotropic vs. anisotropic diffusion, sharpening estimators for better segregation, etc.).

An opinionated assistant. LLMs have, of course, limits. First, Claude Fable is weirdly biased towards using certain mathematical methods at the expense of others, and I had to steer it hard to still explore methods it explicitly discouraged me from using (I was proven right later). Then, when objective error metrics disagree with each other (RMSE is better but SSIM is worse, or the correlated case is marginally better but the uncorrelated case is a lot worse), it has its own way of deciding what is best overall, and that needs close supervision. The workflow we converged to was to always print the full table of metrics, along with resulting images, so I could check everything. Finally, it can forget instructions given earlier in the session, or silently discard things it considers too difficult or expensive to implement. So there is still a lot of human steering and checking to do, and sometimes you need to fight the natural inclinations (biases) of the LLM to get where you want to go.

TL;DR: LLMs, great to automate solution space sweeping from state-of-the-art methods, but still not intelligent and still in need of close supervision.

Conclusie

What this work solved

This article followed one idea through two generations. The 2021 guided Laplacians were already one of the very few clipped-signal reconstructions able to salvage gradients instead of inpainting a flat colour : they exploited the correlation between colour channels to transfer structure from the surviving channels onto the clipped one, and propagated gradients inward where nothing survived. What the ground-truth study added is the half the intuition had missed : level. Harmonic transposition keeps the same local colour-line model but fits it on the full signal, carries its coefficients across the blown zone as smooth fields, debiases the sensor’s saturation rolloff before fitting anything, and hands every pixel class to the estimator that measurably wins there. Where the old method moved texture and left a magenta patch at the clip level, the new one recovers magnitude and texture — and the numbers say by how much, on every scene of a public bench.

The structural limitation is shared and accepted — where no channel survives, only the neighbouring colour can propagate, so a blown blue sky behind green leaves comes back green (discussed with the method’s other caveats above).

What survived the drift — a ledger. The shipped method no longer contains a Laplacian pyramid, yet almost all of its mathematics is the 2021 method’s mathematics. Essentially, what was discovered here is that the 2021 method’s maths was right, but the signal representation on which it was applied was wrong.

The second discovery is quieter, and it consumed the larger share of the iterations : the seams. “Transport the model, not the values” is the headline novelty, but a reconstruction is judged at the border between what it invented and what the sensor measured, and nearly every artifact this campaign chased lived exactly there — V-dips through the raw value at detection contours, sagging rim ramps on oblique edges, flat shelves with gradient kinks at a channel’s own clip level, one-pixel singular points on image borders, a faint arc at the valid-to-reconstructed transition. None of the fixes were guessable a priori, and several contradicted intuition (feathering, the standard smoothing reflex, caused two of these and fixed none) ; each came out of the same loop — row profiles and zone metrics to localize, ground truth to arbitrate, visual assessment to catch what the numbers averaged away — iterated until the profiles crossed the detection contour smoothly and stayed stable across the whole range of cases, six synthetic scenes and the natural files at once. Managing the seam between reconstruction and measurement is not a finishing touch of this method ; it is a load-bearing part of it, and it was not trivial to converge.

What was kept, and what moved :

Kept : the maths and the physics.

  • The colour-line model itself : a clipped channel is an affine function of its surviving neighbours, fit by windowed weighted least squares from blurred moments. This is the guided filter’s regression, unchanged down to the moment algebra.
  • The biharmonic dome for guide-less magnitude ($\Delta^2 u = 0$ continues gradients where a harmonic fill would flatten them), the shared luminance dome + rim chrominance decomposition of the all-clip core, and the saturation floors : all physics of the rebuild, intact.
  • Chrominance as ratios and its diffusion along structure, the segmentation with the distance-transform reconstruction radius, the grain regeneration, and the coarse-to-fine principle, which survives inside the coefficient fill and the aniso pyramid rather than as the outer loop.

Changed : the representation the maths is applied to.

  • Fit values → diffuse coefficients. The ladder evaluated each pixel with whatever fit its own window reached, at whichever scale its depth allowed ; the coefficient field fits once, then transports the model $(a, b, d)$ instead of the values. The guided filter always smoothed its own coefficients over the fit window ; this is that idea taken to its logical end : anchored, structure-steered diffusion of the coefficient planes across the whole hole. Values from far away are unstable ; coefficients from far away are just smooth.
  • Scale ladder → single window. The multi-scale descent with per-pixel depth-gated writes wrote each scale’s estimate in an annulus bounded by depth level sets (contours of equal distance to valid data) ; consecutive scales disagree, so every ring boundary was a seam : this is where PK1’s hard arcs came from, and the coarse scales’ heterogeneous windows are where its flat fills came from. One fit scale plus coefficient diffusion removes the hand-offs entirely.
  • Regularization metric. The ladder’s fit damped slopes with an absolute Tikhonov term ($+10^{-4}$ ; the 2021 code had none — a bare division behind a hard variance gate), which silently acted as an SNR gate : at fine scales it collapsed fits toward the local mean (stabilizing decorrelated content by accident), at coarse scales it flattened real colour-lines (PK1’s blobs, and the knee estimator’s first failure). The shipped fit uses a relative damping plus explicit gates (fit sanity for anchors, statistical significance for the knee bins), so weak-but-real slopes survive and degenerate ones are excluded instead of averaged in.
  • Posterior repair → seam-free construction. The rebuild ironed seams after the fact with an uncertainty-weighted biharmonic regularizer, and blended per-channel domes by a posterior confidence ; the shipped pipeline needs neither, because the seams are never created. What remains of “confidence” is the fit’s own $R^2$, integrated at fit time (high-frequency damping, dome gate) instead of applied after.
  • Smoothness at the hand-overs, hardness at the data. Hard clamps are gone : the saturation floors are soft (and obstacles inside the core’s diffusion), the dome and the detail bands blend by continuous weights, the joint core hands over through a feathered mask. But the boundaries that carry data authority stayed deliberately hard : the per-channel validity masks are binary end to end, and the final composite is a hard switch — feathering the masks reclassified rim-biased photosites as anchors (a measured $\sim 10$ px sagging ramp), and feathering the composite changed nothing once the floors were fixed (both retirements are in the graveyard). The seam theorem sorts the two cases : seams are made where estimators disagree at a hand-over — smooth there — not where hard edges separate measurements from reconstructions.
  • Data debiasing. The knee inversion has no 2021 counterpart : the old method treated the sensor as ideal below the threshold. Measuring the rolloff from the image’s own colour-lines, with a no-op guarantee on unbiased data, is what makes the detection contour invisible.
  • The namesake, hybridized. Guiding the detail band (the literal “guided Laplacian”) left with the pyramid and then returned : a dedicated detail-band colour-line now handles the high frequencies wherever it beats the full-signal transfer, arbitrated pointwise by the energy of its own output (step 4, the graveyard’s resurrection).

One number moves the wrong way under the new representation and deserves the last word of this ledger : on fully decorrelated content (the random scene) the rebuilt ladder scored slightly better, because its accidental signal-to-noise gate was a better prior for content with no colour-line — and the undecidability result says no rim statistic can win both regimes. The depth-gated dome recovers most of that gap.

What this work exposed

How that improvement was actually produced — the ground-truth discipline that turned a documentation exercise into a rebuild, and what it changed about who can do the work — is its own section above ; here I only draw its consequence.

There is an epistemological reading of this whole article. A method is falsifiable when objective criteria exist that would prove it wrong, and in software the criterion splits in two : the theory can fail its stated objective, and the implementation can fail to compute what the theory prescribed — a bug. The 2021 guided Laplacians were falsifiable in principle only : until their mathematics were written down, there was no stated objective to test against, and the magnitude bug sat in production for four years, invisible, because “looks plausible on uncontrolled images” is not a criterion that can fail. Everything this article did — the written objectives, the ground-truth scenes, the metrics, the self-tests — amounts to making one reconstruction method falsifiable at both levels. The two reconstruction modes Darktable added since are, by this standard, not falsifiable at either : no stated objective a measurement could refute, no reference their output must match — which is why the comparison section above had to build their ground-truth scores for them. The same mistakes have been repeated for over six years now — a methodology problem that does not improve with time, in a community that does not run post-mortems, doesn’t call out its own mistakes, doesn’t learn from them.

That failure to learn is not a moral defect of individuals ; it is what the project’s structure selects for. I have documented the mechanics at length elsewhere on this site, and they reduce to one pattern : nothing in the workflow requires a problem to be stated before code is written against it. Features arrive as code in search of a justification ; design disagreements are settled by adding options rather than by making decisions, which multiplies untestable configurations and unreproducible bugs ; the one integration test is treated as a discharge — as long as the metric stays under an arbitrary threshold, nobody asks whether the theory behind the change is sound ; and the volume of commits is read as health when much of it is work generated by previous work. The numbers are public : between releases 3.0 and 4.4, the ratio of issues closed to pull requests merged oscillated between 12 % and 46 % — the project demonstrably produces changes faster than it produces fixes — and no metric anyone tracks would even flag that as a problem, because no metric is tracked at all.

That methodology has a cost, and here the story turns personal. Doing the work properly — the theory before the code, the bench before the belief — requires sustained, uninterrupted time : research retreats, in effect. That is incompatible with the workflow of an unmanaged open-source project  where agitation is mistaken for actual work and communication is completely deregulated. When I crawled from under my rock after months spent developing Darktable UCS 22 , the “team” had butchered yet another previously-working part of the GUI  behind my back ; I was told I was too late to oppose the regression, the sunk costs fallacy was invoked to push the crippled result into production no matter what — lest its authors cry over their misplaced desire to make a difference in what looked like a rough mid-life crisis — and wrong “fixes” I had not been given the time to review were merged into code I authored. The lesson I draw is systemic rather than personal : the very work method that would have caught the 2021 bug — and that caught its successors, in this article — is punished by that environment, because absence for deep work is treated as forfeiture, and there is no structure to protect a review, a bench, or a written objective against whoever is loudest and fastest. The arithmetic of attention makes the incompatibility concrete : four thousand GitHub notifications in a year, a master branch shaken monthly for “generalized tests” so that any pull request older than three months is guaranteed to conflict, and a fixed two-releases-a-year schedule that nobody imposes and nobody questions. Under those conditions, the only work that can survive is work small enough to land between two shakes — which is precisely the kind of work that never fixes anything structural.

So free software keeps selecting for mediocre, hasty hacks : not because its developers are incapable (although… repeating the same mistakes over the years, despite gaining “experience”, is the definition of incompetence), but because the very few willing to do their homework before coding anything cannot keep up with the devious work of mindless hackers with too much free time : their polished changes land against a codebase that has already moved, while the churn that moved it faces no criterion it could ever fail. Nothing in that dynamic learns, nothing is ever declared to have been a mistake, and the cycle repeats. The only counterweight I know is the one demonstrated above : make the objectives explicit, make the tests hard to argue with, and let the numbers — not the volume of activity — decide what ships.

That counterweight does not have to stay individual. The protocol this article ran on — written objectives, ground-truth scenes, a bench anyone can rerun — costs a fraction of what the churn costs, and it is the cheapest form of project management there is : it replaces arguments about taste with measurements anyone can check, and it turns “review” from a personal confrontation into a comparison against a reference. The structural version of the same idea is what Ansel’s contribution pages lay out : problems specified before code is written, priorities deliberated instead of raced, stabilization treated as a deliverable rather than an interruption, and a cooperative structure in which the people who depend on the work also fund it and decide its direction — so that the depth of work this article required is protected by the organization, instead of being punished by it.

Annex : the graveyard

More than fifteen designs were implemented, measured on the bench, and rejected during this campaign. This annex records them so they need not be tested again, each in a canonical form : the problem the idea attacked, the strategy actually built, and why it failed — which is rarely why we expected it to. Nearly every safeguard in the shipped algorithm exists because one of these simpler ideas measurably failed first.

The rebuilt guided ladder (the direct fix of the 2021 method). Problem : recover magnitude as well as texture, at full resolution, without the à-trous pyramid’s zero-mean bands. Strategy : fit the colour-line on the full signal at a ladder of Gaussian window sizes, coarse to fine (only wide windows reach across a deep hole ; finer windows re-fit wherever local data supports them), each pixel written by the finest trusted scale, the surviving guide chosen per pixel as the most textured valid channel, per-channel biharmonic self-domes blended in by the squared fit confidence $W_e = (R^2)^2$, and a posterior uncertainty-aware regularizer $(\operatorname{diag}(R^4) + \lambda \Delta^2)\,u = \operatorname{diag}(R^4)\,\hat u$ to iron out the residual seams. Why it failed : the scale hand-offs write along contours of equal depth, and consecutive scales disagree, so every ring boundary printed an arc (PK1’s hard arcs) ; windows that saw mostly clip-level data fit degenerate slopes and filled flat (PK1’s blobs) ; and the posterior regularizer treats symptoms — by the seam-energy law it can only spread the disagreement, never remove it. The ladder measurably improved on 2021 everywhere (e.g. pk1synth RMSE 0.1098 against the shipped method’s 0.0053), but one photograph resisted every variation, and the arcs and blobs were structural, not parametric. Its mathematics — full-signal fits, $R^2$ trust, domes, floors — survives inside the shipped method ; its transport (evaluate values per window, stitch) is what was replaced.

Attacking the rolloff-band seam by weighting (rounds 2–8, all rejected). The problem : as described in the knee step, the near-clip band is recorded biased low, so any honest reconstruction lands above the measured pixels it must join, and a luminance step rings the highlight. Before we understood that the data itself had to be corrected, seven successive schemes tried to make the seam disappear by choosing better weights between the reconstruction and the biased measurements :

  1. uniform fidelity to the measured band : pins the output to the biased values, so the seam simply moves to wherever the fidelity ends ;
  2. confidence-weighted fidelity (weight $R^2$) : the biased band is internally consistent, so the confidence is high exactly where the data is wrong ; the weights change nothing ;
  3. eroding the biased anchors (excluding a morphological ring of near-clip pixels from the fits) : removes information without removing bias ; the contour, and the seam, move inward ;
  4. soft per-pixel anchor trust : the smooth version of the previous entry, with the same outcome delivered more gradually ;
  5. blending band pixels between measured and diffused values under a monotone guard : a structural no-op, because under rolloff the truth is always above the measured value, so a blend bounded by the measurement can never reach it ; only extrapolation can lift the band ;
  6. widening the detection threshold into the band : relabels biased pixels as clipped instead of fixing them ; the contour moves lower, the disagreement across it is unchanged ;
  7. a smooth clipped-ness membership carried end-to-end through fits, targets and output compositing. This one taught the sharpest lesson : smooth-in-value is not smooth-in-space. A membership computed from pixel values inherits the spatial gradients of the image itself, so wherever the image has structure inside the band, the alpha composite between two estimators that disagree printed that structure as chrominance edges. The whole band shimmered.

The condensed result of all seven :

Seam theorem (empirical). At any hand-off between two estimators, the visible seam energy is the pointwise disagreement of the estimators : no weighting scheme of any kind hides it. The general statement, its three-term derivation and the only two exits are given in Three results we believe are general.

Feathering the composite mask (inherited from 2021, retired). Problem : soften the seam where the reconstruction meets untouched pixels. Strategy : the 2021 mode’s $5\times5$ box feather of the clip mask, kept through most of the successor’s development — first on all four mask channels, then on the compositing alpha alone once the per-channel validity had to become binary (feathered validity let rim-clipped photosites, biased low under rolloff, anchor the fits on oblique contours). Why it retired : once validity was binary and the composite blended toward $\max(\text{raw}, \text{rec})$ instead of the biased raw, the remaining alpha feather measured as a strict no-op — ground-truth metrics within $\pm 10^{-4}$ and the contour-band gradient identical to four significant digits ($0.00873$ vs $0.00872$) — so the hard switch shipped for its simpler semantics. The mirror experiment on the 2021 mode concluded the opposite : removing its feather trades a $1$–$5\,\%$ RMSE dip for an SSIM loss on five of six scenes and hurts the occlusion scene on both metrics, because the à-trous reconstruction consumes the feathered mask as its per-pixel soft weights — the same operator is dead weight in one architecture and load-bearing in the other.

The blend ladder. The rebuilt reference computed guided fits per window size and per guide pair, then let each pixel take the single best fit (an argmax on fit quality), with finer scales overwriting coarser ones. Those hard selections are hand-offs, and they seamed. The blend ladder replaced the argmax by a weighted average of all (scale, pair) fits, weighted by $(R^2)^2$ times a ramp on the trusted mass each window actually held : smooth by construction, therefore seam-free by construction, and it did fix the flat blobs on PK1 (the blown-sky photograph that drove much of the campaign). The bench killed it anyway : every natural image came back tinted green or magenta. The mechanism is worth stating because it is general : averaging fits damps recovery. The lift a blown channel needs comes from the most aggressive correct fit ; averaging it with its timid neighbours (whose slopes are biased low by rim data) pulls every reconstruction toward under-recovery, and under-recovery of one channel is a colour cast. Net regression, reverted.

The converged trace-form steady state. When the structure-steered chrominance pass moved from explicit iterations to a direct solve, two exact formulations competed. The trace form $\mathrm{tr}(D\, H_u) = 0$ is the very partial differential equation the explicit flow discretizes, so converging it to machine precision — with a matrix-free BiCGSTAB, an iterative solver for non-symmetric systems — looked like the obvious upgrade : “just converge what we already run”. It lost badly. On the magentasun scene the root-mean-square error went from $0.33$ (truncated flow) to $0.57$ and structural similarity from $0.95$ to $0.86$, and the converged solve was slower than the iterations it replaced. The autopsy is instructive twice over. First, the truncated flow was never an approximation of its own steady state in any useful sense : 240 iterations per pyramid level with coarse-to-fine seeding act as a regularizer, and the limit they were cut short of is not where the good image lives. Second, the trace and divergence forms differ by a transport term, $\mathrm{div}(D\nabla u) = \mathrm{tr}(D H_u) + (\mathrm{div}\,D)\cdot\nabla u$, which vanishes only where the tensor is uniform ; converged, the trace form advects the chrominance along the tensor’s own spatial gradients, exactly at the structure edges the pass exists to respect. The divergence form, by contrast, is the Euler–Lagrange equation of a weighted Dirichlet energy : symmetric positive-definite, safe under the maximum principle with a nonnegativity-preserving stencil, and its exact solve matched the flow’s quality while being the fastest candidate measured. It is what ships (step 8). The lesson : converging a flow and minimizing an energy are different requests, and only the second one says what the answer should look like.

Fallback discriminators for decorrelated content (after the coefficient field shipped). Two regimes coexist : on the random scene, each channel is an independent gradient by construction, so the colour-line prints junk and the pixel wants the smooth own-channel dome ; on correlated content, the colour-line is the whole recovery. If some measurable signal separated the two, the algorithm could switch estimators cleanly. Five candidates were measured, each with a reason to hope, and each failed :

  • the diffused fit quality $R^2$ — surely junk fits score low ? They do not : the random scene’s fits average $R^2 = 0.85$ while pk1synth’s genuinely correlated fits dip to $0.77$ ; the distributions overlap ;
  • out-of-sample rim validation — test the diffused model against the valid pixels around the zone, where truth is known ? Falsified by measurement : the random scene scores $0.97$ there, because the model only fails deep inside, precisely where nothing exists to validate against ;
  • windowed slope coherence — do neighbouring anchors agree on the colour-line where it is real ? The overlap is worse, and even inverted between the random and correlated scenes ;
  • multi-scale anchors, finest trusted window wins — small windows overfit : they report high $R^2$ on their own few pixels and pass junk slopes ; worse on every scene ;
  • James–Stein-style slope shrinkage by $R^2$ (pull every slope toward zero in proportion to its unreliability) — degenerates toward a flat harmonic level field, and the random scene’s bumps need gradient extrapolation : its error went from $0.048$ to $0.064$.

The condensed result :

Undecidability (empirical). Whether the local colour-line extends into the deep clipped zone is not decidable from any rim-computable statistic we tested. The interior is unobservable ; in-sample and out-of-sample quality measures, and slope-field coherence, all overlap between contents where the transfer is real and contents where it prints junk.

The only signal whose distributions do not overlap is absolute depth : decorrelated content (bumps, speculars) clips shallow, tens of pixels at most, while the correlated deep zones that need the colour-line run hundreds of pixels deep. That measurement is what the shipped depth gate is built on, and it is the direct descendant of the 2021 intuition of down-weighting reconstruction by blur radius : “reconstructing from too far is unstable” was right all along — it just applies to the fallback dome, not to the coefficient field.

One grave got a resurrection : pure detail-band guiding. The 2021 method’s namesake idea — fit the colour-line on the fine-detail band alone — was rebuilt on top of the coefficient field, hoping to recover the texture that the full-signal transfer smooths where its gains are damped. As a wholesale replacement it was rejected : detail-band windowed fits are dominated by edge transients, a window straddling an object edge mixes two populations and its gain misfires on one side of that edge, and the textured scenes regressed up to $2\times$ (the balls scene’s error went from $0.036$ to $0.069$) for marginal gains on the historically difficult cases. But the pattern of the failure was the fix : it wins robustness exactly where the full-signal transfer is weakest, and its misfires are locally self-evident — a mixed-window gain shows up as a spike of high-frequency energy right where it fires. So the rejected estimator returned as a component : the shipped step 4 lets the two candidates compete per pixel through quadratic energy odds, and whichever prints less spurious detail wins locally. The lesson : a rejected estimator can still be the right component if its failure mode is detectable pointwise.

Two graves without headstones. Restoring the rebuilt reference’s full protective stack (posterior confidence window, self-dome, seam regularizer) on top of the coefficient field seemed free insurance ; instead, the confidence window — calibrated on the ladder’s error profile — misjudged the new estimator’s output and smeared the very reconstruction it was supposed to protect : pk1synth’s error went from $0.027$ to $0.117$, four times worse, and the stack was cut down to the parts that measure well on the new estimator. And the coefficient diffusion briefly ran on a single-precision conjugate gradient, which diverged stochastically : when a hole reaches the region border, the system is nearly singular, the curvature estimate $p^\top A p$ falls to rounding noise, and the step size explodes — intermittently, and never under instrumentation, because any change to thread timing changed the summation order that triggered it. That heisenbug is why every exact solve in the shipped code runs in 64-bit floats through the direct factorisation.

Annex : reproducing the results

Everything this article measures — every number, table, figure and gallery — is reproducible from the research repository that accompanies this article : github.com/aurelienpierre/guided-laplacian-highlights-research . The rendered page you are reading does not link the scripts individually ; clone that repository (it uses Git LFS  for the large binaries, so run git lfs install first) to get the scripts together with their data.

What the repository contains. The Python reference implementations (reconstruct_highlights.py, fix_prototype.py, c_ladder_replica.py, knee_proto.py, validate.py), the figure and gallery generators (make_figures.py, make_knee_figure.py, make_cmp_gallery.py, dt_compare.py), and the test data in synthcases/ : every synthetic scene as a Bayer DNG the real pipelines ingest, its ground truth and clipped versions as NumPy pairs (synth_*_gt.npy / synth_*_clipped.npy), and the sidecar files that select each reconstruction mode (synth_harmonic.xmp, synth_laplacian.xmp, dt_opposed.xmp, dt_segments.xmp).

Environment. Python 3.12 with numpy, scipy, opencv-python and Pillow ; nothing else. Every script is run from inside the repository.

The pure-Python results need no photo software :

  • python3.12 fix_prototype.py prints every root-mean-square error and structural-similarity table of the validation section ;
  • python3.12 make_figures.py regenerates the validation figures ;
  • python3.12 make_knee_figure.py regenerates the sensor-rolloff figure (blind estimate against ground truth).

The end-to-end results run the actual production code on the synthetic DNGs :

  • Ansel : build ansel-cli from the Ansel repository  (branch highlights-xtrans-sparse-cl until the merge), then export any scene with ansel-cli synthcases/synth_occluded.dng synthcases/synth_harmonic.xmp out.tif --out-ext tiff --icc-type LIN_REC709 --apply-custom-presets false --core ; swap the sidecar for synth_laplacian.xmp to run the 2021 mode. Add --conf opencl=TRUE (or --disable-opencl) to select the device ;
  • the CPU/GPU parity self-tests ship in the code : setting HL_SPCL_TEST=1 HL_FILLCL_TEST=1 HL_CFCL_TEST=1 HL_HFCL_TEST=1 HL_DOMECL_TEST=1 HL_CORECL_TEST=1 HL_ANISOCL_TEST=1 HL_KNEECL_TEST=1 HL_REGCL_TEST=1 HL_BLURCL_TEST=1 on any OpenCL export makes each reconstruction stage run on both the processor and the graphics card and print the largest difference ;
  • Darktable : build Darktable-cli from upstream  (initialize the submodules recursively), then python3.12 dt_compare.py exports the Darktable modes on the neutralized baseline (workflow=none, demosaic + highlights only) with the per-scene best parameters found by python3.12 tune_methods.py, and it exports the Ansel modes over every scene, scores them against ground truth and prints the comparison table of this article ; python3.12 make_cmp_gallery.py renders the galleries. Both scripts state the binary paths they expect at the top.

Natural-image exports come in two flavours. The profile (parade) plots use CFA-domain distillates (<image>-sensor-profiles.npz), produced by make_sensor_profiles.py from full-resolution exports of the raw through white balance + highlight reconstruction only, with demosaicing set to photosite color passthrough and the colour input profile assigned to linear Rec709 so the white-balanced photosite values cross the export untouched. Full resolution and passthrough are both load-bearing : any demosaicing or resampling stage between the module and the plot interpolates across the reconstruction’s steep rims and prints undershoot that reads as false floor violations. The multi-hundred-megabyte TIFF pairs are not stored ; regenerate them from the raws with the patched sidecars the script’s header describes. The visual tiles and edge metrics use <image>-current.tif, each photograph’s own development history (its .xmp sidecar) with one surgical change : every highlights history entry has its parameters replaced by the stock harmonic-transposition defaults before exporting. The sidecars of these test images carry years of interactive experiments, and their active highlights entry is not necessarily the shipped mode — exporting them unpatched silently benchmarks whatever mode the last darkroom session left behind.

Performance numbers are machine-dependent by nature : the protocol (full ansel-cli export, wall-clock minimum of three runs, idle machine) is stated with the tables, and the timing harness is bench_gl_vs_ht.py in the research repository.

  1. PDF .

Acknowledgments

I would like to thank Ricky Moon for having sponsored the Claude Max subscription that allowed to use Claude Fable 5 to do the bulk of this work. It would have taken months, if not a year to achieve all that without the boost given by AI.


Translated from English by : Claude. In case of conflict, inconsistency or error, the English version shall prevail.

  1. Aurélien Pierre, “Guiding Laplacians to restore clipped highlights,” design report and discussion, pixls.us community forum, 2021. URL ↩︎ ↩︎

  2. In the Ansel source tree, src/iop/highlights_harmonic.h (included by src/iop/highlights.c), with the CPU/GPU parity self-tests in src/iop/highlights_selftests.h. Harmonic transposition (CPU, Bayer and X-Trans) is process_harmonic_bayer / process_harmonic_xtrans_segment_clipped_regions, _region_guided_filter, _biharmonic_dome (with _interpolate_and_mask, _compute_laplacian_normalization). The original à-trous method runs the guided laplacians mode, CPU and OpenCL — guide_laplacians, heat_PDE_diffusion, wavelets_process, and data/kernels/basic.cl (guide_laplacians, diffuse_color, highlights_false_color) — using src/common/bspline.h (B_SPLINE_SIGMA, B_SPLINE_TO_LAPLACIAN, equivalent_sigma_at_step). ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  3. Kaiming He, Jian Sun, and Xiaoou Tang, “Guided Image Filtering,” IEEE Transactions on Pattern Analysis and Machine Intelligence, 35(6), 1397-1409, 2013. DOI: 10.1109/TPAMI.2012.213 . Originally in ECCV 2010↩︎ ↩︎ ↩︎

  4. Chuan Qin, Shuozhong Wang, and Xinpeng Zhang, “Simultaneous inpainting for image structure and texture using anisotropic heat transfer model,” Multimedia Tools and Applications, 56(3), 469-483, 2012. DOI: 10.1007/s11042-010-0601-4 ↩︎ ↩︎ ↩︎

  5. Y. Oono and S. Puri, “Computationally efficient modeling of ordering of quenched phases,” Physical Review Letters, 58(8), 836-839, 1987. DOI: 10.1103/PhysRevLett.58.836 ↩︎ ↩︎

  6. M. Patra and M. Karttunen, “Stencils with isotropic discretization error for differential operators,” Numerical Methods for Partial Differential Equations, 22(4), 936-953, 2006. DOI: 10.1002/num.20129 ↩︎ ↩︎

  7. Aurélien Pierre, “Rotation-invariant Laplacian for 2D grids,” 2021, which derives the 9-point stencil, the B-spline Gaussian-equivalent $\sigma_B$, and the difference-of-Gaussians to Laplacian normalization constant used as B_SPLINE_TO_LAPLACIAN. URL ↩︎ ↩︎ ↩︎ ↩︎

  8. Michael Unser, “Splines: A Perfect Fit for Signal and Image Processing,” IEEE Signal Processing Magazine, 16(6), 22-38, 1999. DOI: 10.1109/79.799930 ↩︎

  9. Holger Dammertz, Daniel Sewtz, Johannes Hanika, and Hendrik P.A. Lensch, “Edge-Avoiding À-Trous Wavelet Transform for fast Global Illumination Filtering,” Ulm University, ↩︎

  10. The local-affine “color-line” prior — within a small patch, a surface’s colour channels are affinely related. Canonical sources: Ido Omer and Michael Werman, “Color Lines: Image Specific Color Representation,” CVPR 2004; and the matting Laplacian of Anat Levin, Dani Lischinski, and Yair Weiss, “A Closed-Form Solution to Natural Image Matting,” IEEE TPAMI 30(2), 228-242, 2008, DOI 10.1109/TPAMI.2007.1177 . The related “Colorization using Optimization” (SIGGRAPH 2004, DOI 10.1145/1015706.1015780 ) uses a softer intensity-affinity prior. ↩︎ ↩︎

  11. The near-saturation nonlinearity of image sensors is standard characterization knowledge : J. R. Janesick, Photon Transfer: DN → λ, SPIE Press, 2007 (gain and noise are measured at the low-illumination end because linearity degrades approaching full well) ; the EMVA 1288 standard (European Machine Vision Association) restricts its linearity regression to 0–70 % of saturation for the same reason ; F. Wang and A. J. P. Theuwissen, “Linearity analysis of a CMOS image sensor,” Electronic Imaging, 2017, details the pixel-chain mechanisms (source-follower gain, voltage-dependent photodiode capacitance). URL . The magnitude of the bias on a given camera is measured from the image itself by the knee estimator ; see the figure in the knee section. ↩︎