Spracovanie obrázkov OpenCV

Spracovanie Obrazkov Opencv



V tomto článku budeme študovať metódy spracovania obrazu. Preskúmame niektoré základné, ale kritické témy v oblasti počítačového videnia a strojového učenia. Tieto základné techniky spracovania obrazu môžu vyriešiť zložité problémy, ako sú súbory údajov. Výsledkom je šesť základných krokov pri spracovaní obrazu, ktoré sú uvedené nižšie:
  1. Preklad obrázkov
  2. Otočenie obrazu
  3. Obrazová aritmetika
  4. Prevracanie obrázkov
  5. Orezanie obrázka
  6. Zmena veľkosti obrázka

Teraz podrobne vysvetlíme všetky vyššie uvedené témy spracovania obrazu.

1. Preklad obrázkov

Preklad obrazu je metóda spracovania obrazu, ktorá nám pomáha posúvať obraz pozdĺž osi x a y. Obrázok môžeme posúvať nahor, nadol, doprava, doľava alebo ľubovoľnou kombináciou.







Prekladovú maticu môžeme definovať symbolom M a môžeme ju reprezentovať v matematickej forme, ako je uvedené nižšie:





Prostredníctvom tohto programu môžeme pochopiť koncept prekladového obrazu.





Python kód: Nasledujúci názov programu zachováme ako translate.py .

# importovať požadované balíky

importovať numpy ako napr.

importovať argparse

importovať imutil

importovať cv2

# implementujeme analyzátor argumentov

ap_obj = argparse. ArgumentParser ( )

ap_obj. pridať_argument ( '-k' , '--obrázok' , požadovaný = Pravda ,

Pomoc = 'umiestnenie obrazového súboru' )

args = ktorých ( ap_obj. parse_args ( ) )

# načítať obrázok a zobraziť ho na obrazovke

obrázok = cv2. imread ( args [ 'obrázok' ] )

cv2. imshow ( 'Original_image' , obrázok )

# Preklad obrázka je matica NumPy, ktorá je uvedená nižšie:

# [[1, 0, shiftX], [0, 1, shiftY]]

# Vyššie uvedenú maticu NumPy použijeme na posunutie obrázkov pozdĺž

# Smery osi x a osi y. Na to musíme jednoducho odovzdať hodnoty pixelov.

# V tomto programe posunieme obrázok o 30 pixelov doprava

# a 70 pixelov smerom dole.

translation_mat = napr. plavák32 ( [ [ 1 , 0 , 30 ] , [ 0 , 1 , 70 ] ] )

image_translation = cv2. warpAffine ( obrázok , translation_mat ,

( obrázok. tvar [ 1 ] , obrázok. tvar [ 0 ] ) )

cv2. imshow ( 'Preklad obrázkov dole a vpravo' , image_translation )

# teraz použijeme vyššie uvedenú maticu NumPy na posunutie obrázkov pozdĺž

# Smery osi x (vľavo) a osi y (hore).

# Tu posunieme obrázky o 50 pixelov doľava

# a 90 pixelov smerom nahor.

translation_mat = napr. plavák32 ( [ [ 1 , 0 , - päťdesiat ] , [ 0 , 1 , - 90 ] ] )

image_translation = cv2. warpAffine ( obrázok , translation_mat ,

( obrázok. tvar [ 1 ] , obrázok. tvar [ 0 ] ) )

cv2. imshow ( 'Preklad obrázkov hore a doľava' , image_translation )

cv2. čakajteKľúč ( 0 )

Riadky 1 až 5: Importujeme všetky potrebné balíky pre tento program, ako napríklad OpenCV, argparser a NumPy. Upozorňujeme, že existuje ďalšia knižnica, ktorá je imutils. Toto nie je balík OpenCV. Toto je len knižnica, ktorá jednoducho ukáže rovnaké spracovanie obrazu.



Imutily knižnice nebudú zahrnuté automaticky, keď nainštalujeme OpenCV. Ak chcete nainštalovať imutils, musíme použiť nasledujúcu metódu:

pip install imutils

Riadky 8 až 15: Vytvorili sme náš agrparser a načítali sme náš obrázok.

Riadky 24 až 25: V tejto sekcii programu prebieha preklad. Matica prekladu nám hovorí, o koľko pixelov sa obrázok posunie nahor alebo nadol alebo doľava alebo doprava. Pretože OpenCV vyžaduje, aby hodnota matice bola v poli s pohyblivou rádovou čiarkou, translačná matica nadobúda hodnoty v poliach s pohyblivou rádovou čiarkou.

Prvý riadok matice prekladu vyzerá takto:

Tento riadok matice je pre os x. Hodnota t X rozhodne, či sa obrázok posunie na ľavú alebo pravú stranu. Ak prejdeme so zápornou hodnotou, znamená to, že obrázok sa posunie na ľavú stranu a ak je hodnota kladná, znamená to, že sa obrázok posunie na pravú stranu.

Teraz definujeme druhý riadok matice takto:

Tento riadok matice je pre os y. Hodnota t Y rozhodne, či sa obrázok posunie nahor alebo nadol. Ak prejdeme so zápornou hodnotou, znamená to, že obrázok sa posunie nahor a ak je hodnota kladná, znamená to, že sa obrázok posunie nadol.

V predchádzajúcom programe na riadku 24 definujeme t X = 30 a t Y = 70. Takže posúvame obrázok o 30 pixelov smerom doprava a 70 pixelov nadol.

Ale hlavný proces prekladu obrazu prebieha na riadku 25, kde definujeme maticu prekladu cv2.warpAffine . V tejto funkcii odovzdávame tri parametre: prvý parameter je obrázok, druhý parameter je matica prekladu a tretí parameter je rozmer obrázka.

Riadok 27: Riadok 27 zobrazí výsledok vo výstupe.

Teraz implementujeme ďalšiu maticu prekladu pre ľavú a hornú stranu. Na to musíme definovať záporné hodnoty.

