- 1. Operacions i emmascarament de bits
- 2. Convolució i desenfocament
- 3. Nitidesa: invertir la imatge borrosa
- 4. Trituració (binarització)
- 5. Dilatació, erosió, obertura / tancament
- 6. Detecció de vores i gradients d'imatge
- 14. Perspectiva i transformació afí
- 8. Aplicació de Live Sketch
En els tutorials anteriors, hem après sobre OpenCV i hem realitzat alguns processos bàsics d’imatges i, a continuació, en el següent tutorial hem fet alguna manipulació d’imatges a OpenCV com retallada, rotació, transformació d’imatges, etc. algunes tècniques més de manipulació d’imatges, com al final del tutorial, crearem un programa python-opencv per fer esbossos en directe a partir de la transmissió en directe de la càmera web. Aquesta aplicació utilitzarà moltes de les funcions de processament d’imatges que hem après fins ara o que aprendrem en aquest tutorial, de manera que aquest serà un bon exemple pràctic per cobrir totes les funcions.
Com es va explicar al tutorial anterior, OpenCV és Open Source Commuter Vision Library que té interfícies C ++, Python i Java i és compatible amb Windows, Linux, Mac OS, iOS i Android. Per tant, es pot instal·lar fàcilment a Raspberry Pi amb entorns Python i Linux. I Raspberry Pi amb OpenCV i càmera connectada es pot utilitzar per crear moltes aplicacions de processament d’imatges en temps real, com ara detecció de cares, bloqueig de cares, seguiment d’objectes, detecció de matrícules de cotxes, sistema de seguretat domèstica, etc.
En aquest tutorial, veurem algunes manipulacions d’imatges més utilitzant Python OpenCV. Aquí aprendrem a aplicar la següent funció a una imatge mitjançant Python OpenCV:
- Operacions i emmascarament a bits
- Convolució i desenfocament
- Nitidesa: inverteix la imatge borrosa
- Llindar (binarització)
- Dilatació, erosió, obertura / tancament
- Detecció de vores i gradients d'imatge
- Perspectiva i transformació afí
- Aplicació de Live Sketch
1. Operacions i emmascarament de bits
Les operacions a bits us ajuden a emmascarar les imatges i us ajuden a crear imatges senzilles.
Fer un quadrat
import cv2 import numpy com np # utilitzem només dues dimensions perquè es tracta d’una imatge en escala de grisos, si féssim servir una imatge #colored, hauríem utilitzat un rectangle = np.zeros ((300,300,3), np.uint8) # Fer un quadrat quadrat = np.zeros ((300.300), np.uint8) cv2.rectangle (quadrat, (50,50), (250.250), 255, -1) cv2.imshow ("quadrat", quadrat) cv2. waitKey (0)
Fer una el·lipse
el·lipse = np.zeros ((300.300), np.uint8) cv2.ellipse (el·lipse, (150.150), (150.150), 30.0.180.255, -1) cv2.imshow ("el·lipse", el·lipse) cv2.waitKey (0)

Experimentar amb operacions a bits
#AND_shows només on es creuen els dos
BitwiseAND = cv2.bitwise_and (quadrat, el·lipse) cv2.imshow ("AND", BitwiseAND) cv2.waitKey (0)
#OR_ mostra només on hi ha un quadrat o una el·lipse
BitwiseOR = cv2.bitwise_or (quadrat, el·lipse) cv2.imshow ("OR", BitwiseOR) cv2.waitKey (0)
#XOR_sobre només on existeix per si mateix
BitwiseXOR = cv2.bitwise_xor (quadrat, el·lipse) cv2.imshow ("XOR", BitwiseXOR) cv2.waitKey (0)
#NOT_shows tot allò que no forma part de l’el·lipse i que NO es pot aplicar només a una sola figura
BitwiseNOT_elp = cv2.bitwise_not (el·lipse) cv2.imshow ("NOT_ellipse", BitwiseNOT_elp) cv2.waitKey (0) cv2.destroyAllWindows ()

