- 1. Bitovne operacije i maskiranje
- 2. Konvolucija i zamagljivanje
- 3. Oštrenje - Obrtanje slike zamućuje se
- 4. Usitnjavanje (binizacija)
- 5. Proširenje, erozija, otvaranje / zatvaranje
- 6. Otkrivanje rubova i gradijenti slike
- 14. Perspektiva i afirmirana transformacija
- 8. Aplikacija za skice uživo
U prethodnim tutorijalima naučili smo o OpenCV-u i izvršili neke osnovne obrade slika, a zatim smo u slijedećem tutorialu izveli neke manipulacije slikama u OpenCV-u poput obrezivanja, rotacije, transformacije slike itd. Dakle, u nastavku s prethodnim tutorijalom za manipulaciju slikama, ovdje učimo još neke tehnike manipulacije slikama poput i na kraju tutorijala ćemo izgraditi python-opencv program za izradu skica uživo iz feeda web kamere uživo. Ova će aplikacija koristiti mnoge funkcije obrade slika koje smo do sada naučili ili ćemo naučiti u ovom vodiču, pa će ovo biti dobar praktični primjer za pokrivanje svih funkcija.
Kao što je rečeno u prethodnom vodiču, OpenCV je Open Source Commuter Vision Library koja ima C ++, Python i Java sučelja i podržava Windows, Linux, Mac OS, iOS i Android. Tako se može lako instalirati u Raspberry Pi s Pythonom i Linux okruženjem. A Raspberry Pi s OpenCV-om i priključenom kamerom može se koristiti za stvaranje mnogih aplikacija za obradu slika u stvarnom vremenu poput otkrivanja lica, zaključavanja lica, praćenja predmeta, otkrivanja pločica automobila, kućnog sigurnosnog sustava itd.
U ovom uputstvu vidjet ćemo još nekoliko manipulacija slikama pomoću Python OpenCV-a. Ovdje ćemo naučiti primijeniti sljedeću funkciju na sliku pomoću Python OpenCV-a:
- Bitovne operacije i maskiranje
- Zamotavanje i zamagljivanje
- Oštrenje - Obrtanje slike zamućuje se
- Pragovanje (binarnizacija)
- Proširenje, erozija, otvaranje / zatvaranje
- Otkrivanje rubova i gradijenti slike
- Perspektiva i afinitetna transformacija
- Aplikacija skica uživo
1. Bitovne operacije i maskiranje
Operacije u bitovima pomažu vam u maskiranju slika i stvaraju neke jednostavne slike.
Izrada kvadrata
import cv2 import numpy kao np # koristimo samo dvije dimenzije jer je ovo slika u sivim tonovima, ako smo koristili sliku u boji, tada bismo koristili pravokutnik = np.zeros ((300,300,3), np.uint8) # Izrada kvadrata kvadrat = np.zero ((300.300), np.uint8) cv2.rectangle (kvadrat, (50,50), (250,250), 255, -1) cv2.imshow ("kvadrat", kvadrat) cv2. waitKey (0)
Izrada elipse
elipsa = np.zero ((300.300), np.uint8) cv2.ellipse (elipsa, (150.150), (150.150), 30.0.180.255, -1) cv2.imshow ("elipsa", elipsa) cv2.waitKey (0)

Eksperimentiranje s bitovnim operacijama
#AND_prikazuje samo tamo gdje se to dvoje sijeku
BitwiseAND = cv2.bitwise_and (kvadrat, elipsa) cv2.imshow ("AND", BitwiseAND) cv2.waitKey (0)
#OR_prikazuje samo tamo gdje je kvadrat ili elipsa
BitwiseOR = cv2.bitwise_or (kvadrat, elipsa) cv2.imshow ("ILI", BitwiseOR) cv2.waitKey (0)
#XOR_prikazuje samo tamo gdje bilo koji od njih postoji sam po sebi
BitwiseXOR = cv2.bitwise_xor (kvadrat, elipsa) cv2.imshow ("XOR", BitwiseXOR) cv2.waitKey (0)
#NOT_prikazuje sve što nije dio elipse i NE može se primijeniti samo na jednu figuru
BitwiseNOT_elp = cv2.bitwise_not (elipsa) cv2.imshow ("NOT_ellipse", BitwiseNOT_elp) cv2.waitKey (0) cv2.destroyAllWindows ()

