3. diel - Práca s pixelmi a operácie s obrázkami v Pythone
V minulej lekcii, Práca s videom v Pythone a kreslenie a písanie do obrázkov , sme si ukázali, ako načítať a uložiť video a ako kresliť rôzne tvary a text na obrázky. V dnešnom Python tutoriále si ukážeme, ako pracovať s pixelmi a vykonávať aritmetické operácie s obrázkami.
Práca s pixely
Z predchádzajúcich lekcií už vieme, že video sa skladá z jednotlivých snímke / obrázkov, ktoré sa skladajú z pixelov a tie sú usporiadané v 2D listu.
Ako vždy budem v ukážkach používať obrázok nižšie:
Najskôr si obrázok načítame:
import cv2 import numpy as np img = cv2.imread("letadlo.jpg")
Zmena farby pixelu
Vypíšeme si farbu pixelu, ktorý sa nachádza na pozíciu
250x330
. V numpy sa index u viacrozmerných polí rozdeľuje
pomocou začiatku ,
:
print(img[250, 330])
Farbu bodu skúsime tiež zmeniť a obrázok znovu vykresliť:
print(img[250, 330]) img[250, 330] = [255,255,255] print(img[250, 330]) cv2.imshow("obrazek", img) cv2.waitKey() cv2.destroyAllWindows()
Uistíme sa, že sa farba naozaj zmenila.
Zmena farby oblasti v obrázku
Takto môžeme zmeniť farbu vybranej časti obrázka a nie len jednému
pixelu. Nižšie vyberieme oblasť od bodu [250:500]
do bodu
[330:600]
:
img[250:500, 330:600] = [255,255,255] cv2.imshow("obrazek", img) cv2.waitKey() cv2.destroyAllWindows()
Pri indexovanie môžeme použiť jednu z nasledujúcich hodnôt:
img.size
- počet bodov v obrázku (pri obrázku lietadla =2980680
)img.shape
- rozmery obrázku a počet farebných zložiek (pri obrázku lietadlá =(842, 1180, 3)
)- Ak chceme poznať dátový typ obrázku, zistíme ho pomocou
img.dtype
Teraz si skúsime skopírovať vybrané pixely a vložiť ich na ľubovoľnú pozíciu:
img[200:300, 500:600] = img[400:500, 200:300]
výsledok:
Aritmetické operácie s obrázkami
Aby sme si mohli ukázať aritmetické operácie s obrázkami, potrebujeme druhý obrázok. Ja použijem tento:
Najprv skúsime pole pixelov obrázkov sčítať:
letadlo = cv2.imread("letadlo.jpg") kocka = cv2.imread("kocka.jpg") kocka = kocka[:letadlo.shape[0], :letadlo.shape[1]] img = letadlo + kocka cv2.imshow("obrazek", img) cv2.waitKey() cv2.destroyAllWindows()
Keďže obrázok s mačkou je väčší, musíme ho prispôsobiť veľkosti
lietadla pomocou
kocka = kocka[:letadlo.shape[0], :letadlo.shape[1]]
. Potom ich
jednoducho sčítame pomocou img = letadlo + kocka
.
Toto sa nám úplne nevydarilo, pretože len tak 2 obrázky sčítať
nemôžeme. Obrázok je strašne svetlý, pretože pri sčítaní pixelov, napr.
Hodnôt [150, 200, 230] + [50, 80, 140]
nám vyjde
[200, 280, 370]
, čo sa oreže na maximálne hodnoty
[200, 255, 255]
.
Aby sme tomuto predišli, obrázky do seba preženú funkcií
cv2.addWeighted(obrázek1, poměr/váha obrázku1, obrázek2, poměr/váha obrázku2, gamma)
:
img = cv2.addWeighted(letadlo, 0.4, kocka, 0.75, 0)
Výsledok je oveľa pôsobivejšie:
Obrázok je ale stále pomerne svetlý, preto nastavíme hodnotu gamma na
-100
:
img = cv2.addWeighted(letadlo, 0.4, kocka, 0.75, -100)
Výsledný obrázok vyzerá oveľa lepšie
Vloženie obrázku do obrázka bez prelínanie
Na záver si ukážeme pre nás pomerne náročnú operáciu, kedy vložíme jeden obrázok do druhého bez prelínanie. Ako ukážku si vložíme logo ITnetworku do obrázka s lietadlom. Logo je nasledujúci obrázok typu PNG:
Na lietadlo ho vložíme tak, aby bola biela farba priehľadná. Uveďme si najprv kompletný zdrojový kód, ktorý si vzápätí popíšeme:
letadlo = cv2.imread("letadlo.jpg") itn = cv2.imread("itn.png") region = letadlo[ 0:itn.shape[0], 0:itn.shape[1] ] itn_seda = cv2.cvtColor(itn, cv2.COLOR_BGR2GRAY) ret, maska = cv2.threshold(itn_seda, 150, 255, cv2.THRESH_BINARY_INV) maska_inv = cv2.bitwise_not(maska) letadlo_bg = cv2.bitwise_and(region, region, mask = maska_inv) itn_bez_bg = cv2.bitwise_and(itn, itn, mask = maska) logo_celek = cv2.add(letadlo_bg, itn_bez_bg) letadlo[ 0:itn.shape[0], 0:itn.shape[1] ] = logo_celek
Najskôr si definujeme región v obrázku lietadlo, kam logo vložíme. My ho
vložíme do ľavého horného rohu, región teda bude
region = letadlo[ 0:itn.shape[0], 0:itn.shape[1] ]
. Logo prevedieme
z farebného na šedej pomocou
itn_seda = cv2.cvtColor(itn, cv2.COLOR_BGR2GRAY)
, aby sme neskôr
mohli oddeliť pozadie. Vytvoríme masku, ktorá nám oddelí biele pozadie ako
cv2.threshold(obrázek, práh, maximální hodnota, typ operace)
.
Táto funkcia prevedie pixely buď na čierne alebo biele. Potom použijeme
bitovou operáciu a vytvoríme tak ďalšie masku s opačnou hodnotou
maska_inv = cv2.bitwise_not(maska)
. Aplikujeme
maska_inv
na vybraný región z obrázku lietadlo ako
letadlo_bg = cv2.bitwise_and(region, region, mask = maska_inv)
.
Potom aplikujeme maska
na logo pomocou bitovej operácie, tým sa
zbavíme pozadí
itn_bez_bg = cv2.bitwise_and(itn, itn, mask = maska)
a nakoniec
logo vložíme do obrázka ako
letadlo[ 0:itn.shape[0], 0:itn.shape[1] ] = logo_celek
.
Na bitové operácie a thresholding sa pozrieme podrobnejšie v nasledujúcich lekciách
Zdrojový kód nájdete na stiahnutie v prílohe článku. V budúcej lekcii, Thresholding a analýza obrázkov v Pythone , si vysvetlíme ako funguje thresholding a na čo je vlastne dobrý.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 38x (520.98 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Python