2. Convolució i desenfocament
Una convolució és una operació matemàtica realitzada en dues funcions que produeixen una tercera funció que normalment és una versió modificada de la funció original.
Imatge de sortida = imatge Funció Mida del nucli
En visió per ordinador, fem servir el nucli per especificar la mida sobre la qual executem la nostra funció de manipulació sobre la nostra imatge.
El desenfocament és una operació en què fem la mitjana dels píxels d'una regió (nucli)
OpenCV difumina una imatge aplicant nuclis, un nucli us indica com canviar el valor de qualsevol píxel en combinar-lo amb una quantitat diferent de píxels veïns; el nucli s’aplica a cada píxel de la imatge un per un per produir la imatge final.

Simplement dient, una convolució d’imatges és simplement un element que permet multiplicar dues matrius seguides d’una suma.
Simplement ho podem entendre amb el següent exemple.

L’anterior és un nucli 3X3.
Multipliquem per 1/25 per normalitzar, és a dir, sumant a 1, havíem estat augmentant la intensitat o disminuint la intensitat, com en el cas d’aclarir o enfosquir les imatges.
Anem a provar un mètode de difuminació opencv filter2D, donat per la funció cv2.filter2D (imatge, -1, nucli)
importa cv2 importa numpy com np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', imatge) cv2.waitKey (0)
#creació d’una matriu del nucli de 3x3
kernel_3x3 = np.ones ((3,3), np.float32) / 9
# fem servir cv2.filter2D per involucrar el nucli amb una imatge
borrós = cv2.filter2D (imatge, -1, nucli_3x3) cv2.imshow ('3x3_blurring', borrós) cv2.waitKey (0)
#creació d’una matriu del nucli de 7x7
kernel_7x7 = np.ones ((7,7), np.float32) / 49
# fem servir cv2.filter2D per involucrar el nucli amb una imatge
borrós = cv2.filter2D (imatge, -1, nucli_7x7) cv2.imshow ('7x7_blurring', borrós) cv2.waitKey (0) cv2.destroyAllWindows ()


També hi ha altres tipus de mètodes de desenfocament:
cv2.blur: fa un valor mitjà d’una finestra especificada.
cv2.GaussianBlur: similar, però utilitza una finestra gaussiana (amb més èmfasi en els punts del centre).
cv2.medianBlur: utilitza la mediana de tots els elements de la finestra.
cv2.bilateralFilter– Es difumina mantenint les vores afilades, conserva les vores i els detalls de la línia.
Veurem un per un a continuació, primer mostrarem la imatge original amb el codi següent:
importa cv2 importa numpy com np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', imatge) cv2.waitKey (0)
cv2.blur:
En aquest mètode es fa la mitjana fent girar la imatge amb un filtre de caixa normalitzat, que ocupa el lloc sota la caixa i substitueix l'element central. Aquí la mida de la caixa ha de ser imparella i positiva .
# cv2.blur desenfocament = cv2.blur (imatge, (3,3)) cv2.imshow ("Mitjana", desenfocament) cv2.waitKey (0)
cv2.GaussianBlur:
# cv2.GaussianBlur # en lloc del filtre de caixa, anem a provar el nucli Gaussian Gaussian = cv2.GaussianBlur (imatge, (7,7), 0) cv2.imshow ('Gaussian blurring', Gaussian) cv2.waitKey (0)
cv2.medianBlur:
Es necessita la mediana de tots els píxels sota l'àrea del nucli i l'element central se substitueix per aquest valor mitjà.
# cv2.medianBlur # pren la mediana de tots els píxels sota l'àrea del nucli i l'element central # es substitueix per aquest valor mitjà. mitjana = cv2.medianBlur (imatge, 5) cv2.imshow ('mitjana desenfocament', mitjana) cv2.waitKey (0)
Filtre cv2.bilateral:
El bilateral és molt eficaç en l’eliminació de soroll mantenint les vores afilades
# cv2.bilateralFilter #Bilateral és molt eficaç en l'eliminació del soroll, mantenint les vores afilades bilateral = cv2.bilateralFilter (imatge, 9,75,75) cv2.imshow ("desenfocament bilateral", bilateral) cv2.waitKey (0) cv2. destroyAllWindows ()

