5.19. Tonale correcties¶
Tonale correcties veranderen hoe helderheid en kleur verdeeld zijn in een vastgelegde afbeelding – de aanpassingen die een toepassing toepast wanneer een frame te donker, te helder, te vlak of scheefgetrokken naar de verkeerde kleur is.
De correcties vallen uiteen in twee families: helderheids- en contrastaanpassingen die de helderheid herverdelen, en kleuraanpassingen die veranderen als welke kleur elke pixel wordt afgelezen. Beide hebben tegenhangers in de ISP van de sensor, die elk frame onderweg naar binnen corrigeert; de methoden hier zijn van toepassing op een al vastgelegde Image, achteraf, voor de gevallen waarin het frame meer correctie nodig heeft dan de ISP leverde.
5.19.1. Histogramegalisatie¶
De eenvoudigste contrast-verbredende bewerking is histogramegalisatie. Het idee is om pixelwaarden opnieuw toe te wijzen zodat het histogram van de uitvoer zo vlak mogelijk is – elke waarde komt ongeveer even vaak voor. Het visuele effect is dat een afbeelding met laag contrast (een waarvan het histogram geconcentreerd is in een smalle band) een afbeelding met hoog contrast wordt waarvan de pixels het volledige bereik 0 – 255 beslaan.
histeq() voert de egalisatie uit:
img.histeq()
Het mechanisme is rechtstreeks. De cumulatieve verdelingsfunctie (CDF) van het histogram van de bron wordt berekend; elke invoerpixelwaarde wordt toegewezen aan zijn positie in de CDF, geschaald naar het uitvoerbereik. Waar pixels al gelijkmatig verspreid waren, ligt de toewijzing dicht bij de identiteit; waar pixels zich opstapelden bij één helderheid, spreidt de toewijzing ze uit door die helderheid over een breder bereik van uitvoerwaarden te rekken.
Het resultaat is dramatisch bij scènes met laag contrast – het verschil tussen een schemerige foto binnenshuis en dezelfde foto na histeq is vaak het verschil tussen “onleesbaar” en “perfect leesbaar.” De afweging is dat de bewerking alles versterkt, inclusief sensorruis. Bij een scène met echte detaillering in laag contrast die hersteld moet worden, is histeq het juiste antwoord; bij een schone, goed belichte scène die het simpelweg niet nodig heeft, introduceert histeq zichtbare ruis.
5.19.2. CLAHE: adaptieve egalisatie¶
Histogramegalisatie is globaal: het gebruikt één CDF berekend uit de hele afbeelding en past deze overal toe. Dat werkt op afbeeldingen waarvan het helderheidsbereik ongeveer uniform is, maar faalt bij scènes met gelokaliseerde donkere en heldere gebieden – de CDF wordt getrokken naar de zijde die meer pixels heeft, en de tegenovergestelde zijde wordt overgecorrigeerd.
De adaptieve variant is Contrast Limited Adaptive Histogram Equalisation, gewoonlijk CLAHE genoemd. In plaats van één globale CDF berekent CLAHE een afzonderlijke CDF voor elke kleine tegel van de afbeelding, egaliseert elke tegel tegen zijn eigen CDF, en mengt de tegelranden in elkaar. Het resultaat is dat helderheidsaanpassingen lokaal plaatsvinden – de schaduwrijke hoek krijgt zijn eigen egalisatie zonder dat de heldere hoek hem de verkeerde kant op trekt.
De vlag adaptive=True schakelt histeq() om naar de CLAHE-modus:
img.histeq(adaptive=True, clip_limit=10)
De parameter clip_limit is het deel van CLAHE waar de “contrast limited” in de naam naar verwijst. Lokale egalisatie kan ruis te veel versterken in vlakke gebieden waar de CDF zeer weinig verschillende waarden heeft; de cliplimiet begrenst hoe agressief een enkele bin kan worden herverdeeld, wat de ruisversterking voorkomt terwijl de contrastverbreding waar het ertoe doet toch wordt toegestaan. Een waarde rond 10 is een redelijk startpunt; grotere waarden laten CLAHE harder werken ten koste van meer zichtbare ruis, kleinere waarden maken het zachter.
CLAHE is duurder dan de globale histeq, maar levert schonere resultaten op scènes waar de helderheid ongelijkmatig verdeeld is – wat de meeste echte scènes zijn.
5.19.3. Gamma, contrast en helderheid¶
Histogramegalisatie is de datagedreven manier om helderheid opnieuw toe te wijzen. De data-onafhankelijke manier is om een gekozen curve toe te passen, geparametriseerd door een paar gemakkelijk af te stellen knoppen. gamma() biedt er drie:
img.gamma(gamma=1.0, contrast=1.0, brightness=0.0)
Elke parameter past één specifieke transformatie toe op elke pixel:
gamma haalt de waarde van elke pixel door de machtsfunctie output = input ** (1 / gamma). De standaardbetekenis: waarden groter dan 1.0 verhelderen de afbeelding en lichten middentonen op (de klassieke “monitor gamma”-correctie); waarden kleiner dan 1.0 verdonkeren deze. De parameter is niet-lineair – hij behoudt de zwart- en witpunten en hervormt alleen de verdeling daartussen, wat het juiste gedrag is wanneer het doel is om detail in schaduw- of hooglichtgebieden te herstellen zonder de bestaande extremen te pletten.
contrast haalt elke pixel door een rechte vermenigvuldiging rond het middengrijs-punt. Waarden groter dan 1.0 verhogen het contrast (donker wordt donkerder, helder wordt helderder, middengrijs blijft hetzelfde); waarden kleiner dan 1.0 verlagen het contrast.
brightness voegt een constante toe aan elke pixelwaarde. Positieve waarden verhelderen, negatieve waarden verdonkeren. De verschuiving is uniform – er wordt niets behouden – wat zelden is wat een toepassing op zichzelf wil, maar goed samengaat met een contrastpas om het resultaat opnieuw te centreren.
De drie parameters stellen zich samen: een enkele aanroep van gamma() kan een gammacurve toepassen, dan een contrastvermenigvuldiging, dan een helderheidsverschuiving, alles in één pas. De volgorde is eerst gamma, dan contrast, dan helderheid, wat overeenkomt met de volgorde die de meest intuïtieve resultaten geeft wanneer alle drie niet-standaard zijn.
5.19.4. Automatische witbalans¶
De kleurfamilie van tonale correcties begint met automatische witbalans. Hetzelfde mechanisme dat de ISP van de sensor uitvoert als onderdeel van de beeldverwerkingspijplijn – het aanpassen van de relatieve versterkingen op de rode, groene en blauwe kanalen zodat een gemiddeld grijsgekleurd vlak als daadwerkelijk grijs wordt afgelezen – is ook beschikbaar als bewerking na het vastleggen op een voltooide Image:
img.awb()
De standaard gebruikt het gray-world-algoritme: de gemiddelde kleur van de hele afbeelding wordt verondersteld neutraal grijs te zijn, en de versterkingen per kanaal worden aangepast om dat zo te maken. De alternatieve vorm max=True gebruikt het white-patch-algoritme: de helderste pixels worden verondersteld neutraal wit te zijn, en de versterkingen worden aangepast om ze zo te maken. Beide werken op RGB565 en op ruwe Bayer; geen van beide werkt op grijswaarden (waar geen kleur is om te balanceren) of YUV (waar de kleurrepresentatie niet is waar deze algoritmen op werken).
Wanneer je naar de vorm na het vastleggen grijpt in plaats van de automatische witbalans van de ISP: wanneer de keuze van de ISP slecht paste bij de specifieke scène, wanneer de toepassing referentieframes van schijf laadt die onder andere omstandigheden zijn vastgelegd, of wanneer het kleuroordeel genoeg telt dat de toepassing het opnieuw wil uitvoeren met zijn eigen keuze van algoritme.
5.19.5. De kleurcorrectiematrix¶
Wanneer de kleurcorrectie die de afbeelding nodig heeft niet de schaling per kanaal is die witbalans geeft, maar een meer algemene kanaalmenging, is de bewerking om naar te grijpen de kleurcorrectiematrix. De methode ccm() past een 3-bij-3-matrix (of 3-bij-4 met offset) toe die de (r, g, b)-vector van elke pixel vermenigvuldigt om een nieuwe (r, g, b)-vector te produceren:
img.ccm([[1.1, -0.05, -0.05],
[-0.05, 1.1, -0.05],
[-0.05, -0.05, 1.1]])
De matrix laat de toepassing overspraak tussen de kleurkanalen corrigeren – waar bijvoorbeeld de respons van de rode sensor wat groen licht bevat, kan de matrix een fractie van het groene kanaal aftrekken van de rode uitvoer om te compenseren. Gecombineerd met een offset per kanaal laat de 3-bij-4-vorm de toepassing ook elk kanaal opnieuw op nul zetten.
Het materiaal over de ISP-pijplijn behandelt het waarom van kleurcorrectiematrices. De vorm na het vastleggen op de Image is gewoon dezelfde bewerking, achteraf toegepast.