Riadok 33 až 34: V predchádzajúcom programe na riadku 33 definujeme t X = -50 a t Y = -90. Takže posúvame obrázok o 50 pixelov smerom doľava a 90 pixelov nahor. Ale hlavný proces prekladu obrazu prebieha na riadku 34, kde definujeme maticu prekladu cv2.warpAffine .

Riadok 36 : Riadok 36 zobrazí výsledok, ako je znázornené na výstupe.

Ak chcete spustiť predchádzajúci kód, musíme zadať cestu k obrázku, ako je uvedené nižšie.

Výkon: python translate.py –image squirrel.jpg

Teraz implementujeme rovnaký program na preklad obrázkov pomocou imutil knižnica. Táto knižnica sa veľmi jednoducho používa na spracovanie obrázkov. V tejto knižnici nemusíme myslieť na cv2.warpAffine pretože táto knižnica sa o to postará. Implementujme teda tento program na preklad obrázkov pomocou knižnice imutils.

Python kód: Nasledujúci názov programu zachováme ako translate_imutils.py .

# importujte potrebné balíčky

importovať numpy ako napr.

importovať argparse

importovať imutil

importovať cv2

# Táto funkcia implementuje preklad obrázkov a

# vráti preložený obrázok volajúcej funkcii.

def preložiť ( obrázok , X , Y ) :

prekladová_matica = napr. plavák32 ( [ [ 1 , 0 , X ] , [ 0 , 1 , Y ] ] )

image_translation = cv2. warpAffine ( obrázok , prekladová_matica ,

( obrázok. tvar [ 1 ] , obrázok. tvar [ 0 ] ) )

vrátiť image_translation

# zostavte analyzátor argumentov a analyzujte argumenty

ap = argparse. ArgumentParser ( )

ap. pridať_argument ( '-i' , '--obrázok' , požadovaný = Pravda , Pomoc = 'Cesta k obrázku' )

args = ktorých ( ap. parse_args ( ) )

# načítať obrázok a zobraziť ho na obrazovke

obrázok = cv2. imread ( args [ 'obrázok' ] )

cv2. imshow ( 'Original_image' , obrázok )

image_translation = imutil. preložiť ( obrázok , 10 , 70 )

cv2. imshow ( 'Preklad obrázka doprava a nadol' ,

image_translation )

cv2. čakajteKľúč ( 0 )

Riadky 9 až 13: V tejto časti programu prebieha preklad. Prekladová matica nás informuje o koľko pixelov sa obrázok posunie nahor alebo nadol alebo doľava alebo doprava.

Tieto riadky už boli vysvetlené, ale teraz vytvoríme funkciu s názvom translate () a pošleme do nej tri odlišné parametre. Ako prvý parameter slúži samotný obrázok. Hodnoty x a y translačnej matice zodpovedajú druhému a tretiemu parametru.

Poznámka : Túto funkciu prekladu nie je potrebné definovať v programe, pretože je už zahrnutá v balíku knižnice imutils. Použil som ho v programe kvôli jednoduchému vysvetleniu. Túto funkciu môžeme zavolať priamo pomocou imutils, ako je znázornené v riadku 24.

Riadok 24: Predchádzajúci program ukáže, že na riadku 24 definujeme tx = 10 a ty = 70. Takže posúvame obrázok o 10 pixelov smerom doprava a 70 pixelov nadol.

V tomto programe sa nestaráme o žiadne funkcie cv2.warpAffine, pretože sú už v balíku knižnice imutils.

Ak chcete spustiť predchádzajúci kód, musíme zadať cestu k obrázku, ako je uvedené nižšie:

Výkon:

python imutils. py --obrazová veverička. jpg

2. Otočenie obrazu

Prešli sme si, ako preložiť (t.j. posunúť) obrázok nahor, nadol, doľava a doprava v predchádzajúcej lekcii (alebo v akejkoľvek kombinácii). Ďalej budeme diskutovať o rotácii, ktorá súvisí so spracovaním obrazu.

Obraz sa otáča o uhol, theta, v procese známom ako rotácia. Uhol, o ktorý otáčame obrázok, bude reprezentovaný theta. Okrem toho následne poskytnem funkciu pohodlia otáčania, aby bolo otáčanie obrázkov jednoduchšie.

Podobne ako pri translácii, a možno nie prekvapivo, rotácii o uhol, theta je určená zostavením matice M v nasledujúcom formáte:

Táto matica sa môže otáčať o stupne vektora theta (proti smeru hodinových ručičiek) okolo pôvodnej (x, y)-karteziánskej roviny. Za normálnych okolností by v tomto scenári bol počiatok stredom obrázku, ale v skutočnosti by sme mohli určiť ľubovoľný náhodný bod (x, y) ako náš rotačný stred.

Otočený obrázok R sa potom vytvorí z pôvodného obrázku I pomocou priameho násobenia maticou: R = IM

OpenCV na druhej strane navyše ponúka schopnosť (1) škálovať (t. j. meniť veľkosť) obrázka a (2) ponúkať ľubovoľný stred otáčania na otáčanie okolo.

Naša modifikovaná rotačná matica M je znázornená nižšie:

Začnime otvorením a vygenerovaním nového súboru s názvom otočiť.py :

# importovanie požadovaných balíkov

importovať numpy ako napr.

importovať argparse

importovať imutil

importovať cv2

# vytvorenie objektu argumentparser a analýzy argumentu

apobj = argparse. ArgumentParser ( )

apobj. pridať_argument ( '-k' , '--obrázok' , požadovaný = Pravda , Pomoc = 'cesta k obrázku' )

argumenty = ktorých ( apobj. parse_args ( ) )

obrázok = cv2. imread ( argumenty [ 'obrázok' ] )

cv2. imshow ( 'Original_image' , obrázok )

# Vypočítajte stred obrázka pomocou rozmerov obrázka.

( výška , šírka ) = obrázok. tvar [ : 2 ]

( centrumX , centrumY ) = ( šírka / 2 , výška / 2 )

# Teraz pomocou cv2 otočíme obrázok o 55 stupňov

# určiť rotačnú maticu pomocou getRotationMatrix2D()

