Obrada slika OpenCV

Obrada Slika Opencv



U ovom ćemo članku proučiti metode obrade slike. Ispitat ćemo neke temeljne, ali kritične teme računalnog vida i strojnog učenja. Ove temeljne tehnike obrade slike mogu riješiti složene probleme, poput skupova podataka. Kao rezultat toga, postoji šest temeljnih koraka u obradi slike, koji su navedeni u nastavku:
  1. Prijevod slika
  2. Rotacija slike
  3. Slika Aritmetika
  4. Okretanje slike
  5. Obrezivanje slike
  6. Promjena veličine slike

Sada ćemo detaljno objasniti sve gore navedene teme obrade slike.

1. Prijevod slika

Prijevod slike je metoda obrade slike koja nam pomaže pomicati sliku duž x i y-osi. Sliku možemo pomicati gore, dolje, desno, lijevo ili bilo koju kombinaciju.







Matricu prevođenja možemo definirati simbolom M i možemo je predstaviti u matematičkom obliku, kao što je prikazano u nastavku:





Kroz ovaj program možemo razumjeti koncept slike prijevoda.





Python kôd: Zadržat ćemo sljedeći naziv programa kao prevesti.py .

# uvoz potrebnih paketa

uvoz numpy kao npr.

uvoz argparse

uvoz imutil

uvoz cv2

# implementiramo parser argumenata

ap_obj = argparse. ArgumentParser ( )

ap_obj. dodaj_argument ( '-k' , '--slika' , potreban = Pravi ,

Pomozite = 'lokacija slikovne datoteke' )

args = čiji ( ap_obj. parse_args ( ) )

# učitajte sliku i pokažite je na ekranu

slika = cv2. imread ( args [ 'slika' ] )

cv2. imshow ( 'Originalna_slika' , slika )

# Prijevod slike je NumPy matrica koja je dana u nastavku:

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

# Koristit ćemo gornju NumPy matricu za pomicanje slika duž

# smjerovi x-osi i y-osi. Za ovo moramo jednostavno proslijediti vrijednosti piksela.

# U ovom programu pomaknut ćemo sliku 30 piksela udesno

# i 70 piksela prema dnu.

prijevod_mat = npr. plovak32 ( [ [ 1 , 0 , 30 ] , [ 0 , 1 , 70 ] ] )

prijevod_slike = cv2. warpAffine ( slika , prijevod_mat ,

( slika. oblik [ 1 ] , slika. oblik [ 0 ] ) )

cv2. imshow ( 'Prijevod slike dolje i desno' , prijevod_slike )

# sada ćemo upotrijebiti gornju NumPy matricu za pomicanje slika duž

# smjerovi x-osi (lijevo) i y-osi (gore).

# Ovdje ćemo pomaknuti slike 50 piksela ulijevo

# i 90 piksela prema gore.

prijevod_mat = npr. plovak32 ( [ [ 1 , 0 , - pedeset ] , [ 0 , 1 , - 90 ] ] )

prijevod_slike = cv2. warpAffine ( slika , prijevod_mat ,

( slika. oblik [ 1 ] , slika. oblik [ 0 ] ) )

cv2. imshow ( 'Prijevod slike gore i lijevo' , prijevod_slike )

cv2. čekajKljuč ( 0 )

Redovi 1 do 5: Uvozimo sve potrebne pakete za ovaj program, kao što su OpenCV, argparser i NumPy. Imajte na umu da postoji još jedna biblioteka koja je imutils. Ovo nije paket OpenCV-a. Ovo je samo biblioteka koja će lako prikazati istu obradu slike.



Biblioteka imutils neće biti uključena automatski kada instaliramo OpenCV. Dakle, da bismo instalirali imutils, moramo koristiti sljedeću metodu:

pip instaliraj imutils

Redovi 8 do 15: Napravili smo naš agrparser i učitali našu sliku.

Redovi 24 do 25: Ovaj odjeljak programa je mjesto gdje se odvija prijevod. Prijevodna matrica nam govori koliko će se piksela slika pomaknuti gore ili dolje ili ulijevo ili udesno. Budući da OpenCV zahtijeva da vrijednost matrice bude u nizu s pomičnim zarezom, matrica prijevoda uzima vrijednosti u nizovima s pomičnim zarezom.

Prvi red matrice prijevoda izgleda ovako:

Ovaj redak matrice je za x-osu. Vrijednost t x će odlučiti hoće li se slika pomaknuti u lijevu ili desnu stranu. Ako prenesemo negativnu vrijednost, to znači da će slika biti pomaknuta ulijevo, a ako je vrijednost pozitivna, to znači da će slika biti pomaknuta udesno.

Sada ćemo definirati drugi redak matrice na sljedeći način:

Ovaj redak matrice je za y-os. Vrijednost t Y će odlučiti hoće li se slika pomaknuti gore ili dolje. Ako prenesemo negativnu vrijednost, to znači da će slika biti pomaknuta prema gore, a ako je vrijednost pozitivna, to znači da će slika biti pomaknuta prema dolje.

U prethodnom programu u retku 24 definiramo t x = 30 i t Y = 70. Dakle, pomičemo sliku 30 piksela prema desnoj strani i 70 piksela prema dolje.

Ali glavni proces prevođenja slike odvija se u retku 25, gdje definiramo matricu prevođenja cv2.warpAffine . U ovoj funkciji prosljeđujemo tri parametra: prvi parametar je slika, drugi parametar je matrica prevođenja, a treći parametar je dimenzija slike.

Redak 27: Linija 27 će prikazati rezultat u izlazu.

Sada ćemo implementirati drugu matricu prevođenja za lijevu i gornju stranu. Za ovo moramo definirati negativne vrijednosti.

