Pilditöötlus
Siin peatükis saab tutvuda pilditöötlusega ning tööriistadega, mis Pythonis selle tarvis on. Selle jaoks antakse kõigepealt ülevaade värvimudelitest ning selgitatakse, millised on levinud pildivormingud ning mille poolest nad erinevad.
Ettevalmistus
Juhend eeldab, et oled tutvunud Pythoni järjenditega. Enne alustamist tuleks paigaldada PIL-nimeline teek käsuga pip install Pillow
. Vajadusel loe läbi õpikus moodulite paigaldamise juhised.
Värvimudelid
Juba õige ammu märgati, et kõiki värve, mida inimese silm eristab, on võimalik kokku panna kolmest põhivärvist: sinine, punane ja kollane. Seda nimetatakse subtraktiivseks värvimudeliks, sest valge saamiseks peab värve mustast "lahutama" ja kõiki värve kokku pannes saab musta. Iga põhivärvi kogust võib numbriliselt väljendada skaalal 0-100, nii et näiteks halle toone kirjeldavad sellised segud, kus kõiki värve on võrdselt. Teoorias oleks keskmiselt hall toon segu (50, 50, 50) ja must oleks segu (100, 100, 100), aga kuna saadaolevate värvide kvaliteet varieerub, võib praktikas värve segades tihti saada hoopis tumepruuni.
CMYK
Tänapäeva printerid kasutavad samasugust tuttavat värvimudelit, kuigi on leitud, et täpsema tulemuse jaoks on parem kasutada põhivärvidena tsüaansinist, magentapunast ja kollast. Selle mudeli nimi on CMYK
(Cyan-Magenta-Yellow-Key), kus viimase värvina on lisatud key ehk "võtmevärv" must. Viimane lisati juurde, sest avastati, et kui üritada paberile printides musta saamiseks teisi tinte maksimaalses koguses segada, siis on tulemuseks natuke vettinud välimusega kole paber ja üsna mitterahuldav värvitoon.
RGB ja RGBA
Ekraanid seevastu kasutavad RGB
(Red-Green-Blue) värvimudelit, mis on aditiivne mudel ehk valge saamiseks tuleb kõik kolm erinevat värvi valgust liita (must on pimedus!). RGB
-mudelis on põhivärvide intensiivsused tavaliselt skaalal 0-255, nii et ühe piksli värvi salvestamiseks piisab täpselt kolmest baidist (255 on suurim arv, mis ühte baiti mahub). Lühema kirjapildi huvides kirjutatakse RGB
värve tihti ka kuueteistkümnendkoodidena, kus prefiks on #:
Värv | R | G | B | Vastav heksakood |
---|---|---|---|---|
Must | 0 | 0 | 0 | #000000 |
Valge | 255 | 255 | 255 | #ffffff |
Punane | 255 | 0 | 0 | #ff0000 |
Roheline | 0 | 255 | 0 | #00ff00 |
Sinine | 0 | 0 | 255 | #0000ff |
Lilla | 127 | 0 | 127 | #7f007f |
Pruun | 165 | 42 | 42 | #a52a2a |
RGBA
mudelis on lisatud neljandaks alfakanal, mis määrab kui läbipaistev piksel on (0 = täiesti läbipaistev). See lihtsustab näiteks üleminekute ja varjude loomist veebikujunduses.
LAB
LAB
mudelis on L (lightness) heleduse telg, A (alfa) on sinine-kollane telg ja B (beeta) on roheline-punane telg. See mudel kirjeldab kõige paremini seda, kuidas inimese silm värve näeb ja seega saab sellega kõige rohkem erinevaid silmale nähtavaid värve väljendada. Samuti annavad mitmed teisendused seda mudelit kasutades silmale loomulikuma tulemuse, näiteks pildi värvide pööramine:
Mustvalge või monokroomne
Mustvalges või ühevärvilises värvimudelis on ainult heleduse telg - üks täisarv määrab, kui hele või tume piksel on. Mustvalge värvimudel võib olla ka ainult kahevärviline, nii et ühe bitiga saab määrata, kas piksel on must või valge.
Teised mudelid
On veel mitmeid teisi mudeleid. Pilditöötlusprogrammides võib kokku puutuda hue (värvitoon), saturation (küllastus) ja brightness (heledus) väärtustega. Need parameetrid moodustavad HSB
värvimudeli, kus H ehk hue on olemuselt värviratas - selle võimalikud väärtused on skaalal 0-360. Küllastus ja heledus on kumbki skaalal 0-100.
Vaata ka https://docs.python.org/3/library/colorsys.html
Järgmiselt lingilt leiab kõik värvimudelid (või režiimid), mis teegis PIL
kasutatavad on: https://pillow.readthedocs.io/en/stable/handbook/concepts.html#modes
Harmooniline disain
Raamatute, ajakirjade, riiete, kasutajaliideste ja arvutimängude disainimisel on mõistlik arvestada sellega, kuidas värvid ja nende kombinatsioonid inimestele mõjuvad. Sellega tegeleb värviteooria, kuigi süvitsi me seda siin peatükis uurima ei hakka. Kasulik on teada, et hea värvikompositsioon on harmooniline ja harmooniaid ehk värvikõlasid on erinevaid. Näiteks moodustavad värvikõla kõrvuti asetsevad värvid, ühe värvitooni variatsioonid, aga ka vastandvärvid.
Harmooniad valitakse tavaliselt värviratta abil, mis on sisuliselt ringikujuliselt joonistatud värvispekter. Kõigepealt paigutatakse ringile põhivärvid, seejärel iga kahe põhivärvi vahele nende segu. Nii on lihtne leida vastandvärve - need on alati 180° kaugusel ehk ringi vastaspoolel! Igas värvimudelis ei teki samad harmooniad, sest põhivärvid ja seega ka värviringid on erinevad. Erinevaid värvikõlasid saad valida siin: https://www.sessions.edu/color-calculator/.
Pildifailid ja -vormingud
Pildiformaadid on erineva otstarbega, mõnda kasutatakse veebis graafika kuvamiseks, teised sobivad paremini näiteks printimiseks. Mõned on loodud väiksema faili suuruse saavutamiseks faili kvaliteedi või värvivaliku arvelt.
Joint Photographic Experts Group (.jpeg .jpg)
Paljud digitaalkaamerad salvestavad pilte JPEG-vormingus. Pildid pakitakse kadudega, et failisuurust väiksemana hoida, mis tähendab, et iga kord, kui pilti pärast muutmist salvestatakse, kaob mingi hulk infot. Tihti ei paista see pilti vaadates silmagi, aga korduvalt JPEG-faile muutes ja salvestades võib detaile kaduma minna.
Portable Network Graphics (.png)
.png
on kõige populaarsem vorming, millega veebis graafikat kuvatakse, sest see talletab infot kadudeta ning sellega on võimalik salvestada ka läbipaistvusega piksleid. PNG-failid salvestavad infot RGBA värvimudeli abil ja ühe piksli kohta info salvestamiseks kasutatakse maksimaalselt 64 bitti (värvisügavus = 4*16 bitti). Ühel pildil võib seega kasutada kuni 2**64 erinevat värvitooni (erinevad läbipaistvusastmed kaasa arvatud).
Graphics Interchange Format (.gif)
GIF-vorming on PNG-vormingu eelkäija ja suudab salvestada pilte kuni 256 vabalt valitud värviga, kusjuures iga piksel võib olla ka täiesti läbipaistev. Lisaks toimib GIF-fail piltide jadana - ühte faili saab salvestada mitu pilti, nii et tulemuseks on animeeritud pilt. Pikemate videote salvestamiseks seda siiski ei kasutata, sest paljude kaadritega GIF-fail muutub ruttu väga mahukaks ning selle kuvamine võtab kaua aega. Kuna PNG animeeritud variandid pole populaarseks saanud, siis kasutataksegi animeeritud pildikeste jaoks GIF-vormingut.
Bitmap (.bmp .dib)
BMP-faile ei pakita, seega kipuvad nad päris suured olema. Samas on programmidel neid lihtne lugeda, sest faili sisu ei pea kuidagi lahti pakkima (teisendama). Üks pilt võib kulutada kuni 32-bitti piksli kohta ja peamiselt kasutab seda vormingut Windowsi operatsioonisüsteem.
Scalable Vector Graphics (.svg)
Eelnevalt vaatasime rastergraafika formaate, kus igal pikslil on mingi värviväärtus. Vektorgraafika on pigem objektorienteeritud - pilt koosneb võrrandite abil kirjeldatud kujunditest ja joonistamisinstruktsioonidest. SVG-fail on tegelikult XML-struktuuriga fail, mis võib sisalda ka CSS-elemente (loe viimaste kohta lähemalt veebisisu parsimise peatükist) ning seda pakitakse ilma detaile kaotamata - pildi detailsust saab reguleerida muutmise ajal. Eeliseks on see, et pilte saab skaleerida ilma kvaliteeti kaotamata, samas on realistlikke kujutisi ja fotosid keeruline täpselt salvestada, kuna nende kirjeldamiseks on vaja väga palju objekte. Vorming sobib hästi kaartide ja logode tegemiseks.
Enesekontrolliküsimused
Pilditöötlusteek PIL
Pythonis on rastergraafika piltidega ümber käimiseks võimalik kasutada teeki PIL
(Pillow). See koosneb mitmest moodulist, mille täieliku nimekirja leiab dokumentatsioonist: https://pillow.readthedocs.io/en/stable/reference/. Vaatame mõningaid:
Image
- Põhimoodul. SisaldabImage
klassi ja muud vajalikku piltide avamiseks, salvestamiseks, töötlemiseks.ImageChops
- Matemaatilised või loogilised operatsioonid piltidega (pikslimaatriksitega).ImageColor
- Funktsioonid värvikoodide teisendamiseks mõnda teise värvisüsteemi.ImageDraw
- Pildile joonistamise ja kirjutamise funktsioonid.ImageEnhance
- Klassid, mille abil saab pildi värvitasakaalu, kontrasti, heledust ja teravust reguleerida.ImageFilter
- Erinevad pilditeisendused ja nende koostamise vahendid.ImageOps
- Sisaldab rohkem kõrgetasemelisi pilditeisendusfunktsioone.ImageSequence
- Animeeritud piltide itereerimiseks.ImageTk
- Pildiobjektide teisendamiseks mooduliTkinter
jaoks sobivasse vormingusse.
Tasub teada, et kui on lisaks vaja videotöötluse, masinnägemise või tehisintellekti vahendeid, on mõistlikum kasutada PIL
asemel openCV teeki.
Failivormingu muutmine
PIL
suudab avada kõiki populaarsetes formaatides pilte ning salvestada neid ümber teise formaati. Kuigi PDF-faile selle abil sisse lugeda ei saa, võimaldab PIL
salvestada pilte PDF-kujul, mis sobib hästi näiteks printimiseks. Järgmine koodilõik demonstreerib, kuidas avada .png laiendiga fail ja salvestada see .jpg vormingusse.
Pildifail: python-logo.png
from PIL import Image img = Image.open("python-logo.png") img = img.convert("RGB") # Võib juhtuda, et mõnda pilti peab teisendama img.save("python-logo.jpg")
img.convert()
on siin vajalik, sest sisendfail on salvestatud RGBA
-režiimis, aga PIL
ei luba JPEG-faile selles režiimis salvestada.
Kuna salvestame JPEG-vormingusse, siis pakitakse pilt kadudega, aga JPEG-piltide puhul saab parameetriga quality
määrata, kui palju infot kaduma läheb. Näiteks img.save("python-logo.jpg", quality=100)
jätab kõik detailid alles, aga siis tuleb fail ka palju suurem kui algne PNG-kujutis.
Piltide kuvamine
Kõige lihtsam on pilte kuvada meetodiga show
, mis peaks avama pildi operatsioonisüsteemi vaikefotovaaturis.
Kui Pythoni mooduli Tkinter
abil teha kasutajaliides, siis saab koos PIL
mooduli ImageTk
abiga seal pilte kuvada:
from tkinter import * from PIL import Image, ImageTk root = Tk() canvas = Canvas(root) img = Image.open("python-logo.png") imgTk = ImageTk.PhotoImage(img) canvas.create_image(100,100,image=imgTk) canvas.grid() root.mainloop()
Lihtsamad teisendused
Järgnev kood teeb Pythoni logo erinevatest teisendustest järjendi ja kuvab iga teisenduse:
from PIL import ImageOps teisendused = [ img.rotate(45, expand=True), # 45-kraadine pööre img.transpose(Image.Transpose.FLIP_TOP_BOTTOM), # Vertikaalne peegeldus img.resize( (img.width//2, img.height//2) ), # Kahekordne vähendus img.crop( (50, 50, img.width-50, img.height-50) ), # Väljalõige keskelt ImageOps.grayscale(img), # Mustvalges värviskaalas ImageOps.invert(img), # Vastandvärvides ImageOps.expand(img, 5, "#00ff00") # Rohelise raamiga ] for t in teisendused: t.show()
Üle pikslite itereerimine
Vahel on kasulik teisenduste kombineerimise asemel lihtsalt üle pildi pikslite itereerida ja ükshaaval muudatusi teha. Näiteks saab arvutada iga piksli kauguse pildi keskpunktist ja jätta alles ainult ringikujuline osa pildist:
centerX, centerY = img.width//2, img.height//2 for x in range(img.width): for y in range(img.height): # Muuda läbipaistvaks, kui piksel on kaugemal kui 55px if (x-centerX)**2 + (y-centerY)**2 > 55**2: img.putpixel((x,y), (0,0,0,0)) img.show()
Filtrid
Moodulist ImageFilter
leiab mitmeid filtreid, mida piltidele rakendada. Need on klasside kujul ning kasutada saab neid nii:
from PIL import ImageFilter img.filter(ImageFilter.CONTOUR).show() img.filter(ImageFilter.EMBOSS).show() img.filter(ImageFilter.BoxBlur(3)).show() img.filter(ImageFilter.MedianFilter(13)).show() img.filter(ImageFilter.MinFilter(7)).show()
CONTOUR | EMBOSS | BoxBlur(3) | MedianFilter(13) | MinFilter(7) |
Kuidas filtrid töötavad?
Eelnevalt kirjeldatud pildifiltreid on võimalik ka ise kokku panna matemaatilistest teisendustest, mida nimetatakse konvolutsioonideks. Tuleb lihtsalt teada, millist maatriksit pildi igale pikslile rakendada, et soovitud tulemus saada. Seejärel tehakse vaadeldavast pikslist ning seda ümbritsevatest pikslitest maatriks. Pikslimaatriksi ja valitud teisendusmaatriksi (kernel) vahel tehakse nüüd maatriksite korrutamisele sarnanev tehe. Näiteks järgneva teisendusmaatriksi abil saab piksli 'e' väärtuseks selle alloleva piksli kolmekordne + ülalasuva piksli kahekordne väärtus.
{$ $}{$
\begin{bmatrix}
a & b & c \\
d & \boldsymbol{\color{green} e} & f \\
g & h & i
\end{bmatrix}
\begin{bmatrix}
0 & 3 & 0 \\
0 & 0 & 0 \\
0 & 2 & 0
\end{bmatrix}
= (i \cdot 0)+(h \cdot 3)+(g \cdot 0)+(f \cdot 0)+(e \cdot 0)+(d \cdot 0)+(c \cdot 0)+(b \cdot 2)+(a \cdot 0)
= \color{green} {3 \cdot h + 2 \cdot b}
$}
Praktikas ei pea neid detaile ilmtingimata teadma, sest klass ImageFilter.Kernel
loob ise vajaliku teisenduse etteantud kerneli ja mõne lisaparameetri põhjal:
# Pildi teravustamise kernel: m_sharpen = [ 0, -.5, 0, -.5, 3, -.5, 0, -.5, 0 ] kernel = ImageFilter.Kernel((3,3), m_sharpen, 1) sharpened = img.filter(kernel) sharpened.show()
Kuma lisamine
Hetkel pole teegis PIL
funktsiooni, millega pildile kuma või varju lisada. Vaatame, kuidas seda siiski teha saab. Tahame näiteks Pythoni logo ümber kuma lisada. Selleks teeme pildist koopia, udustame selle ja kleebime algse logo uduse pildi peale.
Udustamiseks kasutame Gaussi udustamise meetodit. Värvilise kuma asemel varju saamiseks võib neljanda rea välja kommenteerida. Et läbipaistev kuma siin paremini nähtav oleks, kleebitakse ta valge tausta peale. Kleepimisel peaks täpsustama maski, et kogu pildiala üle ei kirjutataks.
from PIL import Image, ImageEnhance, ImageFilter img = Image.open("python-logo.png") img_blurred = img.copy() img_blurred = img_blurred.filter(ImageFilter.GaussianBlur(radius=2)) img_blurred = ImageEnhance.Color(img_blurred).enhance(25) # Teeb varju värvi intensiivsemaks result = Image.new("RGB", (img.width, img.height), (255, 255, 255)) # Valge taust result.paste(img_blurred, mask=img_blurred) result.paste(img, mask=img) result.show()
Seotud kursused
Käsitletud teemadega on põhjalikumalt võimalik tutvuda kursustel "MTAT.03.015 Arvutigraafika" ja "MTAT.03.132 Multimeedia". Pildituvastust, muid masinõppe meetodeid ja teeki openCV
tutvustatakse ka aines "LTAT.01.003 Tehisintellekt".
Enesekontrolliküsimused
Ülesanded
1. Kirjuta funktsioon, mis võtab sisendiks kausta nime ja värvisüsteemi, millesse PIL
salvestada lubab, ning salvestab kõik pildid kaustas ümber sellesse süsteemi. Kui mõnda faili ei õnnestu teisendada, tuleks see vahele fail vahele jätta ja kasutajale teada anda.
2. Koosta programm, mis palub kasutajalt sisendiks pilti ja kuvab siis Tkinteri aknas kaheksa varianti sellest pildist, nii et igaühele on rakendatud mingit teisendust või teisenduste kombinatsiooni. Programm võiks ka lubada ühe teisendatud pildi soovitud nimega salvestada.
Vihje: Pildi avamiseks ja salvestamiseks saad kasutada mooduli tkinter.filedialog
funktsioone askopenfile
ja asksaveasfile
.