rotačná matica = cv2. getRotationMatrix2D ( ( centrumX , centrumY ) , 55 , 1,0 )

otočenýObrázok = cv2. warpAffine ( obrázok , rotačná matica , ( šírka , výška ) )

cv2. imshow ( 'Otočený obrázok o 55 stupňov' , otočenýObrázok )

cv2. čakajteKľúč ( 0 )

# Obrázok bude teraz otočený o -85 stupňov.

rotačná matica = cv2. getRotationMatrix2D ( ( centrumX , centrumY ) , - 85 , 1,0 )

otočenýObrázok = cv2. warpAffine ( obrázok , rotačná matica , ( šírka , výška ) )

cv2. imshow ( 'Otočený obrázok o -85 stupňov' , otočenýObrázok )

cv2. čakajteKľúč ( 0 )

Riadky 1 až 5: Importujeme všetky potrebné balíky pre tento program, ako napríklad OpenCV, argparser a NumPy. Upozorňujeme, že existuje ďalšia knižnica, ktorá je imutils. Toto nie je balík OpenCV. Toto je len knižnica, ktorá sa použije na jednoduché zobrazenie rovnakého spracovania obrazu.

Imutily knižnice nebudú zahrnuté automaticky, keď nainštalujeme OpenCV. OpenCV nainštaluje imutils. Musíme použiť nasledujúcu metódu:

pip install imutils

Riadky 8 až 14: Vytvorili sme náš agrparser a načítali sme náš obrázok. V tomto argparseri používame iba jeden argument obrázka, ktorý nám povie cestu obrázka, ktorú v tomto programe použijeme na demonštráciu rotácie.

Pri otáčaní obrázka musíme definovať otočný bod otáčania. Väčšinu času budete chcieť otočiť obrázok okolo jeho stredu, ale OpenCV vám namiesto toho umožňuje vybrať ľubovoľný náhodný bod. Jednoducho otočme obrázok okolo jeho stredu.

Riadky 17 až 18 zoberte šírku a výšku obrázka a potom vydeľte každý rozmer dvoma, aby ste určili stred obrázka.

Vytvárame maticu na otáčanie obrazu rovnakým spôsobom, ako sme definovali maticu na prekladanie obrazu. Len zavoláme cv2.getRotationMatrix2D funkciu na riadku 22 namiesto manuálneho vytvárania matice pomocou NumPy (čo môže byť trochu ťažkopádne).

The cv2.getRotationMatrix2D funkcia vyžaduje tri parametre. Prvým vstupom je požadovaný uhol natočenia (v tomto prípade stred obrazu). Theta sa potom používa na určenie toho, o koľko (proti smeru hodinových ručičiek) stupňov otočíme obrázok. Tu otočíme obrázok o 45 stupňov. Posledná možnosť súvisí s veľkosťou obrázka.

Bez ohľadu na to, že sme ešte nehovorili o zmene mierky obrázka, tu môžete zadať číslo s pohyblivou rádovou čiarkou s 1,0, čo znamená, že obrázok by sa mal použiť v pôvodných proporciách. Ak by ste však zadali hodnotu 2,0, veľkosť obrázka by sa zdvojnásobila. Číslo 0,5 takto zmenšuje veľkosť obrázka.

Riadok 22 až 23: Po prijatí našej rotačnej matice M z cv2.getRotationMatrix2D pomocou funkcie otočíme náš obrázok cv2.warpAffine technika na riadku 23. Prvým vstupom funkcie je obrázok, ktorý chceme otočiť. Potom je definovaná šírka a výška nášho výstupného obrázku spolu s našou rotačnou maticou M. Na riadku 23 sa potom obrázok otočí o 55 stupňov.

Môžete si všimnúť, že náš obrázok bol otočený.

Riadky 28 až 30 tvoria druhú rotáciu. Riadky 22 – 23 kódu sú identické, až na to, že tentoraz sa otáčame o -85 stupňov oproti 55.

Do tohto bodu sme jednoducho otočili obrázok okolo jeho stredu. Čo keby sme chceli otočiť obrázok okolo náhodného bodu?

Začnime otvorením a vygenerovaním nového súboru s názvom otočiť.py:

# importovanie požadovaných balíkov

importovať numpy ako napr.

importovať argparse

importovať imutil

importovať cv2

# vytvorenie objektu argumentparser a analýzy argumentu

ap_obj = argparse. ArgumentParser ( )

ap_obj. pridať_argument ( '-k' , '--obrázok' , požadovaný = Pravda , Pomoc = 'cesta k obrázku' )

argument = ktorých ( ap_obj. parse_args ( ) )

# načítať obrázok a zobraziť ho na obrazovke

obrázok = cv2. imread ( argument [ 'obrázok' ] )

cv2. imshow ( 'Original_image' , obrázok )

# Vypočítajte stred obrázka pomocou rozmerov obrázka.

( výška , šírka ) = obrázok. tvar [ : 2 ]

( centrumX , centrumY ) = ( šírka / 2 , výška / 2 )

# Teraz pomocou cv2 otočíme obrázok o 55 stupňov

# určiť rotačnú maticu pomocou getRotationMatrix2D()

rotačná matica = cv2. getRotationMatrix2D ( ( centrumX , centrumY ) , 55 , 1,0 )

otočenýObrázok = cv2. warpAffine ( obrázok , rotačná matica , ( šírka , výška ) )

cv2. imshow ( 'Otočený obrázok o 55 stupňov' , otočenýObrázok )

cv2. čakajteKľúč ( 0 )

# Obrázok bude teraz otočený o -85 stupňov.

rotačná matica = cv2. getRotationMatrix2D ( ( centrumX , centrumY ) , - 85 , 1,0 )

otočenýObrázok = cv2. warpAffine ( obrázok , rotačná matica , ( šírka , výška ) )

cv2. imshow ( 'Otočený obrázok o -85 stupňov' , otočenýObrázok )

cv2. čakajteKľúč ( 0 )

# rotácia obrazu z nejakého ľubovoľného bodu, nie zo stredu