Redak 33 do 34: U prethodnom programu u retku 33 definiramo t x = -50 i t Y = -90. Dakle, pomičemo sliku 50 piksela prema lijevoj strani i 90 piksela prema gore. Ali glavni proces prevođenja slike odvija se u retku 34, gdje definiramo matricu prevođenja cv2.warpAffine .

Linija 36 : Linija 36 će prikazati rezultat kao što je prikazano u izlazu.

Da bismo pokrenuli prethodni kod, moramo dati putanju slike kao što je navedeno u nastavku.

Izlaz: python translate.py –slika vjeverica.jpg

Sada ćemo implementirati isti program za prevođenje slika koristeći imutil knjižnica. Ova je biblioteka vrlo jednostavna za korištenje za obradu slika. U ovoj knjižnici ne moramo razmišljati o cv2.warpAffine jer će se ova knjižnica pobrinuti za ovo. Dakle, implementirajmo ovaj program za prevođenje slika pomoću biblioteke imutils.

Python kôd: Zadržat ćemo sljedeći naziv programa kao translate_imutils.py .

# uvoz potrebnih paketa

uvoz numpy kao npr.

uvoz argparse

uvoz imutil

uvoz cv2

# Ova funkcija implementira prijevod slike i

# vraća prevedenu sliku pozivnoj funkciji.

def Prevedi ( slika , x , Y ) :

prijevodna_matrica = npr. plovak32 ( [ [ 1 , 0 , x ] , [ 0 , 1 , Y ] ] )

prijevod_slike = cv2. warpAffine ( slika , prijevodna_matrica ,

( slika. oblik [ 1 ] , slika. oblik [ 0 ] ) )

povratak prijevod_slike

# konstruirajte parser argumenata i analizirajte argumente

ap = argparse. ArgumentParser ( )

ap. dodaj_argument ( '-i' , '--slika' , potreban = Pravi , Pomozite = 'Put do slike' )

args = čiji ( ap. parse_args ( ) )

# učitavanje slike i prikaz na ekranu

slika = cv2. imread ( args [ 'slika' ] )

cv2. imshow ( 'Originalna_slika' , slika )

prijevod_slike = imutil. Prevedi ( slika , 10 , 70 )

cv2. imshow ( 'Prijevod slike udesno i dolje' ,

prijevod_slike )

cv2. čekajKljuč ( 0 )

Redovi 9 do 13: Ovaj dio programa mjesto je gdje se odvija prijevod. Prijevodna matrica nam govori za koliko piksela će se slika pomaknuti gore ili dolje ili ulijevo ili udesno.

Ovi redovi su već objašnjeni, ali sada ćemo izgraditi funkciju koja se zove translate () i poslati tri različita parametra u nju. Sama slika služi kao prvi parametar. Vrijednosti x i y translacijske matrice odgovaraju drugom i trećem parametru.

Bilješka : Nema potrebe definirati ovu funkciju prevođenja unutar programa jer je već uključena u paket knjižnice imutils. Koristio sam ga unutar programa radi jednostavnog objašnjenja. Ovu funkciju možemo pozvati izravno pomoću imutila, kao što je prikazano u retku 24.

Redak 24: Prethodni program će pokazati da u retku 24 definiramo tx = 10 i ty = 70. Dakle, pomičemo sliku 10 piksela prema desnoj strani i 70 piksela prema dolje.

U ovom programu ne zanimaju nas funkcije cv2.warpAffine jer se one već nalaze unutar paketa knjižnice imutils.

Da bismo pokrenuli prethodni kod, moramo dati putanju slike, kao što je navedeno u nastavku:

Izlaz:

python imutils. py -- slika vjeverica. jpg

2. Rotacija slike

Prošli smo kroz kako prevesti (tj. pomaknuti) sliku gore, dolje, lijevo i desno u prethodnoj lekciji (ili bilo kojoj kombinaciji). Zatim ćemo razgovarati o rotaciji koja se odnosi na obradu slike.

Slika se rotira za kut, theta, u procesu poznatom kao rotacija. Kut za koji rotiramo sliku bit će predstavljen theta. Dodatno, naknadno ću omogućiti praktičnu funkciju rotiranja kako bih rotiranje slika učinio jednostavnijim.

Slično translaciji, i možda ne iznenađuje, rotaciji za kut, theta se određuje izgradnjom matrice M u sljedećem formatu:

Ova matrica može rotirati vektor theta stupnjeva (u smjeru suprotnom od kazaljke na satu) oko ishodišta zadane (x, y)-kartezijeve ravnine. Uobičajeno, u ovom scenariju, ishodište bi bilo središte slike, ali zapravo bismo mogli označiti bilo koju slučajnu (x, y) točku kao naše središte rotacije.

Rotirana slika R zatim se stvara iz izvorne slike I korištenjem izravnog matričnog množenja: R = IM

OpenCV, s druge strane, dodatno nudi mogućnost (1) skaliranja (tj. promjene veličine) slike i (2) ponude središta proizvoljne rotacije za izvođenje rotacije.

Naša modificirana matrica rotacije M prikazana je u nastavku:

Počnimo otvaranjem i generiranjem nove datoteke pod nazivom rotirati.py :

# uvoz potrebnih paketa

uvoz numpy kao npr.

uvoz argparse

uvoz imutil

uvoz cv2

# stvaranje argumentparser objekta i parsiranje argumenta

apobj = argparse. ArgumentParser ( )

apobj. dodaj_argument ( '-k' , '--slika' , potreban = Pravi , Pomozite = 'put slike' )

argumenti = čiji ( apobj. parse_args ( ) )

slika = cv2. imread ( argumenti [ 'slika' ] )

cv2. imshow ( 'Originalna_slika' , slika )