Imatge De-noising-non Local significa Denoising
importa cv2 importa numpy com np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', imatge) cv2.waitKey (0)
#parameter després de None és la intensitat del filtre 'h' (5-10 és un bon rang) #next és h per als components de color, es torna a establir amb el mateix valor que h
dst = cv2.fastNlMeansDenoisingColored (imatge, Cap, 6,6,7,21) cv2.imshow ("Fast significa denois", dst) cv2.waitKey (0) cv2.destroyAllWindows ()

Hi ha 4 variacions de denoising de mitjans no locals
cv2.fastNlMeansDenoising (): per a una imatge a escala única de grisos
cv2.fastNlMeansDenoisingColored (): imatge d’un sol color
cv2.fastNlmeansDenoisingMulti () - per a seqüències d'imatges en escala de grisos
cv2.fastNlmeansDenoisingcoloredMulti (): per a color de seqüència d'imatges
3. Nitidesa: invertir la imatge borrosa
La nitidesa és el contrari a la difuminació, enforteix o ressalta les vores de la imatge.
Kernel =,,
La nostra matriu del nucli suma un, de manera que no cal normalitzar-lo (és a dir, multiplicar-lo per un factor a la mateixa brillantor que l'original), si el nucli no es normalitza a 1 la imatge seria més brillant o més fosca.
importa cv2 importa numpy com np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', imatge) cv2.waitKey (0)
kernel_sharpening = np.array (,
])
#aplicant el nucli de nitidesa a la imatge d'entrada
nitidesa = cv2.filter2D (imatge, -1, kernel_sharpening) cv2.imshow ('imatge nítida ', nítida) cv2.waitKey (0) cv2.destroyAllWindows ()

4. Trituració (binarització)
El llindar és el fet de convertir una imatge en forma binària. A opencv hi ha una funció separada per al llindar definida com
Llindar Cv2. (imatge, valor llindar, valor màxim, tipus llindar)
Hi ha els següents tipus de llindars:
- cv2.THRESH_BINARY: el més comú
- cv2. THRESH_BINARY_INV: el més comú
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2. THRESH_TOZERO_INV
NOTA: cal convertir la imatge a escala de grisos abans de posar el llindar
importar cv2 importar numpy com np # carregar imatge com a escala de grisos image = cv2.imread ('gradient.jpg', 0) cv2.imshow ('original', imatge) cv2.waitKey (0)

#value per sota de 127 passa a 0 (negre) i per sobre de 127 passa a 255 (blanc)
_, batre1 = llindar cv2. (imatge, 127.255, cv2.THRESH_BINARY) cv2.imshow ('1 llindar', batre1) cv2.waitKey (0)
#valor inferior a 127 passa a 255 i valors superiors a 127 passa a 0 (revers de l'anterior)
_, throwh2 = cv2.threshold (imatge, 127.255, cv2.THRESH_BINARY_INV) cv2.imshow ('2 llindar', thrash2) cv2.waitKey (0)
#value per sobre de 127 es trunca (es manté) a 127, l'argument 255 no s'ha utilitzat.
_, thrush3 = llindar cv2. (imatge, 127.255, cv2.THRESH_TRUNC) cv2.imshow ('3 trunc trunc', trill3) cv2.waitKey (0)
Els # valors inferiors a 127 passen a 0 i els 127 superen els mateixos
_, thrash4 = cv2.threshold (imatge, 127.255, cv2.THRESH_TOZERO) cv2.imshow ('4 llindar', thrash4) cv2.waitKey (0)
#Revesrse de dalt, per sota de 127 no canvia, per sobre de 127 passa a zero
_, thrash5 = cv2.threshold (imatge, 127.255, cv2.THRESH_TOZERO_INV) cv2.imshow ('5 llindar', thrash5) cv2.waitKey (0) cv2.destroyAllWindows ()