rotačná matica = cv2. getRotationMatrix2D ( ( centerX - 40 , stredY - 40 ) , 55 , 1,0 )

otočenýObrázok = cv2. warpAffine ( obrázok , rotačná matica , ( šírka , výška ) )

cv2. imshow ( 'Otáčanie obrazu z ľubovoľných bodov' , otočenýObrázok )

cv2. čakajteKľúč ( 0 )

Riadok 34 až 35: Teraz by sa tento kód mal zdať celkom bežný na otáčanie objektu. Ak chcete otočiť obrázok okolo bodu 40 pixelov doľava a 40 pixelov nad jeho stredom, dáme pokyn cv2.getRotationMatrix2D venujte pozornosť jej prvému parametru.

Obrázok vytvorený pri použití tejto rotácie je zobrazený nižšie:

Jasne vidíme, že stred otáčania je teraz súradnica (x, y), ktorá je 40 pixelov vľavo a 40 pixelov nad vypočítaným stredom obrázka.

3. Obrazová aritmetika

Aritmetika obrázkov je v skutočnosti len maticový doplnok s niekoľkými ďalšími obmedzeniami typov údajov, ktorým sa budeme venovať neskôr.

Poďme sa na chvíľu pozrieť na niektoré pekné základy lineárnej algebry.

Zvážte kombináciu nasledujúcich dvoch matíc:

Aký výsledok prinesie pridanie matrice? Jednoduchá odpoveď je súčet položiek matice, prvok po prvku:

Dosť jednoduché, však?

V súčasnosti všetci rozumieme základným operáciám sčítania a odčítania. Pri práci s obrázkami však musíme pamätať na obmedzenia, ktoré ukladá náš farebný priestor a typ údajov.

Pixely v obrázkoch RGB sú napríklad medzi [0, 255]. Čo sa stane, ak sa pokúsime pridať 10 k pixelu s intenzitou 250, keď sa naň pozeráme?

Ak by sme použili štandardné aritmetické princípy, dospeli by sme k hodnote 260. 260 nie je platná hodnota, pretože obrázky RGB sú reprezentované ako 8-bitové celé čísla bez znamienka.

Čo by teda malo nastať? Mali by sme spustiť kontrolu, aby sme sa uistili, že žiadny pixel nie je mimo rozsahu [0, 255], a orezať každý pixel tak, aby mal hodnotu medzi 0 a 255?

Alebo sa „zabalíme“ a vykonáme modulovú operáciu? V súlade s pravidlami modulu by pridanie 10 k 255 malo za následok len hodnotu 9.

Ako by sa malo postupovať pri pridávaní a odčítaní obrázkov mimo rozsahu [0, 255]?

Pravdou je, že neexistuje správna alebo nesprávna technika; všetko závisí od toho, ako pracujete s pixelmi a čo chcete dosiahnuť.

Pamätajte však, že existujú rozdiely medzi pridaním v OpenCV a pridaním v NumPy. Modulovú aritmetiku a „zabalenie“ vykoná NumPy. Na rozdiel od toho OpenCV vykoná orezanie a zabezpečí, aby hodnoty pixelov nikdy neopustili rozsah [0, 255].

Začnime vytvorením nového súboru s názvom aritmetika.py a otvorenie:

# python aritmetic.py --image squirrel.jpg

# importovanie požadovaných balíkov

importovať numpy ako napr.

importovať argparse

importovať imutil

importovať cv2

# vytvorenie objektu argumentparser a analýzy argumentu

apObj = argparse. ArgumentParser ( )

apObj. pridať_argument ( '-k' , '--obrázok' , požadovaný = Pravda , Pomoc = 'cesta k obrázku' )

argumenty = ktorých ( apObj. parse_args ( ) )

obrázok = cv2. imread ( argumenty [ 'obrázok' ] )

cv2. imshow ( 'Original_image' , obrázok )

'''

Hodnoty našich pixelov budú v rozsahu [0, 255]

keďže obrázky sú polia NumPy, ktoré sú uložené ako 8-bitové celé čísla bez znamienka.

Pri použití funkcií ako cv2.add a cv2.subtract budú hodnoty orezané

do tohto rozsahu, aj keď sú pridané alebo odčítané mimo neho

rozsah [0, 255]. Tu je ilustrácia:

'''


vytlačiť ( 'maximálne 255: {}' . formát ( str ( cv2. pridať ( napr. uint8 ( [ 201 ] ) ,

napr. uint8 ( [ 100 ] ) ) ) ) )

vytlačiť ( 'minimum 0: {}' . formát ( str ( cv2. odčítať ( napr. uint8 ( [ 60 ] ) ,

napr. uint8 ( [ 100 ] ) ) ) ) )

'''

Keď robíte aritmetické operácie s týmito poliami pomocou NumPy,

hodnota sa skôr zabalí, než aby bola pristrihnutá

[0,255]rozsah. Pri používaní obrázkov je dôležité toto dodržať

na mysli.

'''


vytlačiť ( 'zabaliť sa: {}' . formát ( str ( napr. uint8 ( [ 201 ] ) + napr. uint8 ( [ 100 ] ) ) ) )

vytlačiť ( 'zabaliť sa: {}' . formát ( str ( napr. uint8 ( [ 60 ] ) - napr. uint8 ( [ 100 ] ) ) ) )

'''

Vynásobme jas každého pixelu na našom obrázku 101.

Aby sme to dosiahli, vygenerujeme pole NumPy rovnakej veľkosti ako naša matica,

vyplnené jednotkami a vynásobte ho číslom 101, aby ste získali pole vyplnené

so 101 s. Nakoniec oba obrázky spojíme.

Všimnete si, že obrázok je teraz „jasnejší“.

'''


Matrix = napr. tie ( obrázok. tvar , dtype = 'uint8' ) * 101

obrázok_pridaný = cv2. pridať ( obrázok , Matrix )

cv2. imshow ( 'Pridaný výsledok obrázka' , obrázok_pridaný )

#Podobným spôsobom môžeme náš obrázok stmaviť fotografovaním