# Izračunajte središte slike pomoću dimenzija slike.

( visina , širina ) = slika. oblik [ : 2 ]

( centarX , centarY ) = ( širina / 2 , visina / 2 )

# Sada ćemo, koristeći cv2, rotirati sliku za 55 stupnjeva na

# odredite matricu rotacije koristeći getRotationMatrix2D()

rotacijska matrica = cv2. getRotationMatrix2D ( ( centarX , centarY ) , 55 , 1.0 )

rotatedImage = cv2. warpAffine ( slika , rotacijska matrica , ( širina , visina ) )

cv2. imshow ( 'Slika je rotirana za 55 stupnjeva' , rotatedImage )

cv2. čekajKljuč ( 0 )

# Slika će sada biti rotirana za -85 stupnjeva.

rotacijska matrica = cv2. getRotationMatrix2D ( ( centarX , centarY ) , - 85 , 1.0 )

rotatedImage = cv2. warpAffine ( slika , rotacijska matrica , ( širina , visina ) )

cv2. imshow ( 'Slika je rotirana za -85 stupnjeva' , rotatedImage )

cv2. čekajKljuč ( 0 )

Redovi 1 do 5: Uvozimo sve potrebne pakete za ovaj program, kao što su OpenCV, argparser i NumPy. Imajte na umu da postoji još jedna biblioteka koja je imutils. Ovo nije paket OpenCV-a. Ovo je samo biblioteka koja će se koristiti za jednostavno prikazivanje iste obrade slike.

Biblioteka imutils neće biti uključena automatski kada instaliramo OpenCV. OpenCV instalira imutils. Moramo koristiti sljedeću metodu:

pip instaliraj imutils

Redovi 8 do 14: Napravili smo naš agrparser i učitali našu sliku. U ovom argparseru koristimo samo jedan argument slike, koji će nam reći putanju slike koju ćemo koristiti u ovom programu za demonstraciju rotacije.

Kada rotiramo sliku, moramo definirati točku zakretanja rotacije. Većinu vremena ćete htjeti rotirati sliku oko središta, ali OpenCV vam omogućuje da umjesto toga odaberete bilo koju slučajnu točku. Jednostavno zarotirajmo sliku oko središta.

Redovi 17 do 18 uzmite širinu i visinu slike, a zatim podijelite svaku dimenziju s dva kako biste odredili središte slike.

Konstruiramo matricu za rotiranje slike na isti način na koji smo definirali matricu za prevođenje slike. Samo ćemo nazvati cv2.getRotationMatrix2D funkcioniraju na liniji 22 umjesto da ručno stvaraju matricu koristeći NumPy (što može biti malo glomazno).

The cv2.getRotationMatrix2D funkcija zahtijeva tri parametra. Prvi unos je željeni rotacijski kut (u ovom slučaju središte slike). Theta se zatim koristi za određivanje za koliko stupnjeva (u smjeru suprotnom od kazaljke na satu) ćemo rotirati sliku. Ovdje ćemo rotirati sliku za 45 stupnjeva. Konačna opcija povezana je s veličinom slike.

Bez obzira na činjenicu da još nismo razgovarali o skaliranju slike, ovdje možete dati broj s pomičnim zarezom s 1,0 koji označava da se slika treba koristiti u izvornim omjerima. Međutim, ako ste upisali vrijednost 2.0, slika bi se udvostručila. Broj od 0,5 tako smanjuje veličinu slike.

Redak 22 do 23: Nakon što primimo našu rotacijsku matricu M od cv2.getRotationMatrix2D funkciju, okrećemo našu sliku pomoću cv2.warpAffine tehnika na liniji 23. Prvi unos funkcije je slika koju želimo rotirati. Zatim se definiraju širina i visina naše izlazne slike, zajedno s našom matricom rotacije M. U liniji 23, slika se zatim rotira za 55 stupnjeva.

Možete primijetiti da je naša slika rotirana.

Redovi 28 do 30 čine drugu rotaciju. Linije 22–23 koda su identične, osim što ovaj put rotiramo za -85 stupnjeva umjesto 55.

Jednostavno smo rotirali sliku oko središta do ove točke. Što ako želimo rotirati sliku oko nasumične točke?

Počnimo otvaranjem i generiranjem nove datoteke pod nazivom rotirati.py:

# uvoz potrebnih paketa

uvoz numpy kao npr.

uvoz argparse

uvoz imutil

uvoz cv2

# stvaranje argumentparser objekta i parsiranje argumenta

ap_obj = argparse. ArgumentParser ( )

ap_obj. dodaj_argument ( '-k' , '--slika' , potreban = Pravi , Pomozite = 'put slike' )

argument = čiji ( ap_obj. parse_args ( ) )

# učitavanje slike i prikaz na ekranu

slika = cv2. imread ( argument [ 'slika' ] )

cv2. imshow ( 'Originalna_slika' , slika )

# Izračunajte središte slike pomoću dimenzija slike.

( visina , širina ) = slika. oblik [ : 2 ]

( centarX , centarY ) = ( širina / 2 , visina / 2 )

# Sada ćemo, koristeći cv2, rotirati sliku za 55 stupnjeva na

# odredite matricu rotacije koristeći getRotationMatrix2D()

rotacijska matrica = cv2. getRotationMatrix2D ( ( centarX , centarY ) , 55 , 1.0 )

rotatedImage = cv2. warpAffine ( slika , rotacijska matrica , ( širina , visina ) )

cv2. imshow ( 'Slika je rotirana za 55 stupnjeva' , rotatedImage )

cv2. čekajKljuč ( 0 )

# Slika će sada biti rotirana za -85 stupnjeva.

rotacijska matrica = cv2. getRotationMatrix2D ( ( centarX , centarY ) , - 85 , 1.0 )