5. Dilatació, erosió, obertura / tancament
Aquestes són les operacions en el camp de la morfologia matemàtica
Dilatació: afegeix píxels als límits de l'objecte en una imatge.
Erosió: elimina els píxels als límits de l'objecte d'una imatge.
Obertura: erosió seguida de dilatació.
Tancament: dilatació seguida d’erosió.
L’obertura és molt útil per eliminar les imatges ja que primer dilueix la imatge per erosió (elimina el soroll) i després la dilata.
Confusió amb dilatació i erosió
De vegades hi ha confusió entre dilatació i erosió generalment en imatges amb fons blanc, ja que l’opencv considera que el fons blanc és una imatge que s’ha de dilatar o erosionar en lloc de la imatge original, de manera que en aquest cas l’erosió funciona com a dilatació i viceversa, com es mostra a la mostra d’imatges. mostrat a continuació.

Recordeu que la dilatació afegeix píxels als límits dels objectes d'una imatge mentre que Erosion elimina els píxels als límits dels objectes d'una imatge
importar cv2 importar numpy com np image = cv2.imread ('imagecv.png', 0) cv2.imshow ('original', imatge) cv2.waitKey (0)

# Erosió
# definim la mida del nostre nucli
nucli = np.ones ((5,5), np.uint8)
#ara erosions la imatge, aquí la iteració no és quan voleu erosionar la imatge
erosió = cv2.erode (imatge, nucli, iteracions = 1) cv2.imshow ('Erosió', erosió) cv2.waitKey (0)
#dilatació
dilatació = cv2.dilata (imatge, nucli, iteracions = 1) cv2.imshow ("dilatació", dilatació) cv2.waitKey (0)
#obertura, bo per eliminar el soroll
obertura = cv2.morphologyEx (imatge, cv2.MORPH_OPEN, nucli) cv2.imshow ('obertura', obertura) cv2.waitKey (0)
#closing, bo per eliminar el soroll
tancament = cv2.morphologyEx (imatge, cv2.MORPH_CLOSE, nucli) cv2.imshow ("tancament", tancament) cv2.waitKey (0) cv2.destroyAllWindows ()

6. Detecció de vores i gradients d'imatge
La detecció de vores és una àrea molt important en la visió per computador, especialment quan es tracta de contorns.
Les vores es poden definir com a límits de la imatge, en realitat són vores que defineixen l’objecte de les imatges i conserven molta informació sobre la imatge.
Formalment, les vores es poden definir com a canvis sobtats (discontinuïtats) en una imatge i poden codificar tanta informació com píxels.


La imatge anterior mostra com la visió per ordinador identifica i reconeix la imatge.
Algorismes de detecció de vores: - Hi ha tres tipus principals d’algorismes de detecció de vores
- Sobel: per posar èmfasi en imatges verticals o horitzontals.
- Laplacià: òptim a causa de la baixa taxa d'errors, les vores ben definides i la detecció precisa.
- Algorisme de detecció de Canny Edge (descarregat per john.F. Canny el 1986)
1. Aplica el desenfocament gaussià
2. Troba el gradient d'intensitat de la imatge
3. aplica una supressió no màxima (és a dir, elimina els píxels que no són arestes).
4. La histèresi s'aplica al llindar (és a dir, si el píxel es troba dins del llindar superior i inferior, es considera com una vora)
importa cv2 importa numpy com np image = cv2.imread ('input.jpg', 0) height, width = image.shape
#sobel
#extreure vores de sobel
sobel_x = cv2.Sobel (imatge, cv2.CV_64F, 0,1, ksize = 5) sobel_y = cv2.Sobel (imatge, cv2.CV_64F, 1,0, ksize = 5) cv2.imshow ('original', imatge) cv2.waitKey (0) cv2.imshow ('sobelx', sobel_x) cv2.waitKey (0)
#Sobertament
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 (imatge, cv2.CV_64F) cv2.imshow ('Laplacian', laplacian) cv2.waitKey (0)
L'algoritme de detecció de vores #canny utilitza valors de gradient com a llindars
# en cany necessitem proporcionar dos valors: llindar1 i llindar2.
# qualsevol degradat superior al llindar 2 es considera una vora.
# qualsevol degradat superior al llindar 1 es considera que no és una vora.
Els #valors entre el llindar 1 i el llindar 2 són tant de vora com no de vora
#sobre la manera com es connecten les seves intensitats, en aquest cas qualsevol valor inferior a 60 es considera
#no arestes mentre que qualsevol valor superior a 120 es considera com a arestes.
canny = cv2.Canny (imatge, 60.120) cv2.imshow ('canny', canny ) cv2.waitKey (0) cv2.destroyAllWindows ()