2. Konvolucija i zamagljivanje
Konvolucija je matematička operacija izvodi na dvije funkcije proizvodnju treću funkciju koja je obično modificirana verzija izvorne funkcije.
Izlazna slika = slika Funkcija Veličina jezgre
U računalnom vidu koristimo jezgre da odredimo veličinu preko koje pokrećemo našu manipulacijsku funkciju nad našom slikom.
Zamućivanje je operacija pri kojoj prosječimo piksele unutar regije (jezgra)
OpenCV zamućuje sliku primjenom jezgri, jezgra vam govori kako promijeniti vrijednost bilo kojeg datog piksela kombinirajući ga s različitom količinom susjednih piksela koji se jezgra primjenjuje na svaki piksel na slici jedan po jedan da bi se dobila konačna slika.

Jednostavno rečeno, konvolucija slike je jednostavno umnožavanje dviju matrica po elementima nakon čega slijedi zbroj.
To jednostavno možemo razumjeti na sljedećem primjeru.

Gore navedeno je 3X3 jezgra.
Množimo s 1/25 da bismo normalizirali, odnosno zbrojili na 1, povećavali smo ili smanjivali intenzitet kao u slučaju posvjetljivanja ili zamračenja slika.
Isprobajmo opencv metodu zamućenja filter2D, zadanu funkcijom cv2.filter2D (slika, -1, jezgra)
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#stvaranje matrice jezgre 3x3
kernel_3x3 = np.ones ((3,3), np.float32) / 9
# koristimo cv2.filter2D za savijanje jezgre sa slikom
zamagljeno = cv2.filter2D (slika, -1, kernel_3x3) cv2.imshow ('3x3_ blurring', zamagljeno) cv2.waitKey (0)
#stvaranje matrice jezgra 7x7
kernel_7x7 = np.ones ((7,7), np.float32) / 49
# koristimo cv2.filter2D za savijanje jezgre sa slikom
zamagljeno = cv2.filter2D (slika, -1, kernel_7x7) cv2.imshow ('7x7_ blurring', zamagljeno) cv2.waitKey (0) cv2.destroyAllWindows ()


Postoje i druge vrste metoda zamućenja:
cv2.blur - Prosječna vrijednost u navedenom prozoru.
cv2.GaussianBlur - Slično, ali koristi Gaussov prozor (veći naglasak na točkama oko središta).
cv2.medianBlur - koristi medijanu svih elemenata u prozoru.
cv2.bilateralFilter - zamućuje se, a rubovi ostaju oštri, a rubovi i detalji crte zadržavaju se.
Vidjet ćemo jedan po jedan u nastavku, prvo ćemo prikazati izvornu sliku koristeći donji kod:
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
cv2.blur:
U ovoj se metodi prosjek vrši konvertiranjem slike s normaliziranim filtrom okvira, to zauzima mjesto ispod okvira i zamjenjuje središnji element. Ovdje veličina kutije mora biti neobična i pozitivna .
# cv2.blur blur = cv2.blur (slika, (3,3)) cv2.imshow ('U prosjeku', zamućenje) cv2.waitKey (0)
cv2.GaussianBlur:
# cv2.GaussianBlur # umjesto kutijastog filtra, pokušajmo s Gaussovim jezgrom Gaussian = cv2.GaussianBlur (slika, (7,7), 0) cv2.imshow ('Gaussova zamućenja', Gaussian) cv2.waitKey (0)
cv2.medianBlur:
Potrebna je medijana svih piksela ispod područja jezgre i središnji element zamjenjuje se ovom medijanom vrijednosti.
# cv2.medianBlur # uzima medijanu svih piksela ispod područja jezgre i središnji element # zamjenjuje se ovom medijanom vrijednosti. srednja = cv2.medianBlur (slika 5) cv2.imshow ('medijan zamućenja', medijan) cv2.waitKey (0)
cv2.bilateralFilter:
Dvostrano je vrlo učinkovito u uklanjanju buke, a rubovi ostaju oštri
# cv2.bilateralFilter #Bilateral je vrlo učinkovit u uklanjanju buke, a rubovi ostaju oštri bilateral = cv2.bilateralFilter (slika, 9,75,75) cv2.imshow ('obostrano zamućenje', obostrano) cv2.waitKey (0) cv2. uništitiAllWindows ()