rotatedImage = cv2. warpAffine ( slika , rotacijska matrica , ( širina , visina ) )

cv2. imshow ( 'Slika je rotirana za -85 stupnjeva' , rotatedImage )

cv2. čekajKljuč ( 0 )

# rotacija slike iz neke proizvoljne točke, ne iz središta

rotacijska matrica = cv2. getRotationMatrix2D ( ( centarX - 40 , centarY - 40 ) , 55 , 1.0 )

rotatedImage = cv2. warpAffine ( slika , rotacijska matrica , ( širina , visina ) )

cv2. imshow ( 'Rotacija slike iz proizvoljnih točaka' , rotatedImage )

cv2. čekajKljuč ( 0 )

Redak 34 do 35: Sada bi se ovaj kod trebao činiti prilično uobičajenim za rotiranje objekta. Za rotiranje slike oko točke 40 piksela ulijevo i 40 piksela iznad središta, dajemo upute cv2.getRotationMatrix2D obratiti pozornost na svoj prvi parametar.

Slika nastala kada primijenimo ovu rotaciju prikazana je u nastavku:

Jasno možemo vidjeti da je središte rotacije sada (x, y)-koordinata, koja je 40 piksela ulijevo i 40 piksela iznad izračunatog središta slike.

3. Aritmetika slike

Zapravo, slikovna aritmetika samo je zbrajanje matrice s nekoliko dodatnih ograničenja na tipove podataka koje ćemo pokriti kasnije.

Uzmimo trenutak da prođemo kroz neke lijepe osnove linearne algebre.

Razmislite o kombiniranju sljedeće dvije matrice:

Kakav bi rezultat dalo zbrajanje matrica? Jednostavan odgovor je zbroj unosa matrice, element po element:

Dovoljno jednostavno, zar ne?

U ovom trenutku svi razumijemo temeljne operacije zbrajanja i oduzimanja. Međutim, moramo voditi računa o ograničenjima koja nameću naš prostor boja i tip podataka dok radimo sa slikama.

Pikseli u RGB slikama, na primjer, nalaze se između [0, 255]. Što se događa ako pokušamo dodati 10 pikselu s intenzitetom 250 dok ga gledamo?

Došli bismo do vrijednosti 260 ako bismo primijenili standardna aritmetička načela. 260 nije važeća vrijednost jer su RGB slike predstavljene kao 8-bitni cijeli brojevi bez predznaka.

Dakle, što bi se trebalo dogoditi? Trebamo li pokrenuti provjeru kako bismo osigurali da nijedan piksel nije izvan raspona od [0, 255], odsijecajući svaki piksel da ima vrijednost između 0 i 255?

Ili se 'zamotamo' i izvedemo operaciju modula? U skladu s pravilima modula, dodavanje 10 na 255 rezultiralo bi samo vrijednošću 9.

Kako treba postupati s dodavanjima i oduzimanjima slika izvan raspona [0, 255]?

Istina je da ne postoji ispravna ili pogrešna tehnika; sve ovisi o tome kako radite sa svojim pikselima i što se nadate postići.

Ali zapamtite da postoje razlike između zbrajanja u OpenCV-u i zbrajanja u NumPy-ju. NumPy će obaviti modulsku aritmetiku i 'omotavanje'. Nasuprot tome, OpenCV će izvršiti izrezivanje i pobrinuti se da vrijednosti piksela nikada ne napuste raspon [0, 255].

Počnimo stvaranjem nove datoteke pod nazivom aritmetika.py i otvori ga:

# python arithmetic.py --image squirrel.jpg

# uvoz potrebnih paketa

uvoz numpy kao npr.

uvoz argparse

uvoz imutil

uvoz cv2

# stvaranje argumentparser objekta i parsiranje argumenta

apObj = argparse. ArgumentParser ( )

apObj. dodaj_argument ( '-k' , '--slika' , potreban = Pravi , Pomozite = 'put slike' )

argumenti = čiji ( apObj. parse_args ( ) )

slika = cv2. imread ( argumenti [ 'slika' ] )

cv2. imshow ( 'Originalna_slika' , slika )

'''

Vrijednosti naših piksela bit će u rasponu [0, 255]

jer su slike NumPy nizovi, koji su pohranjeni kao nepredpisani 8-bitni cijeli brojevi.

Kada koristite funkcije kao što su cv2.add i cv2.subtract, vrijednosti će biti izrezane

ovom rasponu čak i ako se dodaju ili oduzmu izvan

[0, 255] raspon. Evo ilustracije:

'''


ispisati ( 'maksimalno 255: {}' . format ( str ( cv2. dodati ( npr. uint8 ( [ 201 ] ) ,

npr. uint8 ( [ 100 ] ) ) ) ) )

ispisati ( 'minimalno 0: {}' . format ( str ( cv2. oduzeti ( npr. uint8 ( [ 60 ] ) ,

npr. uint8 ( [ 100 ] ) ) ) ) )

'''

Kada izvodite aritmetičke operacije s ovim nizovima koristeći NumPy,

vrijednost će se omotati umjesto da bude ošišana na

[0, 255]raspon. Kada koristite slike, važno je to zadržati

na umu.

'''


ispisati ( 'zaokruži: {}' . format ( str ( npr. uint8 ( [ 201 ] ) + npr. uint8 ( [ 100 ] ) ) ) )

ispisati ( 'zaokruži: {}' . format ( str ( npr. uint8 ( [ 60 ] ) - npr. uint8 ( [ 100 ] ) ) ) )

'''

Pomnožimo svjetlinu svakog piksela na našoj slici sa 101.

Da bismo to učinili, generiramo NumPy polje iste veličine kao naša matrica,

ispunjeno jedinicama i pomnožite ga sa 101 da dobijete ispunjen niz

sa 101s. Na kraju spajamo dvije slike.

Primijetit ćete da je slika sada 'svjetlija'.

'''