14. Perspectiva i transformació afí
Fem un pas enrere i fem una ullada a les transformacions afines i no afines, la imatge original que es mostra a continuació és clarament una imatge no afina, ja que les vores es reuniran en algun moment, però, podem redreçar-la deformant i prenent la perspectiva transformar.
Per a aquesta transformació de perspectiva necessitem les quatre coordenades de la imatge original i, a continuació, els quatre punts de la imatge de sortida, es denoten per punts_A i punts_B. En primer lloc, amb l'ajut d'aquests punts, calculem una matriu de transformació, M amb l'ajut de la funció getPerspectiveTransform.
I després aquesta matriu es dóna a la funció warpPerspective per generar la sortida final.
Ara provem primer la transformació de la perspectiva.
import cv2 import numpy as np import matplotlib.pyplot as plt image = cv2.imread ('paper.jpg') cv2.imshow ('original', imatge) cv2.waitKey (0)
#coordenada de 4 cantons de la imatge original
points_A = np.float32 (,,,])
#coordenades de 4 cantons de la sortida desitjada
#utilitzem una proporció de paper A4 1: 1,41
points_B = np.float32 (,,,])
#utilitzeu els dos conjunts de dos punts per calcular la matriu de transformació, M
M = cv2.getPerspectiveTransform (points_A, points_B) warped = cv2.warpPerspective (imatge, M, (420.594)) cv2.imshow ('warpprespective', warped ) cv2.waitKey (0) cv2.destroyAllWindows ()

La transformació afina és més fàcil que la transformació no afina, ja que només necessitem tres punts per obtenir la transformada. Tot el procés segueix el mateix, però en lloc de transformar la perspectiva, ara tenim una transformació afí i també definim cols i files a warpAffine des de la funció de forma en lloc d’introduir-la manualment.
importar cv2 importar numpy com np importar matplotlib.pyplot com plt image = cv2.imread ('box.jpg') files, cols = image.shape cv2.imshow ('original', image) cv2.waitKey (0)
#coordenada de 3 cantons de la imatge original
points_A = np.float32 (,,])
#coordenades de 3 cantons de la sortida desitjada
#utilitzem una proporció de paper A4 1: 1,41
points_B = np.float32 (,,])
#utilitzeu els dos conjunts de dos punts per calcular la matriu de transformació afí
, M
M = cv2.getAffineTransform (points_A, points_B) warped = cv2.warpAffine (imatge, M, (cols, files)) cv2.imshow ('warpaffine', warped ) cv2.waitKey (0) cv2.destroyAllWindows ()

