- 1. Operații și mascare bitwise
- 2. Convoluție și estompare
- 3. Ascuțirea - inversarea imaginii neclare
- 4. Metodizare (binarizare)
- 5. Dilatare, eroziune, deschidere / închidere
- 6. Detectarea marginilor și gradienții de imagine
- 14. Perspectivă și transformare afină
- 8. Aplicația Live Sketch
În tutorialele anterioare, am aflat despre OpenCV și am făcut câteva prelucrări de bază ale imaginii și apoi în următorul tutorial am făcut o manipulare a imaginii în OpenCV, cum ar fi decuparea, rotația, transformarea imaginii etc. câteva alte tehnici de manipulare a imaginii precum și la sfârșitul tutorialului vom construi un program python-opencv pentru a face schițe live din fluxul live al camerei web. Această aplicație va utiliza multe dintre funcțiile de procesare a imaginilor pe care le-am învățat până acum sau le vom învăța în acest tutorial, deci acesta va fi un bun exemplu practic pentru a acoperi toate funcțiile.
Așa cum am spus în tutorialul anterior, OpenCV este Open Source Commuter Vision Library care are interfețe C ++, Python și Java și acceptă Windows, Linux, Mac OS, iOS și Android. Deci, poate fi instalat cu ușurință în Raspberry Pi cu mediul Python și Linux. Și Raspberry Pi cu OpenCV și cameră atașată poate fi folosit pentru a crea multe aplicații de procesare a imaginilor în timp real, cum ar fi detectarea feței, blocarea feței, urmărirea obiectelor, detectarea plăcilor de înmatriculare a mașinii, sistemul de securitate la domiciliu etc.
În acest tutorial, vom vedea câteva manipulări ale imaginii folosind Python OpenCV. Aici vom învăța să aplicăm următoarea funcție pe o imagine folosind Python OpenCV:
- Operații bit și mascare
- Convoluție și estompare
- Ascuțire - inversarea imaginii se estompează
- Prag (binarizare)
- Dilatare, eroziune, deschidere / închidere
- Detectarea marginilor și gradienții de imagine
- Perspectivă și transformare afină
- Aplicație Live Sketch
1. Operații și mascare bitwise
Operațiile bitwise vă ajută la mascarea imaginilor și vă ajută să creați câteva imagini simple.
Realizarea unui pătrat
import cv2 import numpy ca np # folosim doar două dimensiuni deoarece aceasta este o imagine în tonuri de gri, dacă am folosi o imagine #colored, am fi folosit apoi un dreptunghi = np.zeros ((300,300,3), np.uint8) # Realizarea unui pătrat pătrat = np.zeros ((300.300), np.uint8) cv2.rectangle (pătrat, (50,50), (250.250), 255, -1) cv2.imshow („pătrat”, pătrat) cv2. waitKey (0)
Realizarea unei elipse
elipsă = np.zeros ((300,300), np.uint8) cv2.ellipse (elipsă, (150,150), (150,150), 30,0,180,255, -1) cv2.imshow ("elipsă", elipsă) cv2.waitKey (0)
Experimentarea cu operații bit-bit
#AND_afișează numai acolo unde cele două se intersectează
BitwiseAND = cv2.bitwise_and (pătrat, elipsă) cv2.imshow ("ȘI", BitwiseAND) cv2.waitKey (0)
#OR_afișează numai acolo unde este pătrat sau elipsă
BitwiseOR = cv2.bitwise_or (pătrat, elipsă) cv2.imshow ("SAU", BitwiseOR) cv2.waitKey (0)
#XOR_ arată numai acolo unde există unul singur
BitwiseXOR = cv2.bitwise_xor (pătrat, elipsă) cv2.imshow ("XOR", BitwiseXOR) cv2.waitKey (0)
#NOT_afișează tot ceea ce nu face parte din elipsă și operațiunea NU poate fi aplicată doar unei singure cifre
BitwiseNOT_elp = cv2.bitwise_not (elipsă) cv2.imshow ("NOT_ellipse", BitwiseNOT_elp) cv2.waitKey (0) cv2.destroyAllWindows ()
2. Convoluție și estompare
O convoluție este o operație matematică efectuată pe două funcții care produc o a treia funcție care este de obicei o versiune modificată a funcției originale.
Imagine de ieșire = imagine Funcție Dimensiune nucleu
În viziunea computerizată, folosim nucleul pentru a specifica dimensiunea peste care rulăm funcția noastră de manipulare peste imaginea noastră.
Estomparea este o operațiune în care calculăm media pixelilor dintr-o regiune (Kernel)
OpenCV estompează o imagine prin aplicarea nucleelor, un nucleu vă spune cum să schimbați valoarea unui pixel dat, combinându-l cu o cantitate diferită de pixeli învecinați, nucleul este aplicat fiecărui pixel din imagine unul câte unul pentru a produce imaginea finală.
Spunând simplu, o convoluție a imaginii este pur și simplu o multiplicare înțeleaptă a elementelor a două matrice urmate de o sumă.
O putem înțelege pur și simplu prin următorul exemplu.
Cel de mai sus este un kernel 3X3.
Înmulțim cu 1/25 pentru a normaliza, adică suma la 1 am crescut intensitatea sau am micșorat intensitatea ca în cazul luminării sau întunecării imaginilor.
Să testăm o metodă de estompare opencv filter2D, dată de funcția cv2.filter2D (imagine, -1, kernel)
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#crearea unei matrice de nucleu 3x3
kernel_3x3 = np.ones ((3,3), np.float32) / 9
# folosim cv2.filter2D pentru a convolva nucleul cu o imagine
estompat = cv2.filter2D (imagine, -1, kernel_3x3) cv2.imshow („3x3_blurring”, estompat) cv2.waitKey (0)
#crearea unei matrice de nucleu 7x7
kernel_7x7 = np.ones ((7,7), np.float32) / 49
# folosim cv2.filter2D pentru a convolva nucleul cu o imagine
estompat = cv2.filter2D (imagine, -1, kernel_7x7) cv2.imshow ('7x7_blurring', estompat) cv2.waitKey (0) cv2.destroyAllWindows ()
Există și alte tipuri de metode de estompare:
cv2.blur - Valoarea medie pentru o fereastră specificată.
cv2.GaussianBlur - Similar, dar folosește o fereastră gaussiană (mai mult accent pe punctele din jurul centrului).
cv2.medianBlur– Utilizează mediana tuturor elementelor din fereastră.
cv2.bilateralFilter– Se estompează păstrând marginile ascuțite, păstrează marginile și detaliile liniei.
Vom vedea unul câte unul mai jos, afișăm mai întâi imaginea originală folosind codul de mai jos:
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
cv2.blur:
În această metodă, media se realizează prin convoluarea imaginii cu un filtru de cutie normalizat, acesta ocupă locul de sub cutie și înlocuiește elementul central. Aici dimensiunea cutiei trebuie să fie ciudată și pozitivă .
# cv2.blur blur = cv2.blur (imagine, (3,3)) cv2.imshow („Medie”, blur) cv2.waitKey (0)
cv2.GaussianBlur:
# cv2.GaussianBlur # în locul filtrului de casetă, să încercăm nucleul Gaussian Gaussian = cv2.GaussianBlur (imagine, (7,7), 0) cv2.imshow („Gaussian bluring”, Gaussian )
cv2.medianBlur:
Este nevoie de mediana tuturor pixelilor de sub zona nucleului și elementul central este înlocuit cu această valoare mediană.
# cv2.medianBlur # ia mediana tuturor pixelilor sub zona nucleului și elementul central #este înlocuit cu această valoare mediană. mediana = cv2.medianBlur (imagine, 5) cv2.imshow ('mediana estompează', mediană) cv2.waitKey (0)
cv2.bilateralFilter:
Bilateral este foarte eficient în eliminarea zgomotului, păstrând în același timp marginile ascuțite
# cv2.bilateralFilter #Bilateral este foarte eficient în eliminarea zgomotului, păstrând în același timp marginile ascuțite bilaterale = cv2.bilateralFilter (imagine, 9,75,75) cv2.imshow („estompare bilaterală”, bilaterală) cv2.waitKey (0) cv2. destroyAllWindows ()
Image De-noising-non Local înseamnă Denoising
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#parametru după Niciuna este puterea filtrului „h” (5-10 este o gamă bună) # următorul este h pentru componentele de culoare, setate la fel ca și h
dst = cv2.fastNlMeansDenoisingColored (imagine, None, 6,6,7,21) cv2.imshow („Fast înseamnă denois”, dst) cv2.waitKey (0) cv2.destroyAllWindows ()
Există 4 variante de denozare a mijloacelor nelocale
cv2.fastNlMeansDenoising () - pentru o imagine cu o singură scară de gri
cv2.fastNlMeansDenoisingColored () - Imagine cu o singură culoare
cv2.fastNlmeansDenoisingMulti () - pentru secvența de imagini în tonuri de gri
cv2.fastNlmeansDenoisingcoloredMulti () - pentru secvența de imagine colorată
3. Ascuțirea - inversarea imaginii neclare
Ascuțirea este opusul estompării, întărește sau accentuează marginile din imagine.
Kernel =,,
Matricea kernel-ului nostru se rezumă la unul, deci nu este nevoie să se normalizeze (adică se înmulțește cu un factor la aceeași luminozitate ca la original), dacă kernel-ul nu este normalizat la 1, imaginea ar fi mai strălucitoare sau mai închisă.
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
kernel_sharpening = np.array (,
])
#aplicarea nucleului de ascuțire la imaginea de intrare
ascuțit = cv2.filter2D (imagine, -1, kernel_sharpening) cv2.imshow („imagine ascuțită”, ascuțit) cv2.waitKey (0) cv2.destroyAllWindows ()
4. Metodizare (binarizare)
Pragul este actul de a converti o imagine în formă binară. În opencv există o funcție separată pentru prag definită ca
Cv2.prag (imagine, valoare prag, valoare maximă, tip prag)
Există următoarele tipuri de prag:
- cv2.THRESH_BINARY - cel mai frecvent
- cv2. THRESH_BINARY_INV - cel mai frecvent
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2. THRESH_TOZERO_INV
NOTĂ: imaginea este necesară pentru a fi convertită în tonuri de gri înainte de prag
import cv2 import numpy as np #load image as grayys image = cv2.imread ('gradient.jpg', 0) cv2.imshow ('original', image) cv2.waitKey (0)
#valour sub 127 merge la 0 (negru), iar peste 127 merge la 255 (alb)
_, treh1 = cv2.threshold (imagine, 127.255, cv2.THRESH_BINARY) cv2.imshow („1 prag”, treh1) cv2.waitKey (0)
#valour sub 127 merge la 255 și valorile peste 127 merge la 0 (inversul de mai sus)
_, treh2 = cv2.threshold (imagine, 127.255, cv2.THRESH_BINARY_INV) cv2.imshow („2 prag”, treh2) cv2.waitKey (0)
#value peste 127 sunt trunchiate (păstrate) la 127, argumentul 255 este neutilizat.
_, thresh3 = cv2.threshold (imagine, 127255, cv2.THRESH_TRUNC) cv2.imshow ('3 treierat trunc', thresh3) cv2.waitKey (0)
#valori sub 127 merge la 0, peste 127 sunt neschimbate
_, treh4 = cv2.threshold (imagine, 127.255, cv2.THRESH_TOZERO) cv2.imshow („4 prag”, treh4) cv2.waitKey (0)
#Revesrse de mai sus, sub 127 este neschimbat, peste 127 merge la zero
_, thresh5 = cv2.threshold (imagine, 127255, cv2.THRESH_TOZERO_INV) cv2.imshow ('5 prag', thresh5) cv2.waitKey (0) cv2.destroyAllWindows ()
5. Dilatare, eroziune, deschidere / închidere
Acestea sunt operațiile din domeniul morfologiei matematice
Dilatare - adaugă pixeli la limitele obiectului dintr-o imagine.
Eroziune - Elimină pixeli la limitele obiectului dintr-o imagine.
Deschidere - Eroziune urmată de dilatare.
Închidere - Dilatare urmată de eroziune.
Deschiderea este foarte utilă pentru dezinfectarea imaginilor, deoarece mai întâi subțiază imaginea prin eroziune (elimină zgomotul) și apoi o dilată.
Confuzie cu dilatare și eroziune
Uneori există confuzie între dilatare și eroziune de obicei în imaginile cu fundal alb, deoarece opencv consideră fundalul alb ca imagine care trebuie dilatată sau erodată în locul imaginii originale, deci în acest caz eroziunea funcționează ca dilatare și invers, așa cum se arată în exemplul de imagine prezentat mai jos.
Amintiți-vă, Dilatarea adaugă pixeli la limitele obiectelor dintr-o imagine, în timp ce Eroziunea elimină pixeli la limitele obiectelor dintr-o imagine.
import cv2 import numpy as np image = cv2.imread ('imagecv.png', 0) cv2.imshow ('original', image) cv2.waitKey (0)
# Eroziune
# să definim dimensiunea nucleului nostru
kernel = np.ones ((5,5), np.uint8)
#acum erodăm imaginea, aici iterația nu este de câte ori doriți să erodați imaginea
eroziune = cv2.erode (imagine, nucleu, iterații = 1) cv2.imshow („Eroziune”, eroziune) cv2.waitKey (0)
#dilatație
dilatare = cv2.dilate (imagine, nucleu, iterații = 1) cv2.imshow („dilatare”, dilatare) cv2.waitKey (0)
# deschidere, Bine pentru eliminarea zgomotului
deschidere = cv2.morphologyEx (imagine, cv2.MORPH_OPEN, kernel) cv2.imshow („deschidere”, deschidere) cv2.waitKey (0)
# închidere, bun pentru eliminarea zgomotului
închidere = cv2.morphologyEx (imagine, cv2.MORPH_CLOSE, kernel) cv2.imshow („închidere”, închidere) cv2.waitKey (0) cv2.destroyAllWindows ()
6. Detectarea marginilor și gradienții de imagine
Detectarea marginilor este o zonă foarte importantă în viziunea computerizată, mai ales atunci când se ocupă de contururi.
Marginile pot fi definite ca limite ale imaginii, de fapt sunt margini care definesc obiectul în imagini, păstrează o mulțime de informații despre imagine.
În mod formal, marginile pot fi definite ca modificări bruște (discontinuități) într-o imagine și pot codifica la fel de multe informații ca pixeli.
Imaginea de mai sus arată modul în care viziunea computerizată identifică și recunoaște imaginea.
Algoritmi de detectare a muchiilor: - Există trei tipuri principale de algoritmi de detectare a muchiilor
- Sobel - pentru a pune accent pe imagini verticale sau orizontale.
- Laplacian - optim datorită ratei de eroare reduse, a marginilor bine definite și a detectării precise.
- Algoritmul de detectare Canny Edge (devolut de John.F. Canny în 1986)
1. Aplică neclaritatea Gaussiană
2. Găsește gradientul de intensitate al imaginii
3. aplică suprimarea non-maximă (adică elimină pixeli care nu sunt margini).
4. Histerezisul aplică pragul (adică dacă pixelul se află în pragul superior și inferior, este considerat ca o margine)
import cv2 import numpy as np image = cv2.imread ('input.jpg', 0) height, width = image.shape
#sobel
#extragerea marginilor sobel
sobel_x = cv2.Sobel (imagine, cv2.CV_64F, 0,1, ksize = 5) sobel_y = cv2.Sobel (imagine, cv2.CV_64F, 1,0, ksize = 5) cv2.imshow („original”, imagine) cv2.waitKey (0) cv2.imshow ('sobelx', sobel_x) cv2.waitKey (0)
#Probabil
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 (imagine, cv2.CV_64F) cv2.imshow ('Laplacian', laplacian) cv2.waitKey (0)
# algoritmul de detectare a muchiei utilizează valorile gradientului ca praguri
#in canny trebuie să furnizăm două valori: pragul1 și pragul2 .
# orice gradient mai mare decât pragul 2 este considerat a fi o margine.
# orice gradient mai mare decât pragul 1 este considerat a nu fi o margine.
#valorile cuprinse între pragul 1 și pragul 2 sunt fie ca muchie sau non-muchie
#pe modul în care sunt conectate intensitățile lor, în acest caz orice valoare sub 60 este considerată
#non muchii, în timp ce orice valoare peste 120 este considerată drept margini.
canny = cv2.Canny (imagine, 60.120) cv2.imshow ('canny', canny) cv2.waitKey (0) cv2.destroyAllWindows ()
14. Perspectivă și transformare afină
Să facem un pas înapoi și să aruncăm o privire asupra transformărilor afine și non-afine, imaginea originală prezentată mai jos este clar o imagine non afină, deoarece marginile se vor întâlni la un moment dat, cu toate acestea, o putem îndrepta deformând și luând perspectiva transforma.
Pentru această transformare de perspectivă avem nevoie de cele patru coordonate ale imaginii originale și apoi cele patru puncte ale imaginii de ieșire, acestea sunt notate cu puncte_A și puncte_B. În primul rând cu ajutorul acestor puncte calculăm o matrice de transformare, M cu ajutorul funcției getPerspectiveTransform.
Și apoi această matrice este dată funcției warpPerspective pentru a genera rezultatul final.
Acum să încercăm mai întâi transformarea Perspective.
import cv2 import numpy as np import matplotlib.pyplot as plt image = cv2.imread ('paper.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#coordonată a 4 colțuri ale imaginii originale
points_A = np.float32 (,,,])
#coordonatele a 4 colțuri ale ieșirii dorite
# folosim un raport de hârtie A4 1: 1.41
points_B = np.float32 (,,,])
#utilizați cele două seturi de două puncte pentru a calcula matricea de transformare perspectivă , M
M = cv2.getPerspectiveTransform (points_A, points_B) warped = cv2.warpPerspective (imagine, M, (420.594)) cv2.imshow ('warpprespective', warped ) cv2.waitKey (0) cv2.destroyAllWindows ()
Transformarea afină este mai ușoară decât transformarea non-afină, deoarece avem nevoie doar de trei puncte pentru a obține transformarea. Întregul proces merge la fel, dar în loc de transformare de perspectivă avem acum transformare afină și, de asemenea, definim cols și rânduri în warpAffine din funcția de formă în loc să o introducem manual.
import cv2 import numpy as np import matplotlib.pyplot as plt image = cv2.imread ('box.jpg') rânduri, cols = image.shape cv2.imshow ('original', image) cv2.waitKey (0)
#coordonată a 3 colțuri ale imaginii originale
points_A = np.float32 (,,])
#coordonatele a 3 colțuri ale ieșirii dorite
# folosim un raport de hârtie A4 1: 1.41
points_B = np.float32 (,,])
#utilizați cele două seturi de două puncte pentru a calcula
matricea de transformare afină, M
M = cv2.getAffineTransform (points_A, points_B) warped = cv2.warpAffine (imagine, M, (cols, rânduri)) cv2.imshow ('warpaffine', warped ) cv2.waitKey (0) cv2.destroyAllWindows ()
8. Aplicația Live Sketch
În primul rând, felicitați-vă că ați inventat acest mini proiect după ce ați citit toate funcțiile de manipulare a imaginii de mai sus. Deci, în acest mini proiect al Python OpenCV vom învăța câteva concepte noi de bucle și funcții. Dacă sunteți familiarizat cu programarea, trebuie să aveți o idee mai largă despre funcția și buclele. Cu toate acestea, în python conceptul de bază al buclelor și funcțiilor rămâne același, dar metoda de a le defini se schimbă puțin.
Deci, la începutul acestui program, putem vedea un anumit grup de declarații care se află sub „ schița def (imagine): ” aceasta este o definiție formală a unei funcții, un grup de instrucțiuni care lucrează împreună pentru un anumit rezultat.
Deci, această schiță este o funcție, în funcția python este definită de „def” și se termină cu un semn „:”. De asemenea, declarațiile care trebuie să fie în interiorul funcției sau puteți spune care sunt necesare pentru ca funcția să funcționeze corect, sunt aliniate automat de funcție. Deci, pentru a ieși din funcții, afirmațiile trebuiau aliniate complet la stânga. Pentru referințele suplimentare, puteți consulta Google despre modul în care funcțiile sunt definite în python.
Deci, în această funcție de schiță am introdus mai multe straturi de procesare a imaginilor care se combină împreună pentru a da o ieșire. În primul rând, imaginea este convertită în tonuri de gri, astfel încât opencv-ul să o poată procesa cu ușurință și apoi se aplică o neclaritate gaussiană la imaginea la scară de gri, astfel încât să se reducă zgomotul. Apoi, marginile sunt extrase cu ajutorul algoritmului de detectare a muchiilor, apoi se aplică un invers binar pe imaginea definită de margine, aici inversul binar ar putea fi realizat și prin bitwise_NOT, dar am ales în mod deliberat acest prag invers binar, deoarece oferă libertate pentru a-și seta parametrii până când obținem o imagine clară.
De asemenea, să rețineți că funcția ia imaginea argumentelor și returnează cele două argumente ret și mască. În timp ce ret este boolean care spune că funcția este rulată cu succes sau nu, iar masca este rezultatul final al funcției, adică imaginea procesată.
Apoi, al doilea concept este de operare a camerei web în opencv, care este realizat de funcția cv2.VideoCapture (0) , care stochează imaginea într-un capac de obiect , care poate fi citit cu funcția cap.read () , tot aici pentru a nota acel capac. read () se află în bucla infinită de timp, deoarece a trebuit să surprindă în mod continuu imaginile, pentru a-i da impresia unui videoclip live, unde rata de cadre a videoclipului ar fi rata de cadre a camerei dvs. web, care este în mare parte între 24 și 60 fps.
cap.read () returnează ret și frame, unde ret este booleanul care indică faptul că funcția a fost rulată cu succes sau nu și cadrul conține imaginea făcută de camera web.
Mai jos este codul Python OpenCV complet pentru rularea Live Sketch
import cv2 import numpy ca np #sketch generând funcția def schiță (imagine): # converti imaginea în tonuri de gri img_gray = cv2.cvtColor (imagine, cv2.COLOR_BGR2GRAY) #curățarea imaginii folosind Gaussian blur img_gray_blur = cv2.GaussianBlur (img_ 5,5), 0) #extract margini canny_edges = cv2.Canny (img_gray_blur, 10,70) #fă o inversare binarizează imaginea ret, mask = cv2.threshold (canny_edges, 70,255, cv2.THRESH_BINARY_INV) returnează masca #initialize webcam, cap este obiectul furnizat de captura video # conține un boolean care indică dacă a avut succes (ret) #it conține, de asemenea, imaginile colectate de pe camera web (cadru) cap = cv2.VideoCapture (0) în timp ce este adevărat: ret, cadru = cap.read () cv2.imshow ('livesketcher', schiță (cadru)) dacă cv2.waitKey (1) == 13: # 13 este enterkey break #release camera și închide fereastra, nu uitați să eliberați camera web cu ajutorul cap.release () cap.release () cv2.destroyAllWindows ()
Deci acesta este sfârșitul părții 2 a Manipulărilor de imagine în Python-OpenCV. Pentru a cunoaște bine viziunea computerizată și OpenCV, consultați articolele anterioare (Noțiuni introductive despre Python OpenCV și Manipulări de imagine în Python OpenCV (Partea 1) și veți putea face ceva interesant cu Computer Vision.