Matrica = npr. one ( slika. oblik , dtype = 'uint8' ) * 101

slika_dodana = cv2. dodati ( slika , Matrica )

cv2. imshow ( 'Rezultat dodane slike' , slika_dodana )

#Na sličan način, možemo učiniti svoju sliku tamnijom uzimanjem

# 60 udaljen od svih piksela.

Matrica = npr. one ( slika. oblik , dtype = 'uint8' ) * 60

slika_oduzeta = cv2. oduzeti ( slika , Matrica )

cv2. imshow ( 'Rezultat oduzete slike' , slika_oduzeta )

cv2. čekajKljuč ( 0 )

Redovi od 1 do 16 koristit će se za izvođenje našeg normalnog procesa, koji uključuje uvoz naših paketa, konfiguriranje našeg parsera argumenata i učitavanje naše slike.

Sjećate li se kako sam ranije raspravljao o razlici između OpenCV i NumPy dodatka? Sad kad smo to temeljito obradili, pogledajmo konkretan slučaj kako bismo bili sigurni da ga razumijemo.

Dva 8-bitna NumPy niza cijelih brojeva bez predznaka definirana su na linija 26 . Vrijednost 201 je jedini element u prvom nizu. Iako je samo jedan član u drugom polju, on ima vrijednost 100. Vrijednosti se zatim zbrajaju pomoću OpenCV-ove funkcije cv2.add.

Što očekujete da će biti rezultat?

U skladu s konvencionalnim aritmetičkim načelima, odgovor bi trebao biti 301. Ali zapamtite da imamo posla s 8-bitnim cijelim brojevima bez predznaka, koji mogu biti samo u rasponu [0, 255]. Budući da koristimo metodu cv2.add, OpenCV rukuje isjecanjem i osigurava da zbrajanje vrati maksimalni rezultat od 255.

Prvi redak popisa u nastavku prikazuje ishod pokretanja ovog koda:

aritmetika. py

maksimalno od 255 : [ [ 255 ] ]

Zbroj je doista proizveo broj od 255.

Nakon toga, linija 26 koristi cv2.subtract za postizanje oduzimanja. Još jednom definiramo dva NumPy niza 8-bitnih cijelih brojeva bez predznaka s jednim elementom u svakom. Vrijednost prvog niza je 60, dok je vrijednost drugog niza 100.

Naša aritmetika nalaže da bi oduzimanje trebalo rezultirati vrijednošću od -40, ali OpenCV ponovno rješava izrezivanje umjesto nas. Otkrivamo da je vrijednost smanjena na 0. Naš rezultat u nastavku to pokazuje:

aritmetika. py

minimum od 0 : [ [ 0 ] ]

Koristeći cv2, oduzmite 100 od 60 oduzmite, dajući vrijednost 0.

Ali što se događa ako upotrijebimo NumPy umjesto OpenCV-a za izvođenje izračuna?

Linije 38 i 39 riješiti ovo pitanje.

Prvo se definiraju dva 8-bitna nepredznačena niza cijelih brojeva NumPy s po jednim elementom. Vrijednost prvog niza je 201, dok je vrijednost drugog niza 100. Naše bi zbrajanje bilo skraćeno, a vratila bi se vrijednost 255 ako bismo koristili funkciju cv2.add.

NumPy, s druge strane, 'omata' i radi modulo aritmetiku umjesto izrezivanja. NumPy se vraća na nulu kada se dosegne vrijednost od 255, a zatim nastavlja brojati dok se ne dosegne 100 koraka. To potvrđuje prva linija izlaza, koja je prikazana u nastavku:

aritmetika. py
omotati oko: [ Četiri pet ]

Zatim se definiraju još dva NumPy niza, jedan s vrijednošću 50, a drugi sa 100. Ovo bi oduzimanje bilo skraćeno metodom cv2.subtract kako bi se vratio rezultat 0. Ali svjesni smo da umjesto izrezivanja, NumPy izvršava modulo aritmetika. Umjesto toga, modulo procedure se okreću i počinju brojati unatrag od 255 kada se tijekom oduzimanja dosegne 0. To možemo vidjeti iz sljedećeg izlaza:

aritmetika. py

omotati oko: [ 207 ]

Još jednom, naš izlaz terminala pokazuje razliku između izrezivanja i omatanja oko:

Ključno je imati na umu željeni rezultat kada izvodite cjelobrojnu aritmetiku. Želite li da se vrijednosti izvan raspona [0, 255] izrežu? Nakon toga upotrijebite tehnike aritmetike slike ugrađene u OpenCV.

Želite li da se vrijednosti prelamaju ako su izvan raspona [0, 255] i modulskih aritmetičkih operacija? NumPy nizovi se zatim jednostavno dodaju i oduzimaju kao i obično.

Linija 48 definira jednodimenzionalni NumPy niz istih dimenzija kao naša slika. Još jednom, osiguravamo da je naš tip podataka 8-bitni cijeli broj bez predznaka. Jednostavno pomnožimo našu matricu jednoznamenkastih vrijednosti sa 101 da bismo je ispunili vrijednostima 101 umjesto 1. Na kraju, koristimo funkciju cv2.add da dodamo našu matricu 100s izvornoj slici. Ovo povećava intenzitet svakog piksela za 101, a istovremeno osigurava da sve vrijednosti koje pokušaju prijeći 255 budu ošišane na raspon [0, 255].

Promatrajte kako je slika osjetno svjetlija i izgleda 'ispranije' od originala. To je zato što tjeramo piksele prema svjetlijim bojama povećanjem intenziteta njihovih piksela za 101.