8. Aplicació de Live Sketch
En primer lloc, feliciteu-vos que heu inventat aquest mini projecte després de llegir totes les funcions de manipulació d'imatges anteriors. Així doncs, en aquest mini projecte de Python OpenCV aprendrem alguns conceptes nous de bucles i funcions. Si esteu familiaritzat amb la programació, heu de tenir una idea més àmplia de quina és la funció i els bucles. No obstant això, a Python el concepte bàsic de bucles i funcions continua sent el mateix, però el mètode per definir-los canvia una mica.
Així doncs, al començament d’aquest programa podem veure un grup determinat d’enunciats encapçalat sota el “ def sketch (imatge): ” es tracta d’una definició formal d’una funció, un grup d’instruccions que treballen junts per a una sortida determinada.
Per tant, aquest esbós és una funció, en funció de pitó es defineix per "def" i acaba amb una marca ":". També les afirmacions que cal que estiguin dins de la funció o que pugueu dir quines són necessàries perquè la funció funcioni correctament, estan alineades automàticament per la funció. Així, per sortir de les funcions, calia alinear totalment les sentències. Per obtenir més referències, podeu consultar a Google com es defineixen les funcions a Python.
Així doncs, en aquesta funció d'esbós hem introduït diverses capes de processament d'imatges que es combinen per donar una sortida. En primer lloc, la imatge es converteix en escala de grisos perquè l’opencv pugui processar-la fàcilment i després s’aplica un desenfocament gaussià a la imatge d’escala de grisos per reduir el soroll. A continuació, les vores s’extreuen amb l’ajut de l’algoritme de detecció de vores del cany i, a continuació , s’aplica una inversa binària a la imatge definida per la vora, aquí la inversa binària també es podria fer per bitwise_NOT, però havíem escollit deliberadament aquest llindar invers binari ja que dóna llibertat per establir els seus paràmetres fins obtenir una imatge clara.
També cal tenir en compte que la funció pren la imatge dels arguments i retorna els dos arguments ret i mask. Mentre que ret és el booleà que indica que la funció s'executa correctament o no i que la màscara és la sortida final de la funció, és a dir, la imatge processada.
A continuació, el segon concepte consisteix a fer funcionar la càmera web en opencv que es fa mitjançant la funció cv2.VideoCapture (0) , que emmagatzema la imatge en un tap d’ objecte que pot llegir-se amb la funció cap.read () , també aquí per assenyalar aquest límit. read () es troba dins del bucle while infinit ja que havia de capturar contínuament les imatges, per donar-li la sensació d’un vídeo en directe, on la freqüència de fotogrames del vídeo seria la freqüència de fotogrames de la vostra càmera web, que es troba entre 24 i 60 fps.
cap.read () retorna ret i frame, on ret és el booleà que indica que la funció s'ha executat o no amb èxit i que el frame conté la imatge presa per la càmera web.
A continuació es mostra el codi OpenCV complet de Python per executar el Live Sketch
importar cv2 importar numpy com np #sketch generant la funció def sketch (imatge): #converteix la imatge a escala de grisos img_gray = cv2.cvtColor (imatge, cv2.COLOR_BGR2GRAY) # neteja de la imatge amb desenfocament de Gauss img_gray_blur = cv2.GaussianBlur (img_gray_blur = cv2. 5,5), 0) #extract edge canny_edges = cv2.Canny (img_gray_blur, 10,70) # fer una inversió binaritza la imatge ret, mask = cv2.threshold (canny_edges, 70,255, cv2.THRESH_BINARY_INV) màscara de retorn #initialize webcam, cap és l'objecte proporcionat per la captura de vídeo # conté un booleà que indica si ha tingut èxit (ret) #it també conté les imatges recollides de la càmera web (frame) cap = cv2.VideoCapture (0) mentre és True: ret, frame = cap.read () cv2.imshow ('livesketcher', sketch (frame)) si cv2.waitKey (1) == 13: # 13 és el enterkey ruptura càmera #release i tancar la finestra, recordeu que ha d'alliberar la càmera web amb l'ajuda d'cap.release () cap.release () cv2.destroyAllWindows ()

Així doncs, aquest és el final de la part 2 de les manipulacions d’imatges a Python-OpenCV. Per obtenir una bona comprensió de la visió per ordinador i OpenCV, consulteu articles anteriors (Introducció a Python OpenCV i manipulacions d’imatges a Python OpenCV (primera part) i podreu fer alguna cosa divertit amb Computer Vision.