# 60 od všetkých pixelov.

Matrix = napr. tie ( obrázok. tvar , dtype = 'uint8' ) * 60

image_subtracted = cv2. odčítať ( obrázok , Matrix )

cv2. imshow ( 'Odčítaný výsledok obrázka' , image_subtracted )

cv2. čakajteKľúč ( 0 )

Riadky 1 až 16 sa použije na vykonanie nášho bežného procesu, ktorý zahŕňa import našich balíkov, konfiguráciu nášho analyzátora argumentov a načítanie nášho obrazu.

Spomeňte si, ako som predtým diskutoval o rozdiele medzi pridaním OpenCV a NumPy? Teraz, keď sme to dôkladne pokryli, pozrime sa na konkrétny prípad, aby sme sa uistili, že ho pochopíme.

Dve 8-bitové polia NumPy bez znamienka sú definované na riadok 26 . Hodnota 201 je jediným prvkom v prvom poli. Aj keď je v druhom poli iba jeden člen, má hodnotu 100. Hodnoty sa potom pridajú pomocou funkcie cv2.add OpenCV.

Aký očakávate výsledok?

V súlade s konvenčnými aritmetickými princípmi by odpoveď mala byť 301. Pamätajte však, že máme do činenia s 8-bitovými celými číslami bez znamienka, ktoré môžu byť iba v rozsahu [0, 255]. Pretože používame metódu cv2.add, OpenCV spracováva orezávanie a zabezpečuje, že sčítanie vráti iba maximálny výsledok 255.

Prvý riadok nižšie uvedeného zoznamu zobrazuje výsledok spustenia tohto kódu:

aritmetika. py

maximálne z 255 : [ [ 255 ] ]

Súčet skutočne priniesol číslo 255.

V nadväznosti na to riadok 26 používa cv2.subtract na vykonanie odčítania. Ešte raz definujeme dve 8-bitové polia NumPy bez znamienka s jedným prvkom v každom. Hodnota prvého poľa je 60, zatiaľ čo hodnota druhého poľa je 100.

Naša aritmetika diktuje, že výsledkom odčítania by mala byť hodnota -40, ale OpenCV spracuje orezanie za nás ešte raz. Zistili sme, že hodnota bola skrátená na 0. Náš výsledok nižšie to demonštruje:

aritmetika. py

minimálne 0 : [ [ 0 ] ]

Pomocou cv2 odpočítajte 100 od 60 a získajte hodnotu 0.

Čo sa však stane, ak použijeme NumPy namiesto OpenCV na vykonanie výpočtov?

Riadky 38 a 39 riešiť tento problém.

Najprv sú definované dve 8-bitové celočíselné polia NumPy bez znamienka, každé s jedným prvkom. Hodnota prvého poľa je 201, zatiaľ čo hodnota druhého poľa je 100. Náš súčet by sa orezal a vrátila by sa hodnota 255, ak by sme použili funkciu cv2.add.

NumPy sa na druhej strane „obtáča“ a robí modulo aritmetiku skôr ako orezávanie. NumPy sa po dosiahnutí hodnoty 255 otočí okolo nuly a potom pokračuje v počítaní, kým sa nedosiahne 100 krokov. Potvrdzuje to prvý riadok výstupu, ktorý je zobrazený nižšie:

aritmetika. py
omotať sa: [ Štyri, päť ]

Potom sa definujú dve ďalšie polia NumPy, jedno s hodnotou 50 a druhé so 100. Toto odčítanie by sa orezalo metódou cv2.subtract, aby vrátilo výsledok 0. Uvedomujeme si však, že namiesto orezania vykoná NumPy modulová aritmetika. Namiesto toho sa modulo procedúry zabalia a začnú počítať spätne od 255, keď sa počas odčítania dosiahne 0. Môžeme to vidieť z nasledujúceho výstupu:

aritmetika. py

omotať sa: [ 207 ]

Náš výstup z terminálu ešte raz demonštruje rozdiel medzi orezávaním a obtáčaním:

Pri vykonávaní celočíselnej aritmetiky je dôležité mať na pamäti požadovaný výsledok. Chcete orezať hodnoty mimo rozsahu [0, 255]? Potom použite vstavané obrázkové aritmetické techniky OpenCV.

Chcete, aby sa hodnoty zalomili, ak sú mimo rozsahu [0, 255] a modulových aritmetických operácií? Polia NumPy sa potom jednoducho pridajú a odčítajú ako obvykle.

Riadok 48 definuje jednorozmerné pole NumPy s rovnakými rozmermi ako náš obrázok. Ešte raz zaisťujeme, že náš typ údajov je 8-bitové celé čísla bez znamienka. Našu maticu jednociferných hodnôt len ​​vynásobíme číslom 101, aby sme ju naplnili hodnotami 101 namiesto 1. Nakoniec použijeme funkciu cv2.add na pridanie našej matice 100 k pôvodnému obrázku. Tým sa zvýši intenzita každého pixelu o 101 a zároveň sa zabezpečí, že všetky hodnoty, ktoré sa pokúsia prekročiť hodnotu 255, budú orezané na rozsah [0, 255].

Všimnite si, ako je obrázok zreteľne jasnejší a vyzerá viac „vyblednutý“ ako originál. Je to preto, že pixely posúvame smerom k jasnejším farbám zvýšením ich intenzity pixelov o 101.

Aby sme odčítali 60 od intenzity každého pixelu obrázka, najprv vytvoríme druhé pole NumPy na riadku 54, ktoré je vyplnené 60-timi sekundami.

Výsledky tohto odčítania sú znázornené na nasledujúcom obrázku:

Predmety okolo nás vyzerajú výrazne tmavšie ako predtým. Dôvodom je, že odpočítaním 60 od každého pixelu presúvame pixely vo farebnom priestore RGB do tmavších oblastí.

4. Preklápanie obrazu

Podobne ako pri otáčaní, prevrátenie obrázka cez jeho os x alebo y je ďalšou možnosťou, ktorú ponúka OpenCV. Aj keď sa operácie preklápania nevyužívajú tak často, ich poznanie je neuveriteľne prospešné z rôznych dôvodov, ktoré možno hneď neuvidíte.