Kako bismo oduzeli 60 od svakog intenziteta piksela slike, prvo uspostavljamo drugi NumPy niz na liniji 54 koji je ispunjen 60-ima.

Ishodi ovog oduzimanja prikazani su na sljedećoj slici:

Predmeti oko nas izgledaju znatno tamnije nego prije. To je zato što oduzimanjem 60 od svakog piksela pomičemo piksele u RGB prostoru boja u tamnija područja.

4. Okretanje slike

Slično rotaciji, okretanje slike preko njene x ili y-osi još je jedna opcija koju nudi OpenCV. Čak i ako se operacije okretanja ne koriste tako često, poznavanje njih je nevjerojatno korisno iz raznih razloga koje možda nećete odmah vidjeti.

Razvijamo klasifikator strojnog učenja za malu startup tvrtku koja nastoji identificirati lica na slikama. Da bi naš sustav 'naučio' što je lice, trebat će nam neka vrsta skupa podataka s uzorcima lica. Nažalost, tvrtka nam je dala samo mali skup podataka od 40 lica i ne možemo prikupiti više informacija.

Što ćemo onda učiniti?

Budući da lice ostaje lice bez obzira na to je li zrcalno ili ne, možemo vodoravno okrenuti svaku sliku lica i koristiti zrcalne verzije kao dodatne podatke za obuku.

Ovaj primjer može djelovati glupo i umjetno, ali nije. Flipping je namjerna strategija koju koriste jaki algoritmi dubokog učenja za proizvodnju više podataka tijekom faze obuke.

Iz prethodnog je jasno da metode obrade slike koje učite u ovom modulu služe kao temelj za veće sustave računalnog vida.

Ciljevi:

Koristiti cv2.okrenuti funkciju, u ovoj ćete sesiji naučiti kako okrenuti sliku vodoravno i okomito.

Okretanje je sljedeća manipulacija slikom koju ćemo proučavati. X i y-os slike mogu se okrenuti ili čak obje. Prije nego što zaronimo u kodiranje, najbolje je prvo pogledati rezultate okretanja slike. Pogledajte sliku koja je vodoravno okrenuta na sljedećoj slici:


Obratite pažnju na to kako je naša izvorna slika na lijevoj strani i kako je slika vodoravno zrcaljena na desnoj strani.

Počnimo stvaranjem nove datoteke pod nazivom okretanje.py .

Vidjeli ste primjer okretanja slike, pa pogledajmo kôd:

# python flipping.py --image quirrel.jpg

# uvoz potrebnih paketa

uvoz argparse

uvoz cv2

# stvaranje objekta parsera argumenata i parsiranje argumenta

apObj = argparse. ArgumentParser ( )

apObj. dodaj_argument ( '-i' , '--slika' , potreban = Pravi , Pomozite = 'put slike' )

argument = čiji ( apObj. parse_args ( ) )

slika = cv2. imread ( argument [ 'slika' ] )

cv2. imshow ( 'Izvornik' , slika )

# horizontalno okreni sliku

imageflipped = cv2. okrenuti ( slika , 1 )

cv2. imshow ( 'Okrenuta slika vodoravno' , imageflipped )

# okomito okreni sliku

imageflipped = cv2. okrenuti ( slika , 0 )

cv2. imshow ( 'Okomito okrenuta slika' , imageflipped )

# okretanje slike duž obje osi

imageflipped = cv2. okrenuti ( slika , - 1 )

cv2. imshow ( 'Okrenuto vodoravno i okomito' , imageflipped )

cv2. čekajKljuč ( 0 )

Koraci koje poduzimamo za uvoz naših paketa, raščlanjivanje naših ulaza i učitavanje naše slike s diska obrađuju se u l od 1 do 12 .

Pozivanjem funkcije cv2.flip on redak 15 , sliku je jednostavno okrenuti vodoravno. Slika koju želimo okrenuti i određeni kod ili oznaka koja specificira kako okrenuti sliku dva su argumenta potrebna za metodu cv2.flip.

Vrijednost koda za okretanje 1 znači da ćemo rotirati sliku oko y-osi da bismo je okrenuli vodoravno ( redak 15 ). Ako navedemo kod okretanja 0, želimo rotirati sliku oko x-osi ( Redak 19 ). Negativni flip kod ( Linija 23 ) rotira sliku po obje osi.

Jedan od najlakših primjera u ovoj temi je okretanje slike, što je osnovno.

Zatim ćemo razgovarati o izrezivanju slika i korištenju NumPy nizova za izdvajanje određenih dijelova slike.

5. Obrezivanje slike

Izrezivanje, kao što naziv implicira, je proces odabira i uklanjanja regije interesa (ili jednostavno ROI), što je područje slike koje nas zanima.

Lice bi se moralo izrezati sa slike za aplikaciju za prepoznavanje lica. Osim toga, ako smo stvarali Python skriptu za pronalaženje pasa na slikama, mogli bismo izrezati psa sa slike kada ga pronađemo.

Ciljevi: Naš glavni cilj je upoznati se s rezanjem niza NumPy za obrezivanje područja sa slike i s lakoćom ga koristiti.

Obrezivanje : Kada obrezujemo sliku, cilj nam je ukloniti vanjske elemente koji nas ne zanimaju. Proces odabira našeg ROI-a često se naziva odabir naše regije interesa.

Napravite novu datoteku pod nazivom crop.py , otvorite ga i dodajte sljedeći kod:

# python crop.py

# uvoz potrebnih paketa

uvoz cv2

# učitavanje slike i prikaz na ekranu

slika = cv2. imread ( 'vjeverica.jpg' )

ispisati ( slika. oblik )

cv2. imshow ( 'Izvornik' , slika )

