Obdelava slik OpenCV

Obdelava Slik Opencv



V tem članku bomo preučili metode obdelave slik. Preučili bomo nekatere temeljne, a kritične teme računalniškega vida in strojnega učenja. Te temeljne tehnike obdelave slik lahko rešijo zapletene probleme, kot so nabori podatkov. Posledično obstaja šest temeljnih korakov pri obdelavi slik, ki so navedeni spodaj:
  1. Prevod slik
  2. Vrtenje slike
  3. Slika Aritmetika
  4. Obračanje slike
  5. Obrezovanje slike
  6. Spreminjanje velikosti slike

Zdaj bomo podrobno razložili vse zgoraj omenjene teme obdelave slik.

1. Prevod slik

Prevajanje slik je metoda obdelave slik, ki nam pomaga premikati sliko vzdolž x in y osi. Sliko lahko premikamo gor, dol, desno, levo ali poljubno kombinacijo.







Matriko prevajanja lahko definiramo s simbolom M in jo lahko predstavimo v matematični obliki, kot je prikazano spodaj:





S tem programom lahko razumemo koncept prevodne slike.





Koda Python: Naslednje ime programa bomo ohranili kot translate.py .

# uvoz zahtevanih paketov

uvoz numpy kot npr.

uvoz argparse

uvoz imutil

uvoz cv2

# implementiramo razčlenjevalnik argumentov

ap_obj = argparse. ArgumentParser ( )

ap_obj. dodatek_argument ( '-k' , '--slika' , potrebno = Prav ,

pomoč = 'lokacija slikovne datoteke' )

args = čigav ( ap_obj. parse_args ( ) )

# naloži sliko in jo prikaži na zaslonu

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

cv2. imshow ( 'Originalna_slika' , slika )

# Prevod slike je matrika NumPy, ki je podana spodaj:

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

# Zgornjo matriko NumPy bomo uporabili za premik slik vzdolž

# smeri osi x in osi y. Za to moramo preprosto posredovati vrednosti slikovnih pik.

# V tem programu bomo sliko premaknili za 30 slikovnih pik v desno

# in 70 slikovnih pik proti dnu.

prevod_mat = npr. float32 ( [ [ 1 , 0 , 30 ] , [ 0 , 1 , 70 ] ] )