Slika bez buke-ne lokalno znači uklanjanje zvuka
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#parameter nakon None je jačina filtra 'h' (5-10 je dobar raspon) #next je h za komponente boje, postavite opet istu vrijednost kao h
dst = cv2.fastNlMeansDenoisingColored (slika, Nijedno, 6,6,7,21) cv2.imshow ('Brzo znači denois', dst) cv2.waitKey (0) cv2.destroyAllWindows ()

Postoje 4 varijacije odumiranja ne-lokalnih sredstava
cv2.fastNlMeansDenoising () - za jednu sliku sive skale
cv2.fastNlMeansDenoisingColored () - Jednobojna slika
cv2.fastNlmeansDenoisingMulti () - za sive nizove sljedova slika
cv2.fastNlmeansDenoisingcoloredMulti () - za slijed slika u boji
3. Oštrenje - Obrtanje slike zamućuje se
Oštrenje je suprotno zamućenju, ono pojačava ili naglašava rubove na slici.
Kernel =,,
Naša matrica jezgre zbraja jedan, tako da nema potrebe za normalizacijom (tj. Množenjem s faktorom na istu svjetlinu kao izvornik), ako jezgra nije normalizirana na 1, slika bi bila svjetlija ili tamnija.
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
kernel_sharpening = np.array (,
]))
#applying izoštravanje jezgre na ulaznu sliku
izoštreno = cv2.filter2D (slika, -1, oštrina_jezri) cv2.imshow ('izoštrena slika', izoštreno) cv2.waitKey (0) cv2.destroyAllWindows ()

4. Usitnjavanje (binizacija)
Pragovanje je čin pretvaranja slike u binarni oblik. U opencv postoji odvojena funkcija za pragovanje definirana kao
Cv2.threshold (slika, vrijednost praga, Max vrijednost, vrsta praga)
Postoje sljedeće vrste pragova:
- cv2.THRESH_BINARY - najčešći
- cv2. THRESH_BINARY_INV - najčešći
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2. THRESH_TOZERO_INV
NAPOMENA: slika je potrebna za pretvaranje u sive tokove prije praga
import cv2 import numpy as np #load image as grayscale image = cv2.imread ('gradient.jpg', 0) cv2.imshow ('original', image) cv2.waitKey (0)

#value ispod 127 ide na 0 (crno), a iznad 127 ide na 255 (bijelo)
_, thresh1 = cv2.threshold (slika, 127.255, cv2.THRESH_BINARY) cv2.imshow ('1 prag', thresh1) cv2.waitKey (0)
#value ispod 127 ide na 255, a vrijednosti iznad 127 idu na 0 (obrnuto od gore)
_, thresh2 = cv2.threshold (slika, 127.255, cv2.THRESH_BINARY_INV) cv2.imshow ('2 prag', thresh2) cv2.waitKey (0)
#value iznad 127 skraćeni su (zadržani) na 127, argument 255 nije iskorišten.
_, thresh3 = cv2.threshold (slika, 127.255, cv2.THRESH_TRUNC) cv2.imshow ('3 thresh trunc', thresh3) cv2.waitKey (0)
#vrijednosti ispod 127 idu na 0, iznad 127 su nepromijenjene
_, thresh4 = cv2.threshold (slika, 127.255, cv2.THRESH_TOZERO) cv2.imshow ('4 prag', thresh4) cv2.waitKey (0)
#Revesrse gore, ispod 127 je nepromijenjen, iznad 127 ide na nulu
_, thresh5 = cv2.threshold (slika, 127.255, cv2.THRESH_TOZERO_INV) cv2.imshow ('5 prag', thresh5) cv2.waitKey (0) cv2.destroyAllWindows ()