# Isječci polja NumPy koriste se za brzo rezanje slike

# izrezat ćemo lice vjeverice sa slike

lice vjeverice = slika [ 35 : 90 , 35 : 100 ]

cv2. imshow ( 'lice vjeverice' , lice vjeverice )

cv2. čekajKljuč ( 0 )

# A sada, ovdje ćemo izrezati cijelo tijelo

# od vjeverice

tijelo vjeverice = slika [ 35 : 148 , 23 : 143 ]

cv2. imshow ( 'Tijelo vjeverice' , tijelo vjeverice )

cv2. čekajKljuč ( 0 )

Prikazat ćemo obrezivanje u Pythonu i OpenCV-u pomoću slike koju učitamo s diska Redci 5 i 6 .

Izvorna slika koju ćemo izrezati

Koristeći samo osnovne tehnike izrezivanja, nastojimo odvojiti lice i tijelo vjeverice od okolnog područja.

Iskoristit ćemo naše prethodno znanje o slici i ručno unijeti isječke NumPy niza gdje se nalaze tijelo i lice. U normalnim uvjetima općenito bismo koristili algoritme strojnog učenja i računalnog vida za prepoznavanje lica i tijela na slici. No neka zasad stvari budu jasne i izbjegavajmo korištenje bilo kakvih modela detekcije.

Lice na slici možemo identificirati samo jednom linijom koda. redak 13 , Za izdvajanje pravokutnog dijela slike, počevši od (35, 35), nudimo NumPy nizove (90, 100). Može se činiti zbunjujućim da isječak hranimo indeksima prema redoslijedu prvo visina i širina, ali imajte na umu da OpenCV pohranjuje slike kao NumPy nizove. Kao rezultat toga, moramo unijeti vrijednosti za y-os prije x-osi.

NumPy zahtijeva sljedeća četiri indeksa za izvođenje izrezivanja:

Početak y: Y-koordinata na početku. Za ovaj primjer, počinjemo od y=35.

Kraj y: Y koordinata na kraju. Naš usjev će prestati kada je y = 90.

Početak x: X koordinata početka presjeka. Obrezivanje počinje na x=35.

Kraj x: Krajnja koordinata x-osi presjeka. Na x=100, naša kriška je gotova.

Slično, izrezujemo regije (23, 35) i (143, 148) s izvorne slike kako bismo izvukli cijelo tijelo iz slike na Redak 19 .

Možete primijetiti da je slika izrezana kako bi se prikazalo samo tijelo i lice.

6. Promjena veličine slike

Proces povećanja ili smanjenja širine i visine slike poznat je kao skaliranje ili jednostavno mijenjanje veličine. Omjer slike, koji je omjer širine slike i njezine visine, treba uzeti u obzir prilikom promjene veličine slike. Zanemarivanje omjera širine i visine može rezultirati slikama koje su skalirane i izgledaju komprimirano i iskrivljeno:

Naša početna slika je lijevo. Na desnoj strani vidjet ćete dvije slike koje su skalirane bez održavanja omjera slike, što narušava omjer širine slike i njezine visine. Kada mijenjate veličinu svojih slika, općenito biste trebali uzeti u obzir omjer slike.

Tehnika interpolacije koju koristi naš algoritam za promjenu veličine također mora uzeti u obzir cilj funkcije interpolacije za korištenje ovih susjedstava piksela za povećanje ili smanjenje veličine slike.

Općenito, smanjivanje veličine slike daleko je učinkovitije. To je zato što je uklanjanje piksela sa slike sve što funkcija interpolacije treba učiniti. S druge strane, metoda interpolacije trebala bi 'popuniti praznine' između piksela koji prethodno nisu postojali ako se želi povećati veličina slike.

Imamo našu originalnu sliku s lijeve strane. Slika je smanjena na pola svoje izvorne veličine u sredini, ali osim toga, nije došlo do gubitka 'kvalitete' slike. Ipak, veličina slike je znatno povećana na desnoj strani. Sada izgleda 'napuhano' i 'pikselizirano'.

Kao što sam već rekao, obično ćete htjeti smanjiti veličinu slike umjesto da je povećate. Smanjenjem veličine slike analiziramo manje piksela i moramo se nositi s manje 'šuma', što algoritme za obradu slike čini bržima i preciznijima.

Translacija i rotacija dvije su transformacije slike kojima smo se do sada bavili. Sada ćemo ispitati kako promijeniti veličinu slike.

Ne iznenađuje da ćemo mijenjati veličinu naših slika pomoću metode cv2.resize. Kao što sam ranije naznačio, moramo uzeti u obzir omjer slike kada koristimo ovu metodu. Ali prije nego što uđemo preduboko u pojedinosti, dopustite mi da vam dam ilustraciju:

# python resize.py --image squirrel.jpg

# uvoz potrebnih paketa

uvoz argparse

uvoz cv2

# stvaranje objekta parsera argumenata i parsiranje argumenta

apObj = argparse. ArgumentParser ( )

apObj. dodaj_argument ( '-k' , '--slika' , potreban = Pravi , Pomozite = 'put slike' )

argumenti = čiji ( apObj. parse_args ( ) )

# učitavanje slike i prikaz na ekranu

slika = cv2. imread ( argumenti [ 'slika' ] )

cv2. imshow ( 'Izvornik' , slika )

# Kako biste spriječili da slika izgleda iskrivljeno, omjer slike

# mora se uzeti u obzir ili deformirati; dakle, shvatit ćemo što

# omjer nove slike u odnosu na trenutnu sliku.

# Neka širina naše nove slike bude 160 piksela.

aspekt = 160.0 / slika. oblik [ 1 ]

dimenzija = ( 160 , int ( slika. oblik [ 0 ] * aspekt ) )