prevod slike = cv2. warpAffine ( slika , prevod_mat ,

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

cv2. imshow ( 'Prevod slike dol in desno' , prevod slike )

# zdaj bomo uporabili zgornjo matriko NumPy za premikanje slik vzdolž

# smeri osi x (levo) in osi y (navzgor).

# Tukaj bomo slike premaknili za 50 slikovnih pik v levo

# in 90 slikovnih pik navzgor.

prevod_mat = npr. float32 ( [ [ 1 , 0 , - petdeset ] , [ 0 , 1 , - 90 ] ] )

prevod slike = cv2. warpAffine ( slika , prevod_mat ,

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

cv2. imshow ( 'Prevod slike gor in levo' , prevod slike )

cv2. čakajKey ( 0 )

Vrstice od 1 do 5: Uvažamo vse potrebne pakete za ta program, kot so OpenCV, argparser in NumPy. Prosimo, upoštevajte, da obstaja še ena knjižnica, ki je imutils. To ni paket OpenCV. To je le knjižnica, ki bo zlahka prikazala enako obdelavo slike.



Knjižnica imutils ne bo samodejno vključena, ko namestimo OpenCV. Če želimo namestiti imutils, moramo uporabiti naslednjo metodo:

pip namestite imutils

Vrstice od 8 do 15: Ustvarili smo naš agrparser in naložili našo sliko.

Vrstice 24 do 25: V tem razdelku programa poteka prevod. Prevajalska matrika nam pove, za koliko slikovnih pik bo slika premaknjena navzgor ali navzdol ali v levo ali desno. Ker OpenCV zahteva, da je vrednost matrike v nizu s plavajočo vejico, prevajalska matrika sprejema vrednosti v nizih s plavajočo vejico.

Prva vrstica prevodne matrike je videti takole:

Ta vrstica matrike je za os x. Vrednost t x bo odločil, ali bo slika premaknjena na levo ali desno stran. Če podamo negativno vrednost, potem to pomeni, da bo slika premaknjena na levo stran, če je vrednost pozitivna, pa to pomeni, da bo slika premaknjena na desno stran.

Sedaj bomo definirali drugo vrstico matrike na naslednji način:

Ta vrstica matrike je za os y. Vrednost t Y bo odločil, ali bo slika premaknjena navzgor ali navzdol. Če posredujemo negativno vrednost, potem to pomeni, da bo slika premaknjena navzgor, če pa je vrednost pozitivna, potem to pomeni, da bo slika premaknjena navzdol.

V prejšnjem programu v vrstici 24 definiramo t x = 30 in t Y = 70. Torej premaknemo sliko za 30 slikovnih pik proti desni strani in 70 slikovnih pik navzdol.

Toda glavni proces prevajanja slike poteka v vrstici 25, kjer definiramo prevajalsko matriko cv2.warpAffine . V tej funkciji posredujemo tri parametre: prvi parameter je slika, drugi parameter je prevodna matrika in tretji parameter je dimenzija slike.

Vrstica 27: Vrstica 27 bo prikazala rezultat v izhodu.

Zdaj bomo implementirali drugo prevodno matriko za levo in gornjo stran. Za to moramo definirati negativne vrednosti.

Vrstica 33 do 34: V prejšnjem programu v vrstici 33 definiramo t x = -50 in t Y = -90. Tako premaknemo sliko za 50 slikovnih pik proti levi strani in za 90 slikovnih pik navzgor. Toda glavni proces prevajanja slike poteka v vrstici 34, kjer definiramo prevajalsko matriko cv2.warpAffine .

Vrstica 36 : Vrstica 36 bo prikazala rezultat, kot je prikazan v izhodu.

Za zagon prejšnje kode moramo podati pot do slike, kot je podano spodaj.

Izhod: python translate.py –slika veverica.jpg

Zdaj bomo implementirali isti program za prevajanje slik z uporabo imutil knjižnica. Ta knjižnica je zelo enostavna za uporabo pri obdelavi slik. V tej knjižnici nam ni treba razmišljati o cv2.warpAffine ker bo ta knjižnica poskrbela za to. Izvedimo torej ta program za prevajanje slik s knjižnico imutils.

Koda Python: Naslednje ime programa bomo ohranili kot translate_imutils.py .

# uvozite potrebne pakete

uvoz numpy kot npr.

uvoz argparse

uvoz imutil

uvoz cv2

# Ta funkcija izvaja prevod slike in

# vrne prevedeno sliko klicni funkciji.

def prevesti ( slika , x , Y ) :

prevodna_matrika = npr. float32 ( [ [ 1 , 0 , x ] , [ 0 , 1 , Y ] ] )

prevod slike = cv2. warpAffine ( slika , prevodna_matrika ,

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

vrnitev prevod slike

# sestavite razčlenjevalnik argumentov in razčlenite argumente

ap = argparse. ArgumentParser ( )

ap. dodatek_argument ( '-jaz' , '--slika' , potrebno = Prav , pomoč = 'Pot do slike' )

args = čigav ( ap. parse_args ( ) )

# naloži sliko in jo prikaže na zaslonu

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

cv2. imshow ( 'Originalna_slika' , slika )

prevod slike = imutil. prevesti ( slika , 10 , 70 )

cv2. imshow ( 'Prevod slike v desno in navzdol' ,

prevod slike )

cv2. čakajKey ( 0 )

Vrstice od 9 do 13: V tem razdelku programa poteka prevod. Prevajalska matrika nam pove, za koliko slikovnih pik bo slika premaknjena navzgor ali navzdol ali v levo ali desno.

Te vrstice so bile že razložene, zdaj pa bomo zgradili funkcijo, imenovano translate (), in vanjo poslali tri različne parametre. Slika sama služi kot prvi parameter. Vrednosti x in y prevodne matrike ustrezata drugemu in tretjemu parametru.

Opomba : Te funkcije prevajanja ni treba definirati znotraj programa, ker je že vključena v paket knjižnice imutils. Uporabil sem ga znotraj programa zaradi preproste razlage. To funkcijo lahko pokličemo neposredno z imutils, kot je prikazano v vrstici 24.

Vrstica 24: Prejšnji program bo pokazal, da v vrstici 24 definiramo tx = 10 in ty = 70. Torej premaknemo sliko za 10 slikovnih pik proti desni strani in 70 slikovnih pik navzdol.

V tem programu nas ne zanimajo nobene funkcije cv2.warpAffine, ker so že v paketu knjižnice imutils.

Za zagon prejšnje kode moramo podati pot do slike, kot je navedeno spodaj:

Izhod:

python imutils. py --slika veverice. jpg

2. Vrtenje slike

Preučili smo, kako prevesti (tj. premakniti) sliko gor, dol, levo in desno v prejšnji lekciji (ali katero koli kombinacijo). Nato bomo razpravljali o rotaciji, ki je povezana z obdelavo slik.

Slika se zavrti za kot, theta, v procesu, znanem kot rotacija. Kot, za katerega obračamo sliko, bo predstavljen s theta. Poleg tega bom naknadno zagotovil priročno funkcijo vrtenja, da bo vrtenje slik enostavnejše.

Podobno kot pri prevajanju in morda ni presenetljivo pri rotaciji za kot, se theta določi z izgradnjo matrike M v naslednji obliki:

Ta matrika lahko zavrti vektor theta stopinj (v nasprotni smeri urinega kazalca) okoli izhodišča, podane (x, y)-kartezične ravnine. Običajno bi bilo v tem scenariju izhodišče središče slike, v resnici pa bi lahko določili katero koli naključno (x, y) točko kot središče vrtenja.

Zasukana slika R se nato ustvari iz izvirne slike I z uporabo neposrednega matričnega množenja: R = IM

Po drugi strani pa OpenCV dodatno ponuja zmožnost (1) spreminjanja velikosti (tj. velikosti) slike in (2) ponujanja poljubnega središča vrtenja za izvajanje vrtenja.

Naša spremenjena rotacijska matrika M je prikazana spodaj:

Začnimo z odpiranjem in ustvarjanjem nove datoteke, imenovane rotate.py :

# uvoz zahtevanih paketov

uvoz numpy kot npr.

uvoz argparse

uvoz imutil

uvoz cv2

# ustvarjanje objekta argumentparser in razčlenjevanje argumenta

apobj = argparse. ArgumentParser ( )

apobj. dodatek_argument ( '-k' , '--slika' , potrebno = Prav , pomoč = 'pot slike' )

argumenti = čigav ( apobj. parse_args ( ) )

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

cv2. imshow ( 'Originalna_slika' , slika )

# Izračunajte sredino slike z uporabo dimenzij slike.

( višina , premer ) = slika. oblika [ : 2 ]

( centerX , centerY ) = ( premer / 2 , višina / 2 )

# Zdaj bomo z uporabo cv2 zasukali sliko za 55 stopinj na

# določite rotacijsko matriko z uporabo getRotationMatrix2D()

rotationMatrix = cv2. getRotationMatrix2D ( ( centerX , centerY ) , 55 , 1.0 )

rotatedImage = cv2. warpAffine ( slika , rotationMatrix , ( premer , višina ) )

cv2. imshow ( 'Slika je zasukana za 55 stopinj' , rotatedImage )

cv2. čakajKey ( 0 )

# Slika bo zdaj zasukana za -85 stopinj.

rotationMatrix = cv2. getRotationMatrix2D ( ( centerX , centerY ) , - 85 , 1.0 )

rotatedImage = cv2. warpAffine ( slika , rotationMatrix , ( premer , višina ) )

cv2. imshow ( 'Slika je zasukana za -85 stopinj' , rotatedImage )

cv2. čakajKey ( 0 )

Vrstice od 1 do 5: Uvažamo vse potrebne pakete za ta program, kot so OpenCV, argparser in NumPy. Prosimo, upoštevajte, da obstaja še ena knjižnica, ki je imutils. To ni paket OpenCV. To je samo knjižnica, ki bo uporabljena za enostavno prikazovanje iste obdelave slik.

Knjižnica imutils ne bo samodejno vključena, ko namestimo OpenCV. OpenCV namesti imutils. Uporabiti moramo naslednjo metodo:

pip namestite imutils

Vrstice od 8 do 14: Ustvarili smo naš agrparser in naložili našo sliko. V tem argparserju uporabljamo samo en argument slike, ki nam bo povedal pot slike, ki jo bomo uporabili v tem programu za prikaz rotacije.

Ko vrtimo sliko, moramo določiti vrtilno točko vrtenja. Večino časa boste želeli zasukati sliko okoli njenega središča, vendar vam OpenCV omogoča, da namesto tega izberete katero koli naključno točko. Preprosto zavrtimo sliko okoli središča.

Vrstice 17 do 18 vzemite širino in višino slike, nato pa vsako dimenzijo razdelite z dve, da določite središče slike.

Konstruiramo matrico za vrtenje slike na enak način, kot smo definirali matrico za prevajanje slike. Samo poklicali bomo cv2.getRotationMatrix2D funkcijo v vrstici 22 namesto ročnega ustvarjanja matrike z uporabo NumPy (kar je lahko nekoliko okorno).

The cv2.getRotationMatrix2D funkcija zahteva tri parametre. Prvi vnos je želeni rotacijski kot (v tem primeru središče slike). Theta se nato uporabi za določitev, za koliko stopinj (v nasprotni smeri urinega kazalca) bomo zasukali sliko. Tu bomo sliko zasukali za 45 stopinj. Končna možnost je povezana z velikostjo slike.

Ne glede na to, da še nismo razpravljali o spreminjanju velikosti slike, lahko tukaj navedete število s plavajočo vejico z 1,0, kar pomeni, da je treba sliko uporabiti v prvotnih razmerjih. Če pa vnesete vrednost 2,0, bi se slika podvojila. Število 0,5 tako zmanjša velikost slike.

Vrstica 22 do 23: Po prejemu naše rotacijske matrike M od cv2.getRotationMatrix2D našo sliko zavrtimo s pomočjo cv2.warpAffine tehnika v vrstici 23. Prvi vhod funkcije je slika, ki jo želimo zasukati. Nato sta definirani širina in višina naše izhodne slike, skupaj z našo rotacijsko matriko M. V vrstici 23 se slika nato zasuka za 55 stopinj.

Opazite lahko, da je bila naša slika obrnjena.

Vrstice od 28 do 30 predstavljajo drugo rotacijo. Vrstice 22–23 kode so enake, le da tokrat rotiramo za -85 stopinj v nasprotju s 55.

Do te točke smo preprosto vrteli sliko okoli središča. Kaj pa, če bi želeli sliko zavrteti okoli naključne točke?

Začnimo z odpiranjem in ustvarjanjem nove datoteke, imenovane rotate.py:

# uvoz zahtevanih paketov

uvoz numpy kot npr.

uvoz argparse

uvoz imutil

uvoz cv2

# ustvarjanje objekta argumentparser in razčlenjevanje argumenta

ap_obj = argparse. ArgumentParser ( )

ap_obj. dodatek_argument ( '-k' , '--slika' , potrebno = Prav , pomoč = 'pot slike' )

prepir = čigav ( ap_obj. parse_args ( ) )

# naloži sliko in jo prikaže na zaslonu

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

cv2. imshow ( 'Originalna_slika' , slika )

# Izračunajte sredino slike z uporabo dimenzij slike.

( višina , premer ) = slika. oblika [ : 2 ]

( centerX , centerY ) = ( premer / 2 , višina / 2 )

# Zdaj bomo z uporabo cv2 zasukali sliko za 55 stopinj na

# določite rotacijsko matriko z uporabo getRotationMatrix2D()

rotationMatrix = cv2. getRotationMatrix2D ( ( centerX , centerY ) , 55 , 1.0 )

rotatedImage = cv2. warpAffine ( slika , rotationMatrix , ( premer , višina ) )

cv2. imshow ( 'Slika je zasukana za 55 stopinj' , rotatedImage )

cv2. čakajKey ( 0 )

# Slika bo zdaj zasukana za -85 stopinj.

rotationMatrix = cv2. getRotationMatrix2D ( ( centerX , centerY ) , - 85 , 1.0 )

rotatedImage = cv2. warpAffine ( slika , rotationMatrix , ( premer , višina ) )

cv2. imshow ( 'Slika je zasukana za -85 stopinj' , rotatedImage )

cv2. čakajKey ( 0 )

# vrtenje slike iz neke poljubne točke, ne iz središča

rotationMatrix = cv2. getRotationMatrix2D ( ( centerX - 40 , centerY - 40 ) , 55 , 1.0 )

rotatedImage = cv2. warpAffine ( slika , rotationMatrix , ( premer , višina ) )

cv2. imshow ( 'Vrtenje slike iz poljubnih točk' , rotatedImage )

cv2. čakajKey ( 0 )

Vrstica 34 do 35: Zdaj bi se morala ta koda videti precej običajna za vrtenje predmeta. Za vrtenje slike okoli točke 40 slikovnih pik v levo in 40 slikovnih pik nad njeno sredino, damo navodilo cv2.getRotationMatrix2D funkcijo, da bodite pozorni na njen prvi parameter.

Slika, ki nastane, ko uporabimo to rotacijo, je prikazana spodaj:

Jasno lahko vidimo, da je središče rotacije zdaj koordinata (x, y), ki je 40 slikovnih pik levo in 40 slikovnih pik nad izračunanim središčem slike.

3. Aritmetika slike

Pravzaprav je slikovna aritmetika le seštevanje matrike z nekaj dodatnimi omejitvami glede tipov podatkov, ki jih bomo obravnavali kasneje.

Vzemimo si trenutek in pregledamo nekaj lepih osnov linearne algebre.

Razmislite o kombinaciji naslednjih dveh matrik:

Kakšen rezultat bi dalo seštevanje matrike? Preprost odgovor je vsota vnosov v matriko, element za elementom:

Dovolj preprosto, kajne?

Vsi razumemo temeljne operacije seštevanja in odštevanja v tem času. Vendar moramo pri delu s slikami upoštevati omejitve, ki jih nalaga naš barvni prostor in tip podatkov.

Slikovne pike na slikah RGB so na primer med [0, 255]. Kaj se zgodi, če poskušamo pikslu dodati 10 z intenzivnostjo 250, medtem ko ga gledamo?

Če bi uporabili standardna aritmetična načela, bi prišli do vrednosti 260. 260 ni veljavna vrednost, saj so slike RGB predstavljene kot 8-bitna cela števila brez predznaka.

Torej, kaj bi se moralo zgoditi? Ali naj zaženemo preverjanje, da zagotovimo, da nobena slikovna pika ni zunaj obsega [0, 255], pri čemer vsako slikovno piko odrežemo tako, da ima vrednost med 0 in 255?

Ali pa »zavijemo« in izvedemo operacijo modula? V skladu s pravili modula bi dodajanje 10 k 255 povzročilo samo vrednost 9.

Kako je treba obravnavati seštevanja in odštevanja slik, ki presegajo obseg [0, 255]?

Resnica je, da ni prave ali napačne tehnike; vse je odvisno od tega, kako delate s svojimi slikovnimi pikami in kaj želite doseči.

Vendar ne pozabite, da obstajajo razlike med seštevanjem v OpenCV in seštevanjem v NumPy. NumPy bo izvedel modulno aritmetiko in »ovijanje«. V nasprotju s tem bo OpenCV izvedel izrezovanje in zagotovil, da vrednosti slikovnih pik nikoli ne zapustijo območja [0, 255].

Začnimo z ustvarjanjem nove datoteke z imenom aritmetika.py in odpiranje:

# python arithmetic.py --image squirrel.jpg

# uvoz zahtevanih paketov

uvoz numpy kot npr.

uvoz argparse

uvoz imutil

uvoz cv2

# ustvarjanje objekta argumentparser in razčlenjevanje argumenta

apObj = argparse. ArgumentParser ( )

apObj. dodatek_argument ( '-k' , '--slika' , potrebno = Prav , pomoč = 'pot slike' )

argumenti = čigav ( apObj. parse_args ( ) )

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

cv2. imshow ( 'Originalna_slika' , slika )

'''

Vrednosti naših slikovnih pik bodo v območju [0, 255]

ker so slike nizi NumPy, ki so shranjeni kot nepredznačena 8-bitna cela števila.

Pri uporabi funkcij, kot sta cv2.add in cv2.subtract, bodo vrednosti odrezane

temu obsegu, tudi če so dodani ali odšteti od zunaj

[0, 255] obseg. Tukaj je ilustracija:

'''


tiskanje ( 'največ 255: {}' . format ( str ( cv2. dodati ( npr. uint8 ( [ 201 ] ) ,

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

tiskanje ( 'najmanj 0: {}' . format ( str ( cv2. odšteti ( npr. uint8 ( [ 60 ] ) ,

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

'''

Pri izvajanju aritmetičnih operacij s temi nizi z uporabo NumPy,

vrednost se bo ovila, namesto da bi bila prirezana na

[0, 255] obseg. Pri uporabi slik je pomembno, da to ohranite

v mislih.

'''


tiskanje ( 'ovijte okoli: {}' . format ( str ( npr. uint8 ( [ 201 ] ) + npr. uint8 ( [ 100 ] ) ) ) )

tiskanje ( 'ovijte okoli: {}' . format ( str ( npr. uint8 ( [ 60 ] ) - npr. uint8 ( [ 100 ] ) ) ) )

'''

Pomnožimo svetlost vsakega piksla na naši sliki s 101.

Da bi to naredili, ustvarimo matriko NumPy enake velikosti kot naša matrika,

napolnjeno z enicami in ga pomnožite s 101, da dobite napolnjeno matriko

s 101s. Na koncu združimo obe sliki.

Opazili boste, da je slika zdaj 'svetlejša.'

'''


Matrix = npr. tiste ( slika. oblika , dtype = 'uint8' ) * 101

slika_dodana = cv2. dodati ( slika , Matrix )

cv2. imshow ( 'Dodan rezultat slike' , slika_dodana )

#Na podoben način lahko naredimo svojo podobo temnejšo, če vzamemo

# 60 stran od vseh slikovnih pik.

Matrix = npr. tiste ( slika. oblika , dtype = 'uint8' ) * 60

slika_odšteta = cv2. odšteti ( slika , Matrix )

cv2. imshow ( 'Rezultat odštete slike' , slika_odšteta )

cv2. čakajKey ( 0 )

Vrstice od 1 do 16 bo uporabljen za izvajanje našega običajnega postopka, ki vključuje uvoz naših paketov, konfiguracijo našega razčlenjevalnika argumentov in nalaganje naše slike.

Se spomnite, kako sem prej razpravljal o razlikovanju med dodatkom OpenCV in NumPy? Zdaj, ko smo to temeljito obravnavali, si oglejmo poseben primer, da zagotovimo, da ga razumemo.

Dve 8-bitni nepredznačeni celi številski matriki NumPy sta definirani na vrstica 26 . Vrednost 201 je edini element v prvi matriki. Čeprav je v drugi matriki le en član, ima vrednost 100. Vrednosti se nato dodajo s funkcijo cv2.add OpenCV.

Kakšen bo po vašem mnenju rezultat?

V skladu z običajnimi aritmetičnimi načeli bi moral biti odgovor 301. Vendar ne pozabite, da imamo opravka z 8-bitnimi celimi števili brez predznaka, ki so lahko le v območju [0, 255]. Ker uporabljamo metodo cv2.add, OpenCV obravnava izrezovanje in zagotavlja, da seštevanje vrne samo največji rezultat 255.

Prva vrstica spodnjega seznama prikazuje rezultat izvajanja te kode:

aritmetika. py

največ 255 : [ [ 255 ] ]

Seštevek je res dal številko 255.

Po tem, vrstica 26 uporablja cv2.subtract za izvedbo odštevanja. Še enkrat definiramo dve 8-bitni nizi celih števil NumPy brez predznaka z enim elementom v vsakem. Vrednost prve matrike je 60, medtem ko je vrednost druge matrike 100.

Naša aritmetika narekuje, da mora odštevanje dati vrednost -40, vendar OpenCV ponovno opravi izrezovanje namesto nas. Ugotovimo, da je bila vrednost obrezana na 0. Naš spodnji rezultat to dokazuje:

aritmetika. py

najmanj 0 : [ [ 0 ] ]

Z uporabo cv2 odštejte 100 od odštevanja 60, tako da dobite vrednost 0.

Toda kaj se zgodi, če za izračune uporabimo NumPy namesto OpenCV?

Vrstici 38 in 39 obravnavati to težavo.

Najprej sta definirani dve 8-bitni nepredznačeni celi številski matriki NumPy z enim samim elementom. Vrednost prve matrike je 201, medtem ko je vrednost druge matrike 100. Naš dodatek bi bil obrezan in vrnjena bi bila vrednost 255, če bi uporabili funkcijo cv2.add.

NumPy po drugi strani 'ovije' in izvaja modulo aritmetiko namesto izrezovanja. NumPy se vrne na nič, ko je dosežena vrednost 255, nato pa nadaljuje s štetjem, dokler ni doseženih 100 korakov. To potrjuje prva vrstica izhoda, ki je prikazana spodaj:

aritmetika. py
ovijte okoli: [ Štiri, pet ]

Nato sta definirani še dve matriki NumPy, ena z vrednostjo 50 in druga z 100. To odštevanje bi obrezala metoda cv2.subtract, da bi vrnila rezultat 0. Vendar se zavedamo, da namesto izrezovanja NumPy izvede modulo aritmetika. Namesto tega se modulo postopki ovijejo in začnejo šteti nazaj od 255, ko je med odštevanjem dosežena 0. To lahko vidimo iz naslednjega rezultata:

aritmetika. py

ovijte okoli: [ 207 ]

Naš izhod terminala še enkrat prikazuje razliko med izrezovanjem in ovijanjem:

Ključnega pomena je, da pri izvajanju celoštevilske aritmetike upoštevate želeni rezultat. Ali želite, da se vrednosti izven obsega [0, 255] izrežejo? Po tem uporabite vgrajene slikovne aritmetične tehnike OpenCV.

Ali želite, da se vrednosti ovijejo, če so zunaj obsega [0, 255] in aritmetičnih operacij modula? Nizi NumPy se nato preprosto dodajo in odštejejo kot običajno.

Vrstica 48 definira enodimenzionalno matriko NumPy z enakimi dimenzijami kot naša slika. Še enkrat zagotovimo, da je naš podatkovni tip 8-bitna cela števila brez predznaka. Samo pomnožimo našo matriko enomestnih vrednosti s 101, da jo zapolnimo z vrednostmi 101 namesto z 1. Nazadnje uporabimo funkcijo cv2.add, da izvirni sliki dodamo našo matriko 100s. To poveča intenzivnost vsake slikovne pike za 101, obenem pa zagotovi, da so vse vrednosti, ki poskušajo preseči 255, odrezane na obseg [0, 255].

Opazujte, kako je slika opazno svetlejša in deluje bolj »sprano« kot izvirnik. To je zato, ker slikovne pike usmerjamo k svetlejšim barvam, tako da zvišamo njihovo intenziteto za 101.

Da bi od vsake intenzivnosti slikovne pike odšteli 60, najprej vzpostavimo drugo matriko NumPy v vrstici 54, ki je napolnjena s 60-imi.

Rezultati tega odštevanja so prikazani na naslednji sliki:

Predmeti okoli nas so videti bistveno temnejši kot so bili prej. To je zato, ker z odštevanjem 60 od vsake slikovne pike premaknemo slikovne pike v barvnem prostoru RGB v temnejša področja.

4. Obračanje slike

Podobno kot pri vrtenju je tudi obračanje slike čez os x ali y druga možnost, ki jo ponuja OpenCV. Tudi če se operacije obračanja ne uporabljajo tako pogosto, je njihovo poznavanje izjemno koristno zaradi različnih razlogov, ki jih morda ne opazite takoj.

Razvijamo klasifikator strojnega učenja za majhno zagonsko podjetje, ki želi prepoznati obraze na slikah. Da bi se naš sistem »naučil«, kaj je obraz, bi potrebovali nekakšen nabor podatkov z vzorčnimi obrazi. Na žalost nam je podjetje dalo le majhen nabor podatkov s 40 obrazi in ne moremo zbrati več informacij.

Kaj pa naj naredimo?

Ker obraz ostane obraz, ne glede na to, ali je zrcaljen ali ne, lahko vsako sliko obraza vodoravno obrnemo in zrcaljene različice uporabimo kot dodatne podatke za usposabljanje.

Ta primer se morda zdi neumen in umeten, vendar ni. Obračanje je premišljena strategija, ki jo uporabljajo močni algoritmi za globoko učenje za proizvodnjo več podatkov med fazo usposabljanja.

Iz prejšnjega je jasno, da metode obdelave slik, ki se jih naučite v tem modulu, služijo kot temelj za večje sisteme računalniškega vida.

Cilji:

Uporabljati cv2.flip funkcijo, se boste v tej lekciji naučili vodoravno in navpično obrniti sliko.

Obračanje je naslednja manipulacija slike, ki jo bomo preučevali. Osi x in y slike je mogoče obrniti ali celo obe. Preden se poglobimo v kodiranje, je najbolje, da najprej pogledamo rezultate obračanja slike. Oglejte si sliko, ki je bila vodoravno obrnjena na naslednji sliki:


Upoštevajte, kako je naša izvirna slika na levi in ​​kako je bila slika vodoravno zrcaljena na desni.

Začnimo z ustvarjanjem nove datoteke z imenom flipping.py .

Videli ste primer obračanja slike, zato preglejmo kodo:

# python flipping.py --image quirrel.jpg

# uvoz zahtevanih paketov

uvoz argparse

uvoz cv2

# ustvarjanje predmeta razčlenjevalnika argumentov in razčlenjevanje argumenta

apObj = argparse. ArgumentParser ( )

apObj. dodatek_argument ( '-jaz' , '--slika' , potrebno = Prav , pomoč = 'pot slike' )

prepir = čigav ( apObj. parse_args ( ) )

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

cv2. imshow ( 'Original' , slika )

# vodoravno obrnite sliko

imageflipped = cv2. flip ( slika , 1 )

cv2. imshow ( 'Vodoravno obrnjena slika' , imageflipped )

# navpično obrnite sliko

imageflipped = cv2. flip ( slika , 0 )

cv2. imshow ( 'Navpično obrnjena slika' , imageflipped )

# obračanje slike po obeh oseh

imageflipped = cv2. flip ( slika , - 1 )

cv2. imshow ( 'Obrnjeno vodoravno in navpično' , imageflipped )

cv2. čakajKey ( 0 )

Koraki, ki jih izvedemo za uvoz naših paketov, razčlenitev naših vnosov in nalaganje naše slike z diska, so obdelani v l od 1 do 12 .

S klicem funkcije cv2.flip on Vrstica 15 , sliko preprosto obrnete vodoravno. Slika, ki jo želimo obrniti, in posebna koda ali zastavica, ki določa, kako obrniti sliko, sta dva argumenta, potrebna za metodo cv2.flip.

Vrednost kode obračanja 1 pomeni, da bomo sliko zasukali okoli osi y, da jo bomo obrnili vodoravno ( Vrstica 15 ). Če določimo kodo obračanja 0, želimo zasukati sliko okoli osi x ( 19. vrstica ). Negativna flip koda ( Vrstica 23 ) zasuka sliko po obeh oseh.

Eden najlažjih primerov pri tej temi je obračanje slike, kar je osnovno.

Nato bomo razpravljali o obrezovanju slik in uporabi rezin niza NumPy za ekstrahiranje določenih delov slike.

5. Obrezovanje slike

Obrezovanje, kot pove že ime, je postopek izbire in odstranitve območja zanimanja (ali preprosto ROI), ki je območje slike, ki nas zanima.

Za aplikacijo za zaznavanje obrazov bi bilo treba obraz izrezati iz slike. Poleg tega, če bi ustvarjali skript Python za iskanje psov na slikah, bi morda želeli obrezati psa s slike, ko ga najdemo.

Cilji: Naš glavni cilj je, da se seznanimo z rezanjem matrike NumPy za obrezovanje območij iz slike in jo enostavno uporabljamo.

Obrezovanje : Ko obrežemo sliko, je naš cilj odstraniti zunanje elemente, ki nas ne zanimajo. Postopek izbire naše donosnosti naložbe se pogosto imenuje izbira naše interesne regije.

Ustvari novo datoteko z imenom crop.py , ga odprite in dodajte to kodo:

# python crop.py

# uvoz zahtevanih paketov

uvoz cv2

# nalaganje slike in prikaz na zaslonu

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

tiskanje ( slika. oblika )

cv2. imshow ( 'Original' , slika )

# Rezine polja NumPy se uporabljajo za hitro obrezovanje slike

# obrezali bomo obraz veverice s slike

squirrelface = slika [ 35 : 90 , 35 : 100 ]

cv2. imshow ( 'veveričji obraz' , squirrelface )

cv2. čakajKey ( 0 )

# In zdaj bomo obrezali celotno telo

# od veverice

squirrelbody = slika [ 35 : 148 , 23 : 143 ]

cv2. imshow ( 'Telo veverice' , squirrelbody )

cv2. čakajKey ( 0 )

Prikazali bomo obrezovanje v Pythonu in OpenCV z uporabo slike, ki jo naložimo z diska Vrstici 5 in 6 .

Izvirna slika, ki jo bomo obrezali

Z uporabo samo osnovnih tehnik obrezovanja želimo ločiti veveričji obraz in telo veverice od okolice.

Uporabili bomo naše predhodno znanje o sliki in ročno podali rezine polja NumPy, kjer obstajata telo in obraz. V normalnih pogojih bi na splošno uporabljali strojno učenje in algoritme računalniškega vida za prepoznavanje obraza in telesa na sliki. Vendar naj bodo stvari zaenkrat enostavne in se izogibajmo uporabi kakršnih koli modelov zaznavanja.

Obraz na sliki lahko prepoznamo z eno samo vrstico kode. 13. vrstica , Za ekstrahiranje pravokotnega dela slike, ki se začne pri (35, 35), nudimo rezine polja NumPy (90, 100). Morda se zdi zmedeno, da obrez dovajamo z indeksi v vrstnem redu najprej po višini in po širini, vendar ne pozabite, da OpenCV shranjuje slike kot polja NumPy. Posledično moramo navesti vrednosti za os y pred osjo x.

NumPy za izvedbo našega obrezovanja potrebuje naslednje štiri indekse:

Začetek y: Y-koordinata na začetku. Za ta primer začnemo pri y=35.

Konec y: Y koordinata na koncu. Naš pridelek se bo ustavil, ko bo y = 90.

Začetek x: Začetek x koordinata rezine. Obrezovanje se začne pri x=35.

Konec x: Končna koordinata osi x rezine. Pri x=100 je naša rezina končana.

Podobno obrežemo regije (23, 35) in (143, 148) iz izvirne slike, da izvlečemo celotno telo iz slike na 19. vrstica .

Opazite lahko, da je bila slika obrezana tako, da prikazuje samo telo in obraz.

6. Spreminjanje velikosti slike

Postopek povečevanja ali zmanjševanja širine in višine slike je znan kot skaliranje ali preprosto spreminjanje velikosti. Pri spreminjanju velikosti slike je treba upoštevati razmerje stranic, ki je razmerje med širino slike in njeno višino. Če zanemarjate razmerje stranic, se lahko slike, ki so bile pomanjšane, zdijo stisnjene in popačene:

Naša začetna slika je na levi. Na desni strani boste videli dve sliki, ki sta bili pomanjšani brez ohranjanja razmerja stranic, kar popači razmerje med širino slike in njeno višino. Pri spreminjanju velikosti slik morate na splošno upoštevati razmerje stranic.

Tehnika interpolacije, ki jo uporablja naš algoritem za spreminjanje velikosti, mora upoštevati tudi cilj funkcije interpolacije, da uporabi te soseske slikovnih pik za povečanje ali zmanjšanje velikosti slike.

Na splošno je krčenje velikosti slike veliko bolj učinkovito. To je zato, ker je odstranjevanje slikovnih pik s slike vse, kar mora storiti funkcija interpolacije. Po drugi strani pa bi morala metoda interpolacije 'zapolniti vrzeli' med slikovnimi pikami, ki prej niso obstajale, če bi povečali velikost slike.

Na levi strani imamo prvotno sliko. Slika je bila na sredini zmanjšana na polovico prvotne velikosti, vendar razen tega ni prišlo do izgube 'kakovosti' slike. Kljub temu je bila velikost slike na desni precej povečana. Zdaj je videti »razpihnjeno« in »pikselirano«.

Kot sem že omenil, boste običajno želeli zmanjšati velikost slike, namesto da bi jo povečali. Z zmanjšanjem velikosti slike analiziramo manj slikovnih pik in se moramo ukvarjati z manj 'šuma', zaradi česar so algoritmi za obdelavo slik hitrejši in natančnejši.

Translacija in rotacija sta dve transformaciji slike, ki sta bili obravnavani do sedaj. Zdaj bomo preučili, kako spremeniti velikost slike.

Ni presenetljivo, da bomo spreminjali velikost naših slik z metodo cv2.resize. Kot sem že omenil, moramo pri uporabi te metode upoštevati razmerje stranic slike. Toda preden se pregloboko spustimo v podrobnosti, naj vam predstavim ilustracijo:

# python resize.py --image squirrel.jpg

# uvoz zahtevanih paketov

uvoz argparse

uvoz cv2

# ustvarjanje predmeta razčlenjevalnika argumentov in razčlenjevanje argumenta

apObj = argparse. ArgumentParser ( )

apObj. dodatek_argument ( '-k' , '--slika' , potrebno = Prav , pomoč = 'pot slike' )

argumenti = čigav ( apObj. parse_args ( ) )

# naloži sliko in jo prikaže na zaslonu

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

cv2. imshow ( 'Original' , slika )

# Da bi preprečili, da bi slika izgledala poševno, razmerje stranic

# je treba upoštevati ali deformirati; zato ugotovimo, kaj

# razmerje nove slike in trenutne slike.

# Naredimo širino naše nove slike 160 slikovnih pik.

vidik = 160,0 / slika. oblika [ 1 ]

razsežnost = ( 160 , int ( slika. oblika [ 0 ] * vidik ) )

# ta vrstica bo prikazala dejanske operacije spreminjanja velikosti

spremenjena velikost slike = cv2. spremenite velikost ( slika , razsežnost , interpolacija = cv2. INTER_AREA )

cv2. imshow ( 'Spremenjena velikost širine slike' , spremenjena velikost slike )

# Kaj če bi želeli spremeniti višino slike? - uporabljati

# enako načelo, na podlagi katerega lahko izračunamo razmerje stranic

# na višino namesto na širino. Naredimo lestvico

Višina # slike 70 slikovnih pik.

vidik = 70,0 / slika. oblika [ 0 ]

razsežnost = ( int ( slika. oblika [ 1 ] * vidik ) , 70 )

# izvedite spreminjanje velikosti

spremenjena velikost slike = cv2. spremenite velikost ( slika , razsežnost , interpolacija = cv2. INTER_AREA )

cv2. imshow ( 'Spremenjena višina slike' , spremenjena velikost slike )

cv2. čakajKey ( 0 )

Vrstice 1-14 , Po uvozu naših paketov in konfiguraciji našega razčlenjevalnika argumentov bomo naložili in prikazali našo sliko.

Vrstici 20 in 21: v teh vrsticah se začne ustrezno kodiranje . Pri spreminjanju velikosti slike je treba upoštevati razmerje stranic. Razmerje med širino in višino slike je znano kot razmerje stranic.

Višina širina je razmerje stranic.

Če ne upoštevamo razmerja stranic, bodo rezultati našega spreminjanja velikosti popačeni.

Vklopljeno Vrstica 20 , se izvede izračun spremenjenega razmerja. V tej vrstici kode zagotovimo širino naše nove slike kot 160 slikovnih pik. Naše razmerje (aspectratio) preprosto definiramo kot novo širino (160 slikovnih pik), deljeno s staro širino, do katere dostopamo s sliko, da izračunamo razmerje med novo višino in staro višino. oblika [1].

Nove dimenzije slike naprej Vrstica 21 lahko izračunamo zdaj, ko poznamo naše razmerje. Še enkrat bo nova slika široka 160 slikovnih pik. Po pomnožitvi stare višine z našim razmerjem in pretvorbi rezultata v celo število se izračuna višina. S to operacijo lahko ohranimo prvotno razmerje stranic slike.

Vrstica 24 kjer je slika resnično spremenjena. Slika, ki ji želimo spremeniti velikost, je prvi argument, drugi pa so dimenzije, ki smo jih izračunali za novo sliko. Naša metoda interpolacije, ki je algoritem za spreminjanje velikosti dejanske slike, je zadnji parameter.

Končno, na Vrstica 25 , prikažemo našo pomanjšano sliko.

Na novo določimo naše razmerje (aspectratio). Vrstica 31 . Višina naše nove slike bo 70 slikovnih pik. 70 delimo s prvotno višino, da dobimo novo razmerje med višino in prvotno višino.

Nato določimo dimenzije nove slike. Nova slika bo imela višino 70 slikovnih pik, kar je že znano. Ponovno lahko ohranimo prvotno razmerje stranic slike tako, da pomnožimo staro širino z razmerjem, da dobimo novo širino.

Slika se nato dejansko spremeni v velikost Vrstica 35 , in je prikazano na Vrstica 36.

Tukaj lahko vidimo, da smo zmanjšali širino in višino prvotne slike, medtem ko smo ohranili razmerje stranic. Naša slika bi bila videti popačena, če ne bi ohranili razmerja stranic.

Zaključek

V tem blogu smo preučevali osnovne koncepte obdelave slik. Videli smo prevajanje slik s pomočjo paketa OpenCV. Videli smo metode premikanja slike gor, dol, desno in levo. Te metode so zelo uporabne, ko ustvarimo nabor podatkov podobnih slik, ki jih damo kot nabor podatkov za usposabljanje, tako da bo stroj videl različne slike, tudi če so enake. Ta članek vas je tudi naučil, kako zavrteti sliko okoli katere koli točke v kartezičnem prostoru z uporabo rotacijske matrike. Nato ste odkrili, kako OpenCV obrača slike s to matriko, in videli nekaj ilustracij vrtečih se slik.

V tem razdelku sta bili preučeni dve temeljni (vendar pomembni) slikovni aritmetični operaciji seštevanja in odštevanja. Kot lahko vidite, je seštevanje in odštevanje osnovnih matrik vse aritmetične operacije slike.

Poleg tega smo uporabili OpenCV in NumPy za raziskovanje posebnosti slikovne aritmetike. Upoštevati morate te omejitve, sicer tvegate nepričakovane rezultate pri izvajanju aritmetičnih operacij na svojih slikah.

Pomembno si je zapomniti, da čeprav NumPy izvaja operacijo modula in se »ovije«, vrednosti seštevanja in odštevanja OpenCV režejo zunaj obsega [0, 255], da se prilegajo znotraj obsega. Ko razvijate lastne aplikacije za računalniški vid, si zapomnite to, kar vam bo pomagalo, da se izognete lovljenju zapletenih hroščev.

Obračanje slike je nedvomno ena enostavnejših idej, ki jih bomo raziskali v tem tečaju. Obračanje se pogosto uporablja pri strojnem učenju za ustvarjanje več vzorcev podatkov za usposabljanje, kar ima za posledico močnejše in zanesljivejše klasifikatorje slik.

Naučili smo se tudi, kako uporabljati OpenCV za spreminjanje velikosti slike. Ključnega pomena je, da pri spreminjanju velikosti upoštevate metodo interpolacije, ki jo uporabljate, in razmerje stranic izvirne slike, da rezultat ne bo videti popačen.

Nazadnje je ključnega pomena, da se spomnite, da če je kakovost slike težava, je vedno najbolje preklopiti z večje na manjšo sliko. V večini primerov povečava slike ustvari artefakte in poslabša njeno kakovost.