5. Proširenje, erozija, otvaranje / zatvaranje
To su operacije na polju matematičke morfologije
Proširenje - dodaje piksele granicama objekta na slici.
Erozija - uklanja piksele na granicama objekta na slici.
Otvaranje - Erozija praćena širenjem.
Zatvaranje - širenje praćeno erozijom.
Otvaranje je vrlo korisno u izoliranju slika jer prvo razrjeđuje sliku erozijom (uklanja buku), a zatim je širi.
Zbrka s širenjem i erozijom
Ponekad postoji zabuna između širenja i erozije obično na slikama s bijelom pozadinom, jer opencv smatra bijelu pozadinu slikom koja se širi ili erodira umjesto izvorne slike, pa u ovom slučaju erozija djeluje kao dilatacija i obrnuto, kao što je prikazano na uzorku slike prikazano ispod.

Zapamtite, Dilation dodaje piksele granicama objekata na slici, dok Erozija uklanja piksele na granicama objekata na slici
import cv2 import numpy as np image = cv2.imread ('imagecv.png', 0) cv2.imshow ('original', image) cv2.waitKey (0)

# Erozija
# definirajmo veličinu jezgre
kernel = np.ones ((5,5), np.uint8)
#sad erodiramo sliku, ovdje ponavljanje nije kada želite erodirati sliku
erozija = cv2.erode (slika, jezgra, iteracije = 1) cv2.imshow ('Erozija', erozija) cv2.waitKey (0)
# dilatacija
dilatacija = cv2.dilate (slika, jezgra, iteracije = 1) cv2.imshow ('dilatacija', dilatacija) cv2.waitKey (0)
#opening, dobro za uklanjanje buke
otvaranje = cv2.morphologyEx (slika, cv2.MORPH_OPEN, kernel) cv2.imshow ('otvaranje', otvaranje) cv2.waitKey (0)
#closing, dobro za uklanjanje buke
zatvaranje = cv2.morphologyEx (slika, cv2.MORPH_CLOSE, kernel) cv2.imshow ('zatvaranje', zatvaranje) cv2.waitKey (0) cv2.destroyAllWindows ()

6. Otkrivanje rubova i gradijenti slike
Otkrivanje rubova vrlo je važno područje u računalnom vidu, posebno kada se radi o konturama.
Rubovi se mogu definirati kao granice slike, zapravo su to rubovi koji definiraju objekt na slikama i čuvaju puno podataka o slici.
Formalno se rubovi mogu definirati kao nagle promjene (diskontinuiteti) na slici i mogu kodirati onoliko informacija koliko i pikseli.


Gornja slika prikazuje kako računalni vid prepoznaje i prepoznaje sliku.
Algoritmi za otkrivanje rubova: - Postoje tri glavne vrste algoritama za otkrivanje rubova
- Sobel - za naglašavanje vertikalnih ili vodoravnih slika.
- Laplacian - optimalan zbog niske stope pogrešaka, dobro definiranih rubova i točnog otkrivanja.
- Canny Edge algoritam za otkrivanje (prenio john.F.Canny 1986.)
1. Primjenjuje Gaussovo zamućenje
2. Pronalazi gradijent intenziteta slike
3. primjenjuje potiskivanje bez maksimuma (tj. Uklanja piksele koji nisu rubovi).
4. Histereza primjenjuje prag (tj. Ako je piksel unutar gornjeg i donjeg praga, smatra se rubom)
import cv2 import numpy kao np image = cv2.imread ('input.jpg', 0) visina, širina = image.shape
#sobel
#ekstrakcija rubova sobela
sobel_x = cv2.Sobel (slika, cv2.CV_64F, 0,1, ksize = 5) sobel_y = cv2.Sobel (slika, cv2.CV_64F, 1,0, ksize = 5) cv2.imshow ('original', slika) cv2.waitKey (0) cv2.imshow ('sobelx', sobel_x) cv2.waitKey (0)
# Sobely
cv2.imshow ('sobely', sobel_y) cv2.waitKey (0)
sobel_OR = cv2.bitwise_or (sobel_x, sobel_y) cv2.imshow ('sobelOR', sobel_OR) cv2.waitKey (0)
# laplaian
laplacian = cv2.Laplacian (slika, cv2.CV_64F) cv2.imshow ('laplacian', laplacian) cv2.waitKey (0)
#canny algoritam za otkrivanje ruba koristi vrijednosti gradijenta kao pragove
#u cannyu trebamo navesti dvije vrijednosti: prag1 i prag2.
# bilo koji gradijent veći od praga 2 smatra se rubom.
# bilo koji gradijent veći od praga 1 smatra se da nije rub.
#values u pragu između 1 i 2 su ili praga što rub ili ne-rub
#on kako spojeni njihovi intenziteti, u tom slučaju bilo koju vrijednost ispod 60 se smatra
#non rubovima wheareas se svaka vrijednost iznad 120 ° C smatra rubova.
canny = cv2.Canny (slika, 60.120) cv2.imshow ('canny', canny) cv2.waitKey (0) cv2.destroyAllWindows ()