Vyvíjame klasifikátor strojového učenia pre malú začínajúcu spoločnosť, ktorá sa snaží identifikovať tváre na obrázkoch. Aby sa náš systém „naučil“, čo je to tvár, potrebovali by sme nejaký súbor údajov so vzorovými tvárami. Bohužiaľ, spoločnosť nám poskytla iba malý súbor údajov 40 tvárí a nemôžeme získať viac informácií.

Čo teda urobíme?

Keďže tvár zostáva tvárou bez ohľadu na to, či je zrkadlená alebo nie, môžeme horizontálne prevrátiť každý obrázok tváre a použiť zrkadlové verzie ako ďalšie tréningové údaje.

Tento príklad sa môže zdať hlúpy a umelý, ale nie je. Preklápanie je zámerná stratégia používaná silnými algoritmami hlbokého učenia na vytváranie väčšieho množstva údajov počas tréningovej fázy.

Z predchádzajúceho je zrejmé, že metódy spracovania obrazu, ktoré sa naučíte v tomto module, slúžia ako základ pre väčšie systémy počítačového videnia.

Ciele:

Pomocou cv2.flip V tejto relácii sa naučíte, ako prevrátiť obrázok horizontálne aj vertikálne.

Prevrátenie je ďalšia manipulácia s obrázkom, ktorú budeme študovať. Osi x a y obrázka je možné prevrátiť alebo dokonca oboje. Predtým, ako sa vrhneme na kódovanie, je najlepšie sa najprv pozrieť na výsledky preklopenia obrázka. Pozrite si obrázok, ktorý bol vodorovne prevrátený na nasledujúcom obrázku:


Všimnite si, ako je náš pôvodný obrázok vľavo a ako bol obrázok horizontálne zrkadlený vpravo.

Začnime vytvorením nového súboru s názvom flipping.py .

Videli ste príklad prevrátenia obrázka, takže poďme preskúmať kód:

# python flipping.py --image quirrel.jpg

# importovanie požadovaných balíkov

importovať argparse

importovať cv2

# vytvorenie objektu analyzátora argumentov a analyzovanie argumentu

apObj = argparse. ArgumentParser ( )

apObj. pridať_argument ( '-i' , '--obrázok' , požadovaný = Pravda , Pomoc = 'cesta k obrázku' )

argument = ktorých ( apObj. parse_args ( ) )

obrázok = cv2. imread ( argument [ 'obrázok' ] )

cv2. imshow ( 'Originál' , obrázok )

# horizontálne prevrátiť obrázok

prevrátený obraz = cv2. prevrátiť ( obrázok , 1 )

cv2. imshow ( 'Obrázok prevrátený vodorovne' , prevrátený obraz )

# vertikálne otočte obrázok

prevrátený obraz = cv2. prevrátiť ( obrázok , 0 )

cv2. imshow ( 'Obrázok prevrátený vertikálne' , prevrátený obraz )

# prevrátenie obrázka pozdĺž oboch osí

prevrátený obraz = cv2. prevrátiť ( obrázok , - 1 )

cv2. imshow ( 'Prevrátené horizontálne a vertikálne' , prevrátený obraz )

cv2. čakajteKľúč ( 0 )

Kroky, ktoré podnikneme na import našich balíkov, analýzu našich vstupov a načítanie nášho obrazu z disku, sú spracované v l ines 1 až 12 .

Zavolaním funkcie cv2.flip on Riadok 15 , je jednoduché prevrátiť obrázok vodorovne. Obrázok, ktorý sa snažíme prevrátiť, a špecifický kód alebo príznak, ktorý špecifikuje, ako sa má obrázok prevrátiť, sú dva argumenty potrebné pre metódu cv2.flip.

Hodnota preklápacieho kódu 1 znamená, že obrázok otočíme okolo osi y, aby sme ho prevrátili vodorovne ( Riadok 15 ). Ak zadáme kód prevrátenia 0, chceme otočiť obrázok okolo osi x ( Riadok 19 ). Záporný flip kód ( Riadok 23 ) otočí obrázok v oboch osiach.

Jedným z najjednoduchších príkladov v tejto téme je prevrátenie obrázka, čo je základ.

Ďalej budeme diskutovať o orezaní obrázkov a pomocou výrezov poľa NumPy na extrahovanie konkrétnych častí obrázkov.

5. Orezanie obrázka

Orezanie, ako už názov napovedá, je proces výberu a odstraňovania oblasti záujmu (alebo jednoducho ROI), čo je oblasť obrázka, ktorá nás zaujíma.

Pre aplikáciu na detekciu tváre by tvár musela byť orezaná z obrázka. Okrem toho, ak by sme vytvárali skript Python na vyhľadávanie psov v obrázkoch, možno by sme chceli psa z obrázka orezať, keď ho nájdeme.

Ciele: Naším hlavným cieľom je zoznámiť sa a jednoducho používať rezanie poľa NumPy na orezanie oblastí z obrázka.

Orezanie : Keď orezávame obrázok, naším cieľom je odstrániť vonkajšie prvky, ktoré nás nezaujímajú. Proces výberu našej návratnosti investícií sa často označuje ako výber našej oblasti záujmu.

Vytvorte nový súbor s názvom crop.py , otvorte ho a pridajte nasledujúci kód:

# python crop.py

# importovanie požadovaných balíkov

importovať cv2

# načítanie a zobrazenie obrázka na obrazovke

obrázok = cv2. imread ( 'squirrel.jpg' )

vytlačiť ( obrázok. tvar )

cv2. imshow ( 'Originál' , obrázok )

# Slice poľa NumPy sa používajú na rýchle orezanie obrázka

# ideme orezať tvár veveričky z obrázka

veverička = obrázok [ 35 : 90 , 35 : 100 ]

cv2. imshow ( 'tvár veveričky' , veverička )

cv2. čakajteKľúč ( 0 )

