- 1. Bitne operacije in maskiranje
- 2. Zvijanje in zameglitev
- 3. Ostrenje - vzvratna zameglitev slike
- 4. Vrtanje (binarizacija)
- 5. Razširitev, erozija, odpiranje / zapiranje
- 6. Zaznavanje robov in gradienti slike
- 14. Perspektiva in afinistična preobrazba
- 8. Aplikacija Live Sketch
V prejšnjih vajah smo se naučili o OpenCV in izvedli nekaj osnovnih obdelav slik, nato pa v naslednji vadnici v OpenCV izvedli nekaj manipulacij s slikami, kot so obrezovanje, vrtenje, preoblikovanje slike itd. še nekaj tehnik manipulacije s slikami, na primer in na koncu vadnice bomo zgradili program python-opencv, da bomo v živo naredili skico v živo iz spletne kamere. Ta aplikacija bo uporabila številne funkcije za obdelavo slik, ki smo se jih naučili doslej ali se jih bomo naučili v tej vadnici, zato bo to dober praktični primer za pokrivanje vseh funkcij.
Kot je bilo rečeno v prejšnji vadnici, je OpenCV odprtokodna knjižnica Commuter Vision, ki ima vmesnike C ++, Python in Java in podpira Windows, Linux, Mac OS, iOS in Android. Tako ga je mogoče enostavno namestiti v Raspberry Pi z okoljem Python in Linux. Raspberry Pi z OpenCV in priloženo kamero lahko uporabimo za ustvarjanje številnih aplikacij za obdelavo slik v realnem času, kot so zaznavanje obrazov, zaklepanje obrazov, sledenje predmetom, zaznavanje registrske tablice, sistem za domačo varnost itd.
V tej vadnici si bomo ogledali še nekaj manipulacij s slikami z uporabo Python OpenCV. Tu se bomo naučili uporabljati naslednjo funkcijo na sliki s pomočjo Python OpenCV:
- Bitovne operacije in maskiranje
- Zvijanje in zameglitev
- Ostrenje - obračanje slike v obratni smeri
- Prag (binarizacija)
- Razširitev, erozija, odpiranje / zapiranje
- Zaznavanje robov in gradienti slike
- Perspektivna in afinistična preobrazba
- Aplikacija za skico v živo
1. Bitne operacije in maskiranje
Bit-operacije vam pomagajo pri maskiranju slik in vam pomagajo ustvariti nekaj preprostih slik.
Izdelava kvadrata
import cv2 import numpy as np # uporabljamo samo dve dimenziji, ker je to slika v sivinah, če bi uporabljali #barvno sliko, bi potem uporabili pravokotnik = np.zeros ((300,300,3), np.uint8) # Izdelava kvadrata kvadrat = np.zeros ((300.300), np.uint8) cv2.rectangle (kvadrat, (50,50), (250.250), 255, -1) cv2.imshow ("kvadrat", kvadrat) cv2. waitKey (0)
Izdelava elipse
elipsa = np.zeros ((300.300), np.uint8) cv2.ellipse (elipsa, (150.150), (150.150), 30.0.180.255, -1) cv2.imshow ("elipsa", elipsa) cv2.waitKey (0)
Eksperimentiranje z bitnimi operacijami
#AND_prikaže samo tam, kjer se sekata
BitwiseAND = cv2.bitwise_and (kvadrat, elipsa) cv2.imshow ("IN", BitwiseAND) cv2.waitKey (0)
#OR_prikaže samo tam, kjer je kvadrat ali elipsa
BitwiseOR = cv2.bitwise_or (kvadrat, elipsa) cv2.imshow ("ALI", BitwiseOR) cv2.waitKey (0)
#XOR_prikaže samo tam, kjer obstaja samostojno
BitwiseXOR = cv2.bitwise_xor (kvadrat, elipsa) cv2.imshow ("XOR", BitwiseXOR) cv2.waitKey (0)
#NOT_prikaže vse, kar ni del elipse in operacije NOT ni mogoče uporabiti samo za eno sliko
BitwiseNOT_elp = cv2.bitwise_not (elipsa) cv2.imshow ("NOT_ellipse", BitwiseNOT_elp) cv2.waitKey (0) cv2.destroyAllWindows ()
2. Zvijanje in zameglitev
Konvolucija je matematična operacija izvedena na dveh funkcij, ki proizvajajo tretjo funkcijo, ki je običajno spremenjena različica prvotne funkcije.
Izhodna slika = slika Funkcija Velikost jedra
V računalniškem vidu uporabljamo jedra, da določimo velikost, nad katero vodimo svojo manipulacijsko funkcijo nad našo sliko.
Zameglitev je operacija, pri kateri povprečno izračunamo slikovne pike znotraj regije (jedro)
OpenCV zamegli sliko z uporabo jeder, jedro vam pove, kako spremenite vrednost katere koli dane slikovne pike, tako da jo kombinirate z različno količino sosednjih slikovnih pik, ki jih jedro posamezno nanese na vsako slikovno piko na sliki, da ustvari končno sliko.
Preprosto rečeno, konvolucija slike je preprosto pomnožitev dveh matric, ki ji sledi vsota.
Preprosto ga lahko razumemo na naslednjem primeru.
Zgoraj je jedro 3X3.
Pomnožimo z 1/25, da normaliziramo, tj. Vsoto na 1, smo povečali ali zmanjšali intenzivnost, kot v primeru posvetlitve ali zatemnitve slik.
Preizkusimo metodo zamegljenosti opencv filter2D, ki jo daje funkcija cv2.filter2D (slika, -1, jedro)
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
# ustvarjanje matrike jedra 3x3
jedro_3x3 = np.ones ((3,3), np.float32) / 9
# uporabljamo cv2.filter2D za pretvorbo jedra v sliko
zamegljeno = cv2.filter2D (slika, -1, jedro_3x3) cv2.imshow ('3x3_ blurring', zamegljeno) cv2.waitKey (0)
# ustvarjanje matrike jedra 7x7
jedro_7x7 = np.ones ((7,7), np.float32) / 49
# uporabljamo cv2.filter2D za pretvorbo jedra v sliko
zamegljeno = cv2.filter2D (slika, -1, jedro_7x7) cv2.imshow ('7x7_ blurring', zamegljeno) cv2.waitKey (0) cv2.destroyAllWindows ()
Obstajajo tudi druge vrste metod zameglitve:
cv2.blur - Povprečje vrednosti v določenem oknu.
cv2.GaussianBlur - podobno, vendar uporablja Gaussovo okno (večji poudarek na točkah okoli središča).
cv2.medianBlur - Uporablja mediano vseh elementov v oknu.
cv2.bilateralFilter - zamegli in pri tem ohrani ostrino robov, ohrani robove in podrobnosti črt.
Spodaj bomo videli enega za drugim, najprej izvirno sliko prikažemo s spodnjo kodo:
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
cv2.blur:
Pri tej metodi se povprečenje izvede s pretvorbo slike z normaliziranim filtrom polja, ki zavzame mesto pod okvirjem in nadomesti osrednji element. Tu mora biti velikost škatle nenavadna in pozitivna .
# cv2.blur zameglitev = cv2.blur (slika, (3,3)) cv2.imshow ('Povprečevanje', zamegljenost) cv2.waitKey (0)
cv2.GaussianBlur:
# cv2.GaussianBlur # namesto škatlastega filtra poskusimo z Gaussovim jedrom Gaussian = cv2.GaussianBlur (slika, (7,7), 0) cv2.imshow ('Gaussova zamegljenost', Gaussian) cv2.waitKey (0)
cv2.medianBlur:
Zavzame srednjo vrednost vseh slikovnih pik pod območjem jedra in osrednji element se nadomesti s to srednjo vrednostjo.
# cv2.medianBlur # zavzame mediano vseh slikovnih pik pod območjem jedra in osrednji element # je nadomeščen s to srednjo vrednostjo. mediana = cv2.medianBlur (slika 5) cv2.imshow ("mediana zameglitev ', mediana) cv2.waitKey (0)
cv2.bilateralFilter:
Dvostransko je zelo učinkovito pri odstranjevanju hrupa, hkrati pa ohranja ostre robove
# cv2.bilateralFilter # Bilateral je zelo učinkovit pri odstranjevanju hrupa, hkrati pa ohranja ostre robove bilateral = cv2.bilateralFilter (slika, 9,75,75) cv2.imshow ('dvostransko zamegljevanje', dvostransko) cv2.waitKey (0) cv2. Uniči vse Windows ()
Image Odstranjevanje zvoka-ne lokalno pomeni odpravljanje zvoka
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#parameter za None je moč filtra 'h' (5-10 je dober razpon) #next je h za barvne komponente, znova nastavite enako vrednost kot h
dst = cv2.fastNlMeansDenoisingColored (slika, Brez, 6,6,7,21) cv2.imshow ('Hitro pomeni denois', dst) cv2.waitKey (0) cv2.destroyAllWindows ()
Obstajajo 4 različice nelokalnih načinov, ki jih povzročajo
cv2.fastNlMeansDenoising () - za eno sliko v lestvici sive lestvice
cv2.fastNlMeansDenoisingColored () - enobarvna slika
cv2.fastNlmeansDenoisingMulti () - za slikovno zaporedje sivin
cv2.fastNlmeansDenoisingcoloredMulti () - za barvno zaporedje slik
3. Ostrenje - vzvratna zameglitev slike
Ostrenje je nasprotno zamegljevanju, ojača ali poudari robove na sliki.
Jedro =,
Naša matrika jedra sešteje do enega, zato je ni treba normalizirati (tj. Pomnožiti s faktorjem na enako svetlost kot original), če jedro ni normalizirano na 1, bi bila slika svetlejša ali temnejša.
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
jedro_ostritve = np.array (,
])
#applying ostrenje jedra za vhodno sliko
izostren = cv2.filter2D (slika, -1, ostrenje jedra) cv2.imshow ('izostrena slika', izostreno) cv2.waitKey (0) cv2.destroyAllWindows ()
4. Vrtanje (binarizacija)
Prag je pretvorba slike v binarno obliko. V opencv je ločena funkcija za določanje pragov, definirana kot
Cv2.threshold (slika, vrednost praga, največja vrednost, vrsta praga)
Obstajajo naslednje vrste pragov:
- cv2.THRESH_BINARY - najpogostejši
- cv2. THRESH_BINARY_INV - najpogostejši
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2. THRESH_TOZERO_INV
OPOMBA: sliko je treba pred pragom pretvoriti v sivine
import cv2 import numpy as np #load image as grayscale image = cv2.imread ('gradient.jpg', 0) cv2.imshow ('original', image) cv2.waitKey (0)
#value pod 127 gre na 0 (črna), nad 127 pa na 255 (bela)
_, thresh1 = cv2.threshold (slika, 127.255, cv2.THRESH_BINARY) cv2.imshow ('1 prag', thresh1) cv2.waitKey (0)
#value pod 127 gre na 255 in vrednosti nad 127 gre na 0 (obratno od zgoraj)
_, thresh2 = cv2.threshold (slika, 127.255, cv2.THRESH_BINARY_INV) cv2.imshow ('2 prag', thresh2) cv2.waitKey (0)
#value nad 127 so okrnjeni (zadržani) na 127, argument 255 je neuporabljen.
_, thresh3 = cv2.threshold (slika, 127.255, cv2.THRESH_TRUNC) cv2.imshow ('3 thresh trunc', thresh3) cv2.waitKey (0)
#vrednosti pod 127 gre na 0, nad 127 so nespremenjene
_, thresh4 = cv2.threshold (slika, 127.255, cv2.THRESH_TOZERO) cv2.imshow ('4 prag', thresh4) cv2.waitKey (0)
#Revesrse zgoraj, pod 127 je nespremenjen, nad 127 gre na nič
_, thresh5 = cv2.threshold (slika, 127.255, cv2.THRESH_TOZERO_INV) cv2.imshow ('5 prag', thresh5) cv2.waitKey (0) cv2.destroyAllWindows ()
5. Razširitev, erozija, odpiranje / zapiranje
To so operacije na področju matematične morfologije
Razširitev - dodaja slikovne pike mejam predmeta na sliki.
Erozija - Odstrani slikovne pike na mejah predmeta na sliki.
Odpiranje - erozija, ki ji sledi dilatacija.
Zapiranje - dilatacija, ki ji sledi erozija.
Odpiranje je zelo koristno pri odstranjevanju zvoka na slikah, saj jo najprej z erozijo razredči (odstrani šum), nato pa jo razširi.
Zmeda z dilatacijo in erozijo
Včasih pride do zmede med dilatacijo in erozijo, običajno na slikah z belim ozadjem, saj opencv šteje belo ozadje kot sliko, ki jo je treba razširiti ali erodirati namesto prvotne slike, zato v tem primeru erozija deluje kot dilatacija in obratno, kot je prikazano na vzorcu slike prikazano spodaj.
Ne pozabite, da razširitev dodaja slikovne pike mejam predmetov na sliki, medtem ko Erozija odstranjuje slikovne pike na mejah predmetov na sliki
import cv2 import numpy as np image = cv2.imread ('imagecv.png', 0) cv2.imshow ('original', image) cv2.waitKey (0)
#Erosion
# določimo velikost jedra
jedro = np.ones ((5,5), np.uint8)
# zdaj sliko erodiramo, tukaj ponovitev ne pomeni, da želite sliko erodirati
erozija = cv2.erode (slika, jedro, ponovitve = 1) cv2.imshow ('Erozija', erozija) cv2.waitKey (0)
#dilatacija
dilation = cv2.dilate (slika, jedro, ponovitve = 1) cv2.imshow ('dilatacija', dilatacija) cv2.waitKey (0)
#opening, dobro za odstranjevanje hrupa
opening = cv2.morphologyEx (slika, cv2.MORPH_OPEN, jedro) cv2.imshow ('odpiranje', odpiranje) cv2.waitKey (0)
#closing, dobro za odstranjevanje hrupa
zapiranje = cv2.morphologyEx (slika, cv2.MORPH_CLOSE, jedro) cv2.imshow ('zapiranje', zapiranje) cv2.waitKey (0) cv2.destroyAllWindows ()
6. Zaznavanje robov in gradienti slike
Zaznavanje robov je zelo pomembno področje računalniškega vida, zlasti pri obravnavanju kontur.
Robove lahko definiramo kot meje slike, pravzaprav so to robovi, ki na slikah definirajo predmet, ki ohranja veliko informacij o sliki.
Formalno Robove lahko definiramo kot nenadne spremembe (diskontinuitete) na sliki in lahko kodirajo toliko informacij kot slikovne pike.
Zgornja slika prikazuje, kako računalniški vid prepozna in prepozna sliko.
Algoritmi za zaznavanje robov: - Obstajajo tri glavne vrste algoritmov za zaznavanje robov
- Sobel - za poudarjanje navpičnih ali vodoravnih slik.
- Laplacian - optimalen zaradi nizke stopnje napak, natančno določenih robov in natančnega zaznavanja.
- Canny Edge algoritem za zaznavanje (ki ga je John 1986 Canny prenesel leta 1986)
1. Uporabi Gaussovo zameglitev
2. Poišče gradient intenzivnosti slike
3. uporablja zatiranje, ki ni največje (tj. Odstrani slikovne pike, ki niso robovi).
4. Histereza uporablja prag (tj. Če je slikovna pika znotraj zgornjega in spodnjega praga, se šteje za rob)
uvoz cv2 uvoz numpy kot np image = cv2.imread ('input.jpg', 0) višina, širina = image.shape
#sobel
#extracting sobel robovi
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 algoritem za zaznavanje robov uporablja vrednosti gradienta kot praga
#v canny moramo navesti dve vrednosti: prag1 in prag2.
# Vsak gradient, večji od praga 2, velja za rob.
# kateri koli gradient večji od praga 1 se šteje za rob.
#vrednosti med pragom 1 in pragom 2 so bodisi kot robne bodisi
nerezne # glede na to, kako so povezane njihove intenzivnosti, v tem primeru se šteje katera koli vrednost pod 60 # brez robov, pri čemer se katera koli vrednost nad 120 šteje za robove.
canny = cv2.Canny (slika, 60.120) cv2.imshow ('canny', canny) cv2.waitKey (0) cv2.destroyAllWindows ()
14. Perspektiva in afinistična preobrazba
Naredimo korak nazaj in si oglejmo afine in neafinske transformacije, spodaj prikazana izvirna slika je očitno neafinska slika, saj se bodo robovi na neki točki srečali, vendar jo lahko poravnamo tako, da se upognemo in zavzamemo preoblikovati.
Za to perspektivno preobrazbo potrebujemo štiri koordinate izvirne slike in nato štiri točke izhodne slike, ki so označene s točkama_A in točkami_B. Najprej s pomočjo teh točk izračunamo matriko transformacije, M s pomočjo funkcije getPerspectiveTransform.
In potem je ta matrika dana funkciji warpPerspective za generiranje končnega izhoda.
Zdaj pa poskusimo najprej spremeniti perspektivo.
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 vogalov prvotne slike
points_A = np.float32 (,,,])
#koordinate 4 vogalov želenega izhoda
# uporabljamo razmerje papirja A4 1: 1,41
točke_B = np.float32 (,,,])
# uporabite dva sklopa dveh točk za izračun matrike prespektivne 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 preobrazba je enostavnejša od neafinske, saj potrebujemo le tri točke, da jo dobimo. Celoten postopek gre enako, toda namesto perspektivne transformacije imamo zdaj afino transformacijo in v funkciji shape namesto ročnega vnosa določimo stolpce in vrstice v warpAffine .
import cv2 import numpy as np import matplotlib.pyplot as plt image = cv2.imread ('box.jpg') vrstice, cols = image.shape cv2.imshow ('original', image) cv2.waitKey (0)
#koordinata 3 vogalov prvotne slike
points_A = np.float32 (,,])
#koordinate treh vogalov želenega izhoda
# uporabljamo razmerje papirja A4 1: 1,41
točke_B = np.float32 (,,])
# za izračun matrice Affine #transformation M uporabite dve skupini dveh točk
M = cv2.getAffineTransform (points_A, points_B) warped = cv2.warpAffine (slika, M, (stolpci, vrstice)) cv2.imshow ('warpaffine', warped) cv2.waitKey (0) cv2.destroyAllWindows ()
8. Aplikacija Live Sketch
Najprej si čestitajte, da ste se odzvali temu mini projektu, potem ko ste prebrali vse zgornje funkcije za obdelavo slik. V tem mini projektu Python OpenCV bomo spoznali nekaj novih konceptov zank in funkcij. Če poznate programiranje, morate imeti širšo predstavo o funkciji in zankah. Vendar pa v pythonu osnovni koncept zank in funkcij ostaja enak, vendar se način njihovega določanja nekoliko spremeni.
Torej na začetku tega programa lahko vidimo določeno skupino izjav pod naslovom „ def skica (slika): “ to je formalna definicija funkcije, ki je skupina izjav, ki sodelujejo pri določenem izhodu.
Ta skica je torej funkcija, v pythonu pa je funkcija definirana z "def" in se konča z znakom ":". Funkcije samodejno poravnajo tudi stavke, ki morajo biti znotraj funkcije ali lahko rečete, kateri so potrebni za pravilno delovanje funkcije. Torej, da bi izstopili iz funkcij, je bilo treba izjave popolnoma poravnati levo. Za nadaljnje reference se lahko obrnete na google o tem, kako so funkcije definirane v pythonu.
Torej smo v tej funkciji skice uvedli več plasti obdelave slik, ki se med seboj kombinirajo in dajo rezultat. Najprej se slika pretvori v sivine, tako da jo lahko opencv enostavno obdela, nato pa se na sivo lestvico nanese Gaussova zamegljenost, da se zmanjša šum. Nato se robovi izvlečejo s pomočjo algoritma zaznavanja robov pločevinke, nato pa se na rob definirano sliko uporabi binarna inverza, tukaj bi lahko binarno inverzo naredil tudi bitwise_NOT, vendar smo namerno izbrali ta prag binarno inverzno, saj daje svobodo nastavi svoje parametre, dokler ne dobimo jasne slike.
Upoštevajte tudi, da funkcija vzame sliko argumentov in vrne oba argumenta ret in masko. Medtem ko je ret logična vrednost, ki pove, da se funkcija uspešno izvaja ali ne, maska pa je končni izhod funkcije, tj. Obdelana slika.
Potem je drugi koncept delovanja spletne kamere v opencv, ki jo opravi funkcija cv2.VideoCapture (0) , ki sliko shrani v pokrov predmeta, ki ga je mogoče prebrati s funkcijo cap.read () , tudi tu, da omenimo zgornjo mejo. read () je znotraj neskončne zanke while, saj je neprekinjeno moral zajemati slike, da bi dobil občutek videa v živo, kjer bi bila hitrost sličic videoposnetka hitrost sličic vaše spletne kamere, ki je večinoma med 24 in 60 fps
cap.read () vrne ret in frame, kjer je ret Boolean, kar pomeni, da je bila funkcija uspešno zagnana ali ne, okvir pa vsebuje sliko, ki jo je posnela spletna kamera.
Spodaj je celotna koda Python OpenCV za zagon skice v živo
import cv2 import numpy kot np #sketch generiranje funkcije def skica (slika): # pretvori sliko v sivine img_gray = cv2.cvtColor (slika, cv2.COLOR_BGR2GRAY) # čiščenje slike z uporabo Gaussove zameglitve img_gray_blur = cv2.GaussianBlur (img__grag 5,5), 0) #extract robovi canny_edges = cv2.Canny (img_gray_blur, 10,70) #do invert binarizira sliko ret, mask = cv2.threshold (canny_edges, 70,255, cv2.THRESH_BINARY_INV) return mask #inicialize webcam, cap je objekt, ki ga zagotavlja zajem videa # vsebuje logično vrednost, ki označuje, ali je bila uspešna (ret) #it vsebuje tudi slike, zbrane s spletne kamere (frame) cap = cv2.VideoCapture (0), medtem ko 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 pozabite sprostiti spletne kamere s pomočjo cap.release () cap.release () cv2.destroyAllWindows ()
To je torej konec 2. dela manipulacije s slikami v Python-OpenCV. Za dobro podcenjevanje računalniškega vida in OpenCV si oglejte prejšnje članke (Začetek uporabe Python OpenCV in manipulacije s slikami v Python OpenCV (1. del) in s programom Computer Vision boste lahko naredili nekaj kul.