5.21. Schalen, spiegelen en bijsnijden¶
De vorige deelparagrafen werkten allemaal op pixels op dezelfde posities waar ze begonnen. De familie transform verandert dat. Schalen stuurt elke invoerpixel naar een andere uitvoerpositie, mogelijk naar meerdere uitvoerposities tegelijk (bij opschalen) of naar een positie die met meerdere andere invoerpixels wordt gedeeld (bij neerschalen). Spiegelen en roteren doen hetzelfde via een andere afbeelding. Bijsnijden behoudt een rechthoekige subset van invoerpixels en verwijdert de rest.
De image-module stelt die familie beschikbaar via drie methoden die de meeste van hun argumenten en het meeste van hun gedrag delen:
copy()– produceer een kopie van de afbeelding, eventueel geschaald, bijgesneden of heroriënteerd.crop()– dezelfde bewerking alscopy, maar met de verwachting dat de toepassing een deelrechthoek uit de bron gaat kiezen.scale()– opnieuw hetzelfde, met de verwachting dat de toepassing het resultaat van grootte gaat veranderen.
De drie delen dezelfde argumenten en dezelfde transformatiemachinerie; het verschil is waar het resultaat standaard terechtkomt. copy() produceert een nieuwe afbeelding, terwijl crop() en scale() de bron ter plaatse wijzigen.
5.21.2. Interpolatie: AREA, BILINEAR, BICUBIC¶
Wanneer schalen elke uitvoerpixel naar een positie stuurt die niet uitlijnt met een enkele invoerpixel, moet de methode kiezen welke waarde te schrijven. Drie vlaggen bepalen hoe:
image.BILINEAR interpoleert tussen de vier dichtstbijzijnde invoerpixels, gewogen naar hun afstand tot de uitvoerpositie. Het resultaat is gladder dan nearest-neighbour, zonder zichtbare kartels op diagonale lijnen, maar de extra rekenkundige bewerkingen kosten ongeveer vier keer zoveel als de nearest-neighbour-doorgang. De juiste keuze voor de meeste opschalingswerkzaamheden en voor elke niet-gehele schaalfactor.
image.BICUBIC interpoleert tussen de zestien dichtstbijzijnde invoerpixels met behulp van een kubieke curve, wat nog gladdere resultaten produceert ten koste van opnieuw meer rekenkundige bewerkingen. Beste kwaliteit voor de kostengevoelige toepassingen die het nodig hebben; zelden de extra berekening waard voor live frames die de IDE alleen maar zal weergeven.
image.AREA middelt elke invoerpixel die binnen de voetafdruk van de uitvoerpixel valt – het juiste algoritme voor neerschalen. Bilineair en bicubisch zijn interpolatoren: ze schatten een waarde tussen bronpixels in, wat opschalen nodig heeft, maar bij neerschalen bestrijkt elke uitvoerpixel veel bronpixels en leest een interpolator alleen de paar dichtstbijzijnde ervan – het detail dat het overslaat komt terug als aliasing. image.AREA vouwt in plaats daarvan elke bestreken pixel in het gemiddelde.
Het standaard schaalalgoritme zonder enige hint is nearest-neighbour, wat het goedkoopste is en het juiste antwoord wanneer de bron al op de pixelresolutie van de bestemming is.
5.21.3. Oriëntatie: spiegelingen en rotaties¶
De oriëntatievlaggen zijn een kleine set booleaanse transformaties die vrij met elkaar en met de interpolatievlaggen samenstellen:
image.VFLIPspiegelt de afbeelding verticaal (boven wordt onder).image.HMIRRORspiegelt haar horizontaal (links wordt rechts).image.TRANSPOSEverwisselt de x- en y-as (rijen worden kolommen).
De meeste rotaties ontstaan door het samenstellen van die drie. De module stelt ook benoemde snelkoppelingen beschikbaar:
image.ROTATE_90(=VFLIP | TRANSPOSE)image.ROTATE_180(=HMIRROR | VFLIP)image.ROTATE_270(=HMIRROR | TRANSPOSE)
In code:
img.copy(hint=image.ROTATE_90, copy_to_fb=True)
5.21.4. Verhoudingsverwerking¶
Wanneer de beeldverhouding van de bron niet overeenkomt met de rechthoek waarin deze wordt getekend, bepalen drie vlaggen wat er met de discrepantie moet gebeuren:
image.SCALE_ASPECT_KEEP behoudt de beeldverhouding van de bron en voorziet het resultaat van letterboxing – de bron wordt geschaald totdat deze in de bestemming past, waarbij lege (nul-)pixels de rest van de bestemming opvullen. De juiste keuze wanneer het onvervormd houden van de bron belangrijker is dan het opvullen van de hele uitvoer.
image.SCALE_ASPECT_EXPAND behoudt de beeldverhouding van de bron en snijdt deze bij – de bron wordt geschaald totdat deze de bestemming opvult, waarbij de delen die buiten de bestemming uitsteken worden afgesneden. De juiste keuze wanneer het opvullen van de hele uitvoer belangrijker is dan het zien van elk deel van de bron.
image.SCALE_ASPECT_IGNORE negeert de beeldverhouding en rekt de bron uit om de bestemming op te vullen, waarbij elke vervorming die dat introduceert wordt geaccepteerd. De juiste keuze wanneer de toepassing al rekening heeft gehouden met de vervorming – bijvoorbeeld wanneer de afmetingen van de bestemming niet daadwerkelijk een rechthoek van dezelfde scène zijn.
De standaardwaarde (geen verhoudingsvlag ingesteld) is hetzelfde als SCALE_ASPECT_IGNORE: uitrekken om op te vullen. Toepassingen die om de beeldverhouding geven, specificeren expliciet een van de drie.
5.21.5. Wanneer welke te gebruiken¶
De meeste formaatwijzigingen gebruiken scale() met een x_scale / y_scale-paar en een interpolatiehint:
img.scale(x_scale=0.5, y_scale=0.5, hint=image.AREA)
De meeste rotaties gebruiken dezelfde aanroep met hint=image.ROTATE_90 of vergelijkbaar.
Bijsnijden gebruikt crop() met een niet-standaard roi:
img.crop(roi=(40, 30, 200, 150))
Wanneer de bron de bewerking moet overleven – het vastleggen van een referentieframe, het maken van een miniatuur van een frame dat op het punt staat destructief te worden verwerkt – produceert copy() het resultaat als een nieuwe afbeelding en laat de bron onaangeroerd:
thumbnail = img.copy(x_scale=0.25, y_scale=0.25, hint=image.AREA)
Die standaardwaarde is het echte verschil achter de drie namen: scale en crop transformeren ter plaatse, copy reserveert. De sleutelwoorden voor resultaatplaatsing overbruggen het gat: copy=True op scale of crop reserveert het resultaat als een afzonderlijke heapbuffer in plaats van de bron te overschrijven, en copy_to_fb=True op een van de drie laat het in de framebuffer landen voor de IDE-voorvertoning.