# A teraz orežeme celé telo

# veveričky

veverička = obrázok [ 35 : 148 , 23 : 143 ]

cv2. imshow ( 'Telo veveričky' , veverička )

cv2. čakajteKľúč ( 0 )

Ukážeme orezanie v Pythone a OpenCV pomocou obrázka, ktorý načítame z disku Riadky 5 a 6 .

Pôvodný obrázok, ktorý ideme orezať

Pomocou iba základných techník orezávania sa snažíme oddeliť tvár a telo veveričky od okolia.

Využijeme naše predchádzajúce znalosti o obrázku a ručne dodáme plátky poľa NumPy, kde sa nachádza telo a tvár. Za normálnych podmienok by sme vo všeobecnosti použili strojové učenie a algoritmy počítačového videnia na rozpoznanie tváre a tela na obrázku. Ale nechajme veci zatiaľ priamočiare a vyhýbajme sa používaniu akýchkoľvek detekčných modelov.

Tvár na obrázku dokážeme identifikovať iba jedným riadkom kódu. Riadok 13 , Ak chcete extrahovať obdĺžnikovú časť obrázka počnúc (35, 35), poskytujeme plátky poľa NumPy (90, 100). Môže sa zdať mätúce, že orezanie podávame indexmi v poradí výška-prvá a šírka-druhá, ako to robíme, ale majte na pamäti, že OpenCV ukladá obrázky ako polia NumPy. V dôsledku toho musíme dodať hodnoty pre os y pred osou x.

NumPy vyžaduje na vykonanie nášho orezania nasledujúce štyri indexy:

Začať: Súradnica y na začiatku. V tomto prípade začneme na y=35.

Koniec y: Súradnica y na konci. Naša úroda sa zastaví, keď y = 90.

Začiatok x: Začiatok rezu x súradnica. Orezávanie začína pri x=35.

Koniec x: Súradnica osi x konca rezu. Pri x=100 je náš rez hotový.

Podobne orežeme oblasti (23, 35) a (143, 148) z pôvodnej snímky, aby sme z nej extrahovali celé telo Riadok 19 .

Môžete si všimnúť, že obrázok bol orezaný, aby zobrazoval iba telo a tvár.

6. Zmena veľkosti obrázka

Proces zväčšovania alebo zmenšovania šírky a výšky obrázka je známy ako zmena mierky alebo jednoducho zmena veľkosti. Pri zmene veľkosti obrázka by ste mali zvážiť pomer strán, čo je pomer šírky obrázka k jeho výške. Zanedbanie pomeru strán môže mať za následok zmenšenie obrázkov, ktoré sa zdajú byť komprimované a skreslené:

Náš úvodný obrázok je vľavo. Na pravej strane uvidíte dva obrázky, ktoré boli zmenšené bez zachovania pomeru strán, čím sa skresľuje pomer šírky obrázka k jeho výške. Pri zmene veľkosti obrázkov by ste mali vo všeobecnosti zvážiť pomer strán.

Technika interpolácie, ktorú používa náš algoritmus na zmenu veľkosti, musí tiež brať do úvahy cieľ interpolačnej funkcie použiť tieto susedstvá pixelov na zvýšenie alebo zníženie veľkosti obrázka.

Vo všeobecnosti je oveľa efektívnejšie zmenšiť veľkosť obrázka. Je to preto, že odstránenie pixelov z obrázka je všetko, čo funkcia interpolácie musí urobiť. Na druhej strane, interpolačná metóda by musela „vyplniť medzery“ medzi pixelmi, ktoré predtým neexistovali, ak by sa mala zväčšiť veľkosť obrázka.

Náš pôvodný obrázok máme vľavo. Obrázok sa v strede zmenšil na polovicu pôvodnej veľkosti, ale okrem toho nedošlo k žiadnej strate „kvality obrázka“. Napriek tomu sa veľkosť obrázka na pravej strane výrazne zväčšila. Teraz sa javí ako „nafúknutý“ a „pixelovaný“.

Ako som už uviedol, zvyčajne budete chcieť veľkosť obrázka zmenšiť, a nie zväčšiť. Zmenšením veľkosti obrazu analyzujeme menej pixelov a musíme sa vysporiadať s menším „šumom“, vďaka čomu sú algoritmy spracovania obrazu rýchlejšie a presnejšie.

Translácia a rotácia sú dve transformácie obrazu, ktoré sa doteraz riešili. Teraz sa pozrieme na to, ako zmeniť veľkosť obrázka.

Nie je prekvapením, že veľkosť našich obrázkov zmeníme pomocou metódy cv2.resize. Ako som už naznačil, pri použití tejto metódy musíme zvážiť pomer strán obrázka. Ale skôr, než sa dostaneme príliš hlboko do špecifík, dovoľte mi uviesť ilustráciu:

# python resize.py --image squirrel.jpg

# importovanie požadovaných balíkov

importovať argparse

importovať cv2

# vytvorenie objektu analyzátora argumentov a analyzovanie argumentu

apObj = argparse. ArgumentParser ( )

apObj. pridať_argument ( '-k' , '--obrázok' , požadovaný = Pravda , Pomoc = 'cesta k obrázku' )

argumenty = ktorých ( apObj. parse_args ( ) )

# načítať obrázok a zobraziť ho na obrazovke

obrázok = cv2. imread ( argumenty [ 'obrázok' ] )

cv2. imshow ( 'Originál' , obrázok )

# Aby ste zabránili tomu, aby obraz vyzeral zošikmene, použite pomer strán

# sa musí zvážiť alebo zdeformovať; preto zisťujeme čo

# pomer nového obrázka k aktuálnemu obrázku.

# Urobme šírku nášho nového obrázka 160 pixelov.

aspekt = 160,0 / obrázok. tvar [ 1 ]

rozmer = ( 160 , int ( obrázok. tvar [ 0 ] * aspekt ) )

# tento riadok zobrazí skutočné operácie zmeny veľkosti

zmeniť veľkosť obrázka = cv2. zmeniť veľkosť ( obrázok , rozmer , interpolácia = cv2. INTER_AREA )