14. Perspektiva i afirmirana transformacija
Vratimo se korak unatrag i pogledajmo afine i neafinne transformacije, originalna slika dolje prikazana očito je neafinska slika jer će se rubovi u nekom trenutku susresti, međutim, možemo je ispraviti iskrivljenjem i zauzimanjem perspektive transformirati.
Za ovu perspektivnu transformaciju potrebne su nam četiri koordinate izvorne slike, a zatim četiri točke izlazne slike, označene su točkama_A i točkama_B. Prvo uz pomoć ovih točaka izračunavamo matricu transformacije, M uz pomoć funkcije getPerspectiveTransform.
A onda se ova matrica daje funkciji warpPerspective za generiranje konačnog rezultata.
Ajmo prvo pokušati transformirati Perspektivu.
import cv2 import numpy as np import matplotlib.pyplot as plt image = cv2.imread ('paper.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#koordinata 4 kuta izvorne slike
bodovi_A = np.float32 (,,,])
#koordinate 4 kuta željenog izlaza
#koristimo omjer A4 papira 1: 1,41
bodovi_B = np.float32 (,,,])
#koristite dva skupa dviju točaka za izračunavanje matrice pretpostavljene transformacije, M
M = cv2.getPerspectiveTransform (points_A, points_B) warped = cv2.warpPerspective (slika, M, (420.594)) cv2.imshow ('warpprespective', warped ) cv2.waitKey (0) cv2.destroyAllWindows ()

Afina transformacija je lakša od neafinne transformacije jer nam trebaju samo tri točke da bismo je dobili. Čitav postupak ide isto, ali umjesto perspektivne transformacije sada imamo afiniranu transformaciju i također definiramo kolone i retke u warpAffine iz funkcije oblika, umjesto da ih ručno unosimo .
import cv2 import numpy as np import matplotlib.pyplot as plt image = cv2.imread ('box.jpg') redovi, cols = image.shape cv2.imshow ('original', slika) cv2.waitKey (0)
# koordinata 3 kuta izvorne slike
bodovi_A = np.float32 (,,])
#koordinate 3 kuta željenog izlaza
#koristimo omjer A4 papira 1: 1,41
bodovi_B = np.float32 (,,])
# upotrijebite dva skupa dviju točaka za izračunavanje matrice Affine
#transformation, M
M = cv2.getAffineTransform (points_A, points_B) warped = cv2.warpAffine (slika, M, (kolone, redovi)) cv2.imshow ('warpaffine', iskrivljeno) cv2.waitKey (0) cv2.destroyAllWindows ()