# ovaj redak će pokazati stvarne operacije promjene veličine

promijenjena veličina slike = cv2. promijeniti veličinu ( slika , dimenzija , interpolacija = cv2. INTER_AREA )

cv2. imshow ( 'Promijenjena veličina širine slike' , promijenjena veličina slike )

# Što ako želimo promijeniti visinu slike? - koristiti

# isti princip, možemo izračunati omjer na temelju

# na visinu, a ne na širinu. Napravimo skaliranje

# visina slike 70 piksela.

aspekt = 70.0 / slika. oblik [ 0 ]

dimenzija = ( int ( slika. oblik [ 1 ] * aspekt ) , 70 )

# izvedite promjenu veličine

promijenjena veličina slike = cv2. promijeniti veličinu ( slika , dimenzija , interpolacija = cv2. INTER_AREA )

cv2. imshow ( 'Promijenjena visina slike' , promijenjena veličina slike )

cv2. čekajKljuč ( 0 )

Linije 1-14 , Nakon uvoza naših paketa i konfiguriranja našeg parsera argumenata, učitati ćemo i prikazati našu sliku.

Redci 20 i 21: Relevantno kodiranje počinje u ovim redcima . Omjer slike mora se uzeti u obzir prilikom promjene veličine. Omjer između širine i visine slike poznat je kao omjer slike.

Visina / širina je omjer slike.

Ako ne uzmemo u obzir omjer slike, rezultati naše promjene veličine postat će iskrivljeni.

Na Redak 20 , izvršen je izračun omjera promijenjene veličine. U ovom retku koda dajemo širinu naše nove slike od 160 piksela. Jednostavno definiramo naš omjer (aspectratio) kao novu širinu (160 piksela) podijeljenu sa starom širinom, kojoj pristupamo pomoću slike, kako bismo izračunali omjer nove visine prema staroj visini. oblik [1].

Nove dimenzije slike na Linija 21 može se izračunati sada kada znamo naš omjer. Još jednom, nova slika će imati širinu od 160 piksela. Nakon množenja stare visine s našim omjerom i pretvorbe rezultata u cijeli broj, izračunava se visina. Izvođenjem ove operacije možemo zadržati izvorni omjer slike.

Linija 24 gdje se slika zaista mijenja. Slika kojoj želimo promijeniti veličinu prvi je argument, a drugi su dimenzije koje smo izračunali za novu sliku. Naša metoda interpolacije, koja je algoritam za promjenu veličine stvarne slike, zadnji je parametar.

Konačno, na Linija 25 , prikazujemo našu smanjenu sliku.

Redefiniramo naš omjer (aspectratio) na Linija 31 . Visina naše nove slike bit će 70 piksela. Podijelimo 70 s izvornom visinom da bismo dobili novi omjer visine i izvorne visine.

Zatim utvrđujemo dimenzije nove slike. Nova slika će imati visinu od 70 piksela, što je već poznato. Još jednom možemo zadržati izvorni omjer slike množenjem stare širine s omjerom kako bismo dobili novu širinu.

Slika se tada stvarno mijenja Linija 35 , a prikazuje se na Linija 36.

Ovdje možemo vidjeti da smo smanjili širinu i visinu izvorne slike, a zadržali omjer slike. Naša bi slika izgledala iskrivljeno ako se omjer slike ne bi održavao.

Zaključak

U ovom smo blogu proučavali osnovne različite koncepte obrade slike. Vidjeli smo prijevod slike uz pomoć paketa OpenCV. Vidjeli smo metode za pomicanje slike gore, dolje, desno i lijevo. Ove su metode vrlo korisne kada stvaramo skup podataka sličnih slika koje dajemo kao skup podataka za obuku, tako da će stroj vidjeti različite slike čak i ako su iste. Ovaj vas je članak također naučio kako rotirati sliku oko bilo koje točke u Kartezijevom prostoru pomoću rotacijske matrice. Zatim ste otkrili kako OpenCV rotira slike pomoću ove matrice i vidjeli nekoliko ilustracija vrtećih slika.

Dvije temeljne (ali značajne) slikovne aritmetičke operacije zbrajanja i oduzimanja ispitane su u ovom odjeljku. Kao što vidite, zbrajanje i oduzimanje fundamentalnih matrica su sve aritmetičke operacije slike.

Uz to, upotrijebili smo OpenCV i NumPy kako bismo istražili osobitosti aritmetike slike. Morate imati na umu ova ograničenja ili riskirate dobivanje neočekivanih rezultata prilikom izvođenja aritmetičkih operacija na vašim slikama.

Važno je zapamtiti da iako NumPy izvodi operaciju modula i 'omata', OpenCV zbrajanje i oduzimanje režu vrijednosti izvan raspona [0, 255] kako bi stale unutar raspona. Kada razvijate svoje vlastite aplikacije računalnog vida, zapamtite ovo će vam pomoći u izbjegavanju traženja lukavih grešaka.

Okretanje slike nedvojbeno je jedna od jednostavnijih ideja koje ćemo istražiti u ovom tečaju. Okretanje se često koristi u strojnom učenju za generiranje više uzoraka podataka za obuku, što rezultira snažnijim i pouzdanijim klasifikatorima slika.

Također smo naučili kako koristiti OpenCV za promjenu veličine slike. Ključno je uzeti u obzir i metodu interpolacije koju koristite i omjer širine i visine vaše izvorne slike kada mijenjate veličinu, tako da rezultat ne izgleda iskrivljeno.

Konačno, ključno je upamtiti da ako je kvaliteta slike problem, uvijek je najbolje prebaciti se s veće na manju sliku. U većini slučajeva povećanje slike stvara artefakte i smanjuje njezinu kvalitetu.