cv2. imshow ( 'Šírka obrázka so zmenenou veľkosťou' , zmeniť veľkosť obrázka )

# Čo keby sme chceli zmeniť výšku obrázka? - pomocou

# rovnaký princíp, môžeme vypočítať pomer strán

# na výšku a nie na šírku. Urobme šupky

# výška obrázka 70 pixelov.

aspekt = 70,0 / obrázok. tvar [ 0 ]

rozmer = ( int ( obrázok. tvar [ 1 ] * aspekt ) , 70 )

# vykonajte zmenu veľkosti

zmeniť veľkosť obrázka = cv2. zmeniť veľkosť ( obrázok , rozmer , interpolácia = cv2. INTER_AREA )

cv2. imshow ( 'Výška obrázka so zmenenou veľkosťou' , zmeniť veľkosť obrázka )

cv2. čakajteKľúč ( 0 )

Riadky 1-14 , Po importovaní našich balíkov a konfigurácii nášho analyzátora argumentov načítame a zobrazíme náš obrázok.

Riadky 20 a 21: Príslušné kódovanie začína v týchto riadkoch . Pri zmene veľkosti obrázka je potrebné vziať do úvahy pomer strán. Pomer medzi šírkou a výškou obrázka je známy ako pomer strán.

Výška šírka je pomer strán.

Ak neberieme do úvahy pomer strán, výsledky našej zmeny veľkosti budú skreslené.

Zapnuté Riadok 20 , vykoná sa výpočet pomeru zmenenej veľkosti. V tomto riadku kódu poskytujeme šírku nášho nového obrázka 160 pixelov. Jednoducho definujeme náš pomer (aspectratio) ako novú šírku (160 pixelov) vydelenú starou šírkou, ku ktorej pristupujeme pomocou obrázka, aby sme vypočítali pomer novej výšky k starej výške. tvar[1].

Nové rozmery obrazu na Riadok 21 možno vypočítať teraz, keď poznáme náš pomer. Nový obrázok bude mať opäť šírku 160 pixelov. Po vynásobení starej výšky naším pomerom a prevedení výsledku na celé číslo sa výška vypočíta. Vykonaním tejto operácie môžeme zachovať pôvodný pomer strán obrázka.

Riadok 24 je miesto, kde sa skutočne mení veľkosť obrázka. Obrázok, ktorého veľkosť chceme zmeniť, je prvým argumentom a druhým sú rozmery, ktoré sme vypočítali pre nový obrázok. Naša interpolačná metóda, ktorá je algoritmom na zmenu veľkosti skutočného obrázka, je posledným parametrom.

Nakoniec, na Riadok 25 , zobrazíme náš zmenšený obrázok.

Predefinujeme náš pomer (aspectratio) na Riadok 31 . Výška nášho nového obrázka bude 70 pixelov. Vydelíme 70 pôvodnou výškou, aby sme dostali nový pomer výšky k pôvodnej výške.

Ďalej určíme rozmery nového obrázka. Nový obrázok bude mať výšku 70 pixelov, čo je už známe. Opäť môžeme zachovať pôvodný pomer strán obrázka vynásobením starej šírky pomerom, čím vytvoríme novú šírku.

Veľkosť obrázka sa potom skutočne zmení Riadok 35 a zobrazí sa na Riadok 36.

Tu vidíme, že sme zmenšili šírku a výšku nášho pôvodného obrázka pri zachovaní pomeru strán. Ak by nebol zachovaný pomer strán, náš obrázok by vyzeral zdeformovaný.

Záver

V tomto blogu sme študovali základné rôzne koncepty spracovania obrazu. Videli sme preklad obrázkov pomocou balíka OpenCV. Videli sme metódy na posúvanie obrazu nahor, nadol, doprava a doľava. Tieto metódy sú veľmi užitočné, keď vytvárame množinu údajov podobných obrázkov, ktoré sa majú poskytnúť ako množina trénovacích údajov, takže stroj uvidí rôzne obrázky, aj keď sú rovnaké. Tento článok vás tiež naučil, ako otočiť obrázok okolo ľubovoľného bodu v karteziánskom priestore pomocou rotačnej matice. Potom ste zistili, ako OpenCV otáča obrázky pomocou tejto matice a videli ste niekoľko ilustrácií rotujúcich obrázkov.

V tejto časti boli skúmané dve základné (ale významné) aritmetické operácie sčítania a odčítania. Ako vidíte, sčítanie a odčítanie základných matíc sú všetky aritmetické operácie s obrázkami.

Okrem toho sme použili OpenCV a NumPy na preskúmanie zvláštností aritmetiky obrázkov. Tieto obmedzenia musíte mať na pamäti, inak riskujete neočakávané výsledky pri vykonávaní aritmetických operácií s vašimi obrázkami.

Je dôležité si zapamätať, že hoci NumPy vykonáva modulovú operáciu a „zabalí sa“, hodnoty OpenCV sčítania a odčítania sú mimo rozsahu [0, 255], aby sa zmestili do rozsahu. Pri vývoji vlastných aplikácií počítačového videnia vám toto zapamätanie pomôže vyhnúť sa pátraniu po zložitých chybách.

Prevracanie obrázkov je nepochybne jedným z jednoduchších nápadov, ktoré v tomto kurze preskúmame. Preklápanie sa často používa v strojovom učení na generovanie viacerých vzoriek tréningových údajov, čo vedie k účinnejším a spoľahlivejším klasifikátorom obrázkov.

Tiež sme sa naučili, ako používať OpenCV na zmenu veľkosti obrázka. Pri zmene veľkosti obrázka je dôležité zvážiť metódu interpolácie, ktorú používate, aj pomer strán pôvodného obrázka, aby sa výsledok nezdal skreslený.

Nakoniec je dôležité si uvedomiť, že ak je problémom kvalita obrazu, vždy je najlepšie prejsť z väčšieho na menší. Vo väčšine prípadov zväčšovanie obrázka vytvára artefakty a zhoršuje jeho kvalitu.