8. Aplikacija za skice uživo
Prije svega, čestitajte sebi što ste napravili korak s ovim mini projektom nakon što ste pročitali sve gore navedene funkcije za manipulaciju slikama. Dakle, u ovom mini projektu Python OpenCV- a naučit ćemo neke nove koncepte petlji i funkcija. Ako ste upoznati s programiranjem, morate imati širu ideju o tome koja je funkcija i petlje. Međutim, u pythonu osnovni koncept petlji i funkcija ostaje isti, ali metoda njihovog definiranja malo se mijenja.
Dakle, na početku ovog programa možemo vidjeti određenu skupinu izjava pod naslovom „ def skica (slika): “ ovo je formalna definicija funkcije koja predstavlja skup izjava koji zajedno rade za određeni izlaz.
Dakle, ova skica je funkcija, u pythonu je funkcija definirana s "def" i završava s oznakom ":". Također izrazi koji moraju biti unutar funkcije ili možete reći koji su potrebni da bi funkcija radila ispravno, funkcija se automatski poravnavaju sa strane. Dakle, da bi izašli iz funkcija, izjave je trebalo potpuno poravnati ulijevo. Za daljnje reference možete se obratiti Googleu kako su funkcije definirane u pythonu.
Dakle, u ovoj funkciji skice uveli smo nekoliko slojeva obrade slika koji se zajedno kombiniraju dajući izlaz. Prvo se slika pretvara u sive sjene tako da je opencv može lako obraditi, a zatim se na sliku sive ljestvice primijeni Gaussov zamućenje kako bi se smanjio šum. Zatim se rubovi ekstrahiraju uz pomoć algoritma za otkrivanje rubova limenke, a zatim se binarni inverz primjenjuje na sliku definiranu rubom, ovdje se binarni inverz može izvršiti i bitwise_NOT, ali mi smo namjerno odabrali taj binarni inverzni prag jer daje slobodu postavlja svoje parametre dok ne dobijemo jasnu sliku.
Također napomenuti da funkcija uzima sliku argumenata i vraća dva argumenta ret i masku. Dok je ret logička vrijednost koja govori da se funkcija uspješno izvodi ili ne, a maska je konačni izlaz funkcije, tj. Obrađena slika.
Tada je drugi koncept rada web kamere u opencv-u, što čini funkcija cv2.VideoCapture (0) , koja sprema sliku u poklopac objekta koji se može pročitati pomoću funkcije cap.read () , također ovdje da se primijeti ta kapica. read () je unutar beskonačne while petlje, jer je neprekidno morao hvatati slike, dajući mu osjećaj videozapisa uživo, pri čemu bi brzina kadrova u videozapisu bila brzina kadrova vaše web kamere koja je uglavnom između 24 i 60 fps.
cap.read () vraća ret i frame, gdje je ret logička vrijednost koja označava da je funkcija uspješno pokrenuta ili ne, a okvir sadrži sliku koju je snimila web kamera.
Ispod je cjeloviti Python OpenCV kôd za pokretanje Live Sketcha
import cv2 import numpy kao np #sketch generiranje funkcije def skica (slika): # pretvori sliku u sive img_gray = cv2.cvtColor (slika, cv2.COLOR_BGR2GRAY) # čišćenje slike pomoću Gaussove zamućenosti img_gray_blur = cv2.GaussianBlur (img_grag 5,5), 0) #extract edge canny_edges = cv2.Canny (img_gray_blur, 10,70) #do invert in binarize image ret, mask = cv2.threshold (canny_edges, 70,255, cv2.THRESH_BINARY_INV) return mask #inicijalizirati web kameru, cap je objekt koji omogućuje video snimanje # sadrži logičku vrijednost koja pokazuje je li uspješna (ret) #it također sadrži slike prikupljene s web kamere (frame) cap = cv2.VideoCapture (0), dok je True: ret, frame = cap.read () cv2.imshow ('livesketcher', sketch (frame)) if cv2.waitKey (1) == 13: # 13 je enterkey break #release camera and close window, ne zaboravite pustiti web kameru uz pomoć cap.release () cap.release () cv2.destroyAllWindows ()

Dakle, ovo je kraj 2. dijela manipulacija sa slikama u Python-OpenCV. Da biste postigli dobro razumijevanje računalnog vida i OpenCV-a, prođite kroz prethodne članke (Početak rada s Python OpenCV-om i manipulacijom slikama u Python OpenCV-u (1. dio) i moći ćete napraviti nešto cool s Computer Visionom.

