- 1. Bitvis betjening og maskering
- 2. Konvolution og sløring
- 3. Skarphed - Omvendt billede sløres
- 4. Tærskning (binærisering)
- 5. Udvidelse, erosion, åbning / lukning
- 6. Kantregistrering og billedforløb
- 14. Perspektiv og affine-transformation
- 8. Live Sketch ansøgning
I de foregående tutorials har vi lært om OpenCV og udført nogle grundlæggende billedbehandling og derefter i næste tutorial har vi lavet noget billedmanipulation i OpenCV som beskæring, rotation, billedtransformation osv. Så i forlængelse af den tidligere Image Manipulation-tutorial, her lærer vi nogle flere billedmanipulationsteknikker som og i slutningen af tutorialen vil vi opbygge et python-opencv-program til at lave live-skitse fra live-feedet til webcam. Denne applikation bruger mange af de billedbehandlingsfunktioner, som vi hidtil har lært eller vil lære i denne vejledning, så dette vil være et godt praktisk eksempel til at dække alle funktionerne.
Som fortalt i den foregående vejledning er OpenCV Open Source Commuter Vision Library, der har C ++, Python og Java-grænseflader og understøtter Windows, Linux, Mac OS, iOS og Android. Så det kan let installeres i Raspberry Pi med Python og Linux-miljø. Og Raspberry Pi med OpenCV og tilsluttet kamera kan bruges til at oprette mange realtids billedbehandlingsapplikationer som ansigtsgenkendelse, ansigtslås, genstandssporing, bilnummerpladesporing, hjemmesikkerhedssystem osv.
I denne vejledning vil vi se nogle flere billedmanipulationer ved hjælp af Python OpenCV. Her lærer vi at anvende følgende funktion på et billede ved hjælp af Python OpenCV:
- Bitvis betjening og maskering
- Konvolution og sløring
- Skarphed - Omvendt billede sløres
- Tærskelværdi (binærisering)
- Udvidelse, erosion, åbning / lukning
- Kantregistrering og billedforløb
- Perspektiv & Affine Transform
- Live Sketch ansøgning
1. Bitvis betjening og maskering
Bitvis betjening hjælper dig med billedmaskering og hjælper dig med at oprette nogle enkle billeder.
At lave en firkant
import cv2 import numpy som np # vi bruger kun to dimensioner, fordi dette er et gråtonebillede, hvis vi brugte et #farvet billede, havde vi derefter brugt et rektangel = np.zeros ((300,300,3), np.uint8) # At lave en firkantet kvadrat = np. nuller ((300.300), np.uint8) cv2. Rektangel (kvadrat, (50,50), (250,250), 255, -1) cv2.imshow ("firkant", firkant) cv2. Vent nøgle (0)
At lave en ellipse
ellipse = np. nuller ((300,300), np.uint8) cv2.ellipse (ellipse, (150,150), (150,150), 30,0,180,255, -1) cv2.imshow ("ellipse", ellipse) cv2.waitKey (0)
Eksperimentere med bitvise operationer
#AND_ viser kun, hvor de to skærer hinanden
BitwiseAND = cv2.bitwise_and (firkant, ellipse) cv2.imshow ("AND", BitwiseAND) cv2.waitKey (0)
#OR_ viser kun hvor enten firkant eller ellipse er
BitwiseOR = cv2.bitwise_or (firkant, ellipse) cv2.imshow ("ELLER", BitwiseOR) cv2.waitKey (0)
#XOR_ viser kun, hvor den ene findes i sig selv
BitwiseXOR = cv2.bitwise_xor (firkant, ellipse) cv2.imshow ("XOR", BitwiseXOR) cv2.waitKey (0)
#NOT_ viser alt, hvad der ikke er en del af ellipsen, og IKKE-operationen kan kun anvendes på en enkelt figur
BitwiseNOT_elp = cv2.bitwise_not (ellipse) cv2.imshow ("NOT_ellipse", BitwiseNOT_elp) cv2.waitKey (0) cv2.destroyAllWindows ()
2. Konvolution og sløring
En foldning er en matematisk operation udført på to funktioner, der producerer en tredje funktion, som typisk er en modificeret version af den oprindelige funktion.
Outputbillede = billede Funktion Kernestørrelse
I computersyn bruger vi kerner til at specificere den størrelse, som vi kører vores manipuleringsfunktion over vores billede.
Sløring er en operation, hvor vi gennemsnitlig pixel inden for en region (Kerne)
OpenCV slører et billede ved at anvende kerner, en kerne fortæller dig, hvordan du ændrer værdien på en given pixel ved at kombinere det med forskellige mængder af nærliggende pixels, som kernen anvendes på hver pixel i billedet en efter en for at producere det endelige billede.
Simpelthen at sige, en billedkonvolution er simpelthen en elementvis multiplikation af to matricer efterfulgt af en sum.
Vi kan simpelthen forstå det ved følgende eksempel.
Ovenstående er en 3X3-kerne.
Vi multiplicerer med 1/25 for at normalisere, dvs. summe til 1, vi havde øget intensiteten eller formindsket intensiteten som i tilfælde af lysere eller mørkere billeder.
Lad os teste en opencv sløringsmetode filter2D, givet af funktionen cv2.filter2D (billede, -1, kerne)
import cv2 import numpy som np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
# opretter en 3x3 kernematrix
kernel_3x3 = np.ones ((3,3), np.float32) / 9
# vi bruger cv2.filter2D til at samle kernen med et billede
sløret = cv2.filter2D (billede, -1, kernel_3x3) cv2.imshow ('3x3_blurring', sløret) cv2.waitKey (0)
# opretter en 7x7 kernematrix
kernel_7x7 = np.ones ((7,7), np.float32) / 49
# vi bruger cv2.filter2D til at samle kernen med et billede
sløret = cv2.filter2D (billede, -1, kernel_7x7) cv2.imshow ('7x7_blurring', sløret) cv2.waitKey (0) cv2.destroyAllWindows ()
Der er også andre typer sløringsmetoder:
cv2.blur - Gennemsnitværdi over et bestemt vindue.
cv2.GaussianBlur - Ligner men bruger et Gaussisk vindue (mere vægt på punkter rundt om midten).
cv2.medianBlur– Bruger medianen af alle elementer i vinduet.
cv2.bilateralFilter– Slør, mens kanterne holdes skarpe, men bevarer kanterne og liniedetaljerne.
Vi ser en efter en nedenfor, først viser det originale billede ved hjælp af nedenstående kode:
import cv2 import numpy som np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
cv2.blur:
I denne metode udføres gennemsnitsværdi ved at samle billedet med et normaliseret boksfilter, dette indtager stedet under feltet og erstatter det centrale element. Her skal boksstørrelsen være mærkelig og positiv .
# cv2.blur slør = cv2.blur (billede, (3,3)) cv2.imshow ('Gennemsnit', sløring) cv2.waitKey (0)
cv2.GaussianBlur:
# cv2.GaussianBlur # i stedet for boksfilter, lad os prøve Gaussisk kerne Gaussian = cv2.GaussianBlur (billede, (7,7), 0) cv2.imshow ('Gaussian sløring', Gaussian) cv2.waitKey (0)
cv2.medianBlur:
Det tager medianen af alle pixels under kerneområdet, og det centrale element erstattes med denne medianværdi.
# cv2.medianBlur # tager medianen af alle pixels under kerneområdet og det centrale element # erstattes med denne medianværdi. median = cv2.medianBlur (billede, 5) cv2.imshow (median udviskning «, median) cv2.waitKey (0)
cv2.bilateralFilter:
Bilateral er meget effektiv til fjernelse af støj, mens kanterne holdes skarpe
# cv2.bilateralFilter #Bilateral er meget effektiv til fjernelse af støj, samtidig med at kanterne holdes skarpe bilaterale = cv2.bilateralFilter (billede, 9,75,75) cv2.imshow ('bilateral sløring', bilateral) cv2.waitKey (0) cv2. destroyAllWindows ()
Image De-noising-non Local betyder benævnelse
import cv2 import numpy som np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#parameter efter Ingen er filterstyrken 'h' (5-10 er et godt interval) # næste er h for farvekomponenter, indstillet med samme værdi som h igen
dst = cv2.fastNlMeansDenoisingColored (image, None, 6,6,7,21) cv2.imshow ('Fast betyder denois', dst) cv2.waitKey (0) cv2.destroyAllWindows ()
Der er 4 variationer af ikke-lokale midler, deroising
cv2.fastNlMeansDenoising () - til enkelt gråtonebillede
cv2.fastNlMeansDenoisingColored () - Enkeltfarvet billede
cv2.fastNlmeansDenoisingMulti () - til billedsekvens gråtoner
cv2.fastNlmeansDenoisingcoloredMulti () - til billedsekvens farvet
3. Skarphed - Omvendt billede sløres
Slibning er det modsatte af sløring, det styrker eller fremhæver på kanterne i billedet.
Kernel =,,
Vores kernematrix opsummerer en, så der er ikke behov for at normalisere (dvs. gange med en faktor til samme lysstyrke som originalen), hvis kernen ikke normaliseres til 1, ville billedet være lysere eller mørkere.
import cv2 import numpy som np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
kernel_sharpening = np.array (,
])
# anvendelse af slibekerne til inputbillede
skærpet = cv2.filter2D (billede, -1, kernel_sharpening) cv2.imshow ('skærpet billede', skærpet) cv2.waitKey (0) cv2.destroyAllWindows ()
4. Tærskning (binærisering)
Tærskelværdi er handling at konvertere et billede til binær form. I opencv er der separat funktion til tærskelværdi defineret som
Cv2.threshold (billede, tærskelværdi, maks. Værdi, tærskeltype)
Der er følgende tærskeltyper:
- cv2.THRESH_BINARY - mest almindelige
- cv2. THRESH_BINARY_INV - mest almindelige
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2. THRESH_TOZERO_INV
BEMÆRK: billede er nødvendigt for at konverteres til gråtoner inden tærskelværdi
import cv2 import numpy som np #load image as grayscale image = cv2.imread ('gradient.jpg', 0) cv2.imshow ('original', image) cv2.waitKey (0)
#værdi under 127 gå til 0 (sort), og over 127 gå til 255 (hvid)
_, thresh1 = cv2.threshold (billede, 127,255, cv2.THRESH_BINARY) cv2.imshow ('1 tærskel', thresh1) cv2.waitKey (0)
#værdi under 127 går til 255 og værdier over 127 går til 0 (omvendt af ovenstående)
_, thresh2 = cv2.threshold (billede, 127,255, cv2.THRESH_BINARY_INV) cv2.imshow ('2 tærskel', thresh2) cv2.waitKey (0)
#værdi over 127 afkortes (holdes) ved 127, 255-argumentet er ubrugt.
_, thresh3 = cv2.threshold (billede, 127,255, cv2.THRESH_TRUNC) cv2.imshow ('3 thresh trunc', thresh3) cv2.waitKey (0)
#værdier under 127 går til 0, over 127 er uændrede
_, thresh4 = cv2.threshold (billede, 127,255, cv2.THRESH_TOZERO) cv2.imshow ('4 tærskel', thresh4) cv2.waitKey (0)
#Revesrse af ovenstående, under 127 er uændret, over 127 går til nul
_, thresh5 = cv2.threshold (billede, 127,255, cv2.THRESH_TOZERO_INV) cv2.imshow ('5 tærskel', thresh5) cv2.waitKey (0) cv2.destroyAllWindows ()
5. Udvidelse, erosion, åbning / lukning
Dette er operationerne inden for matematisk morfologi
Udvidelse - det tilføjer pixels til objektets grænser i et billede.
Erosion - Fjerner pixels ved objektets grænser i et billede.
Åbning - Erosion efterfulgt af udvidelse.
Afslutning - udvidelse efterfulgt af erosion.
Åbning er meget nyttigt ved at benægte billederne, da det først fortynder billedet ved erosion (fjerner støj) og derefter udvider det.
Forvirring med udvidelse og erosion
Der er undertiden forveksling mellem udvidelse og erosion normalt i billeder med hvid baggrund, da opencv betragter hvid baggrund som billede, der skal udvides eller eroderes i stedet for originalt billede, så i dette tilfælde fungerer erosion som udvidelse og omvendt, som vist i billedeksempel vist nedenfor.
Husk, udvidelse tilføjer pixels til grænserne for objekter i et billede, mens Erosion fjerner pixels ved grænserne for objekter i et billede
import cv2 import numpy som np image = cv2.imread ('imagecv.png', 0) cv2.imshow ('original', image) cv2.waitKey (0)
#Erosion # lad os definere vores kernestørrelse
kerne = np.ones ((5,5), np.uint8)
# nu eroderer vi billedet, her er iteration ikke de gange, du vil slette billedet
erosion = cv2.erode (billede, kerne, iterationer = 1) cv2.imshow ('Erosion', erosion) cv2.waitKey (0)
# udvidelse
udvidelse = cv2.dilate (billede, kerne, iterationer = 1) cv2.imshow ('udvidelse', udvidelse) cv2.waitKey (0)
#åbning, God til fjernelse af støj
åbning = cv2.morphologyEx (billede, cv2.MORPH_OPEN, kerne) cv2.imshow ('åbning', åbning) cv2.waitKey (0)
#closing, God til fjernelse af støj
lukning = cv2.morphologyEx (billede, cv2.MORPH_CLOSE, kerne) cv2.imshow ('lukning', lukning) cv2.waitKey (0) cv2.destroyAllWindows ()
6. Kantregistrering og billedforløb
Kantdetektion er meget vigtigt område i computersyn, især når man beskæftiger sig med konturer.
Kanter kan defineres som billedgrænser, faktisk er de kanter, der definerer objekt i billeder, de bevarer en masse information om billedet.
Formelt kanter kan defineres som pludselige ændringer (diskontinuiteter) i et billede, og de kan kode så meget information som pixels.
Ovenstående billede viser, hvordan computersyn identificerer og genkender billedet.
Kantdetekteringsalgoritmer: - Der er tre hovedtyper af kantdetekteringsalgoritmer
- Sobel - for at lægge vægt på lodrette eller vandrette billeder.
- Laplacian - optimal på grund af lav fejlrate, veldefinerede kanter og nøjagtig detektion.
- Canny Edge-detekteringsalgoritme (devolped af john F. Canny i 1986)
1. Anvender Gaussisk sløring
2. Finder intensitetsgradient af billedet
3. anvender ikke-maksimal undertrykkelse (dvs. fjerner pixels, der ikke er kanter).
4. Hysterese anvender tærskel (dvs. hvis pixel er inden for den øvre og nedre tærskel, betragtes det som en kant)
import cv2 import numpy som np image = cv2.imread ('input.jpg', 0) højde, bredde = image.shape
#sobel
# udtrækning af sobel kanter
sobel_x = cv2.Sobel (billede, cv2.CV_64F, 0,1, ksize = 5) sobel_y = cv2.Sobel (billede, cv2.CV_64F, 1,0, ksize = 5) cv2.imshow ('original', billede) cv2.waitKey (0) cv2.imshow ('sobelx', sobel_x) cv2.waitKey (0)
#Snak
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 (billede, cv2.CV_64F) cv2.imshow ('Laplacian', laplacian) cv2.waitKey (0)
#canny edge detection algoritme bruger gradientværdier som tærskler
# i canny skal vi give to værdier: tærskel1 og tærskel2 .
# enhver gradient større end tærskel 2 betragtes som en kant.
# enhver gradient, der er større end tærskel 1, anses for ikke at være en kant.
#values i mellem tærskel 1 og tærskel 2 er enten som kant eller ikke-kant
#on hvordan deres intensiteter, beror dette tilfælde enhver værdi under 60 er betragtes
#non kanter wheareas enhver værdi over 120 betragtes som kanter.
canny = cv2.Canny (billede, 60.120) cv2.imshow ('canny', canny ) cv2.waitKey (0) cv2.destroyAllWindows ()
14. Perspektiv og affine-transformation
Lad os tage et skridt tilbage og se på affine og ikke-affine transformationer, det originale billede vist nedenfor er helt klart et ikke-affint billede, da kanterne kommer til at mødes på et tidspunkt, men vi kan rette det ved at vride og tage perspektivet transformere.
Til denne perspektivtransformation har vi brug for de fire koordinater for det originale billede og derefter de fire punkter i outputbilledet, de er betegnet med point_A og points_B. For det første beregner vi en transformationsmatrix ved hjælp af disse punkter, M ved hjælp af getPerspectiveTransform-funktionen.
Og så gives denne matrix til warpPerspective- funktionen for at generere det endelige output.
Lad os nu prøve perspektivtransformationen.
import cv2 import numpy som np import matplotlib.pyplot som plt image = cv2.imread ('paper.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#koordinat af 4 hjørner af det originale billede
point_A = np.float32 (,,,])
#koordinater på 4 hjørner af ønsket output
# vi bruger et forhold på et A4-papir 1: 1,41
point_B = np.float32 (,,,])
# Brug de to sæt med to punkter til at beregne den formodede transformationsmatrix, M
M = cv2.getPerspectiveTransform (points_A, points_B) warped = cv2.warpPerspective (image, M, (420,594)) cv2.imshow ('warpprespective', warped) cv2.waitKey (0) cv2.destroyAllWindows ()
Affine-transformation er lettere end den ikke-affine-transformation, da vi kun har brug for tre punkter for at få transformationen. Hele processen går den samme, men i stedet for perspektivtransformation har vi nu affinetransform, og også definerer vi cols og rækker i warpAffine fra formfunktionen i stedet for manuelt at indtaste den.
import cv2 import numpy som np import matplotlib.pyplot som plt image = cv2.imread ('box.jpg') rækker, cols = image.shape cv2.imshow ('original', image) cv2.waitKey (0)
#koordinat af 3 hjørner af det originale billede
point_A = np.float32 (,,])
#koordinater på 3 hjørner af ønsket output
# vi bruger et forhold på et A4-papir 1: 1,41
point_B = np.float32 (,,])
# Brug de to sæt med to punkter til at beregne
Affine # -transformationsmatrix, M
M = cv2.getAffineTransform (point_A, points_B) warped = cv2.warpAffine (billede, M, (cols, rækker)) cv2.imshow ('warpaffine', warped) cv2.waitKey (0) cv2.destroyAllWindows ()
8. Live Sketch ansøgning
Først og fremmest skal du lykønske dig selv, at du har gjort op til dette miniprojekt efter at have læst alle billedmanipulationsfunktionerne ovenfor. Så i dette miniprojekt af Python OpenCV skal vi lære nogle nye koncepter for sløjfer og funktioner. Hvis du er fortrolig med programmering, skal du have en bredere idé om, hvad funktionen og sløjferne er. Imidlertid forbliver i python det grundlæggende koncept for sløjfer og funktioner det samme, men metoden til at definere dem ændres lidt.
Så ved starten af dette program kan vi se en bestemt gruppe udsagn overskriften under " def sketch (image): " dette er en formel definition af en funktion, en gruppe udsagn arbejder sammen om en bestemt output.
Så denne skitse er en funktion, i pythonfunktion er defineret af “def” og slutter med et “:” -mærke. Også de udsagn, der kræves for at være inde i funktionen, eller du kan sige, hvad der kræves for at funktionen skal fungere korrekt, sidelinjeres automatisk af funktionen. Så for at komme ud af funktionerne skulle udsagnene være helt venstrejusteret. For de yderligere referencer kan du henvise til google om, hvordan funktionerne er defineret i python.
Så i denne skitsefunktion har vi introduceret flere lag af billedbehandling, der kombineres for at give et output. For det første konverteres billedet til gråtoner, så opencv let kan behandle det, og derpå påføres en Gaussisk sløring på gråskalabilledet for at reducere støj. Derefter ekstraheres kanterne ved hjælp af kaninens kantdetekteringsalgoritme, så anvendes en binær invers på det kantdefinerede billede, her kunne binær invers også gøres af bitwise_NOT, men vi havde bevidst valgt denne tærskel binære inverse, da det giver frihed at indstille dens parametre, indtil vi får et klart billede.
Også for at bemærke, at funktionen tager argumentbilledet og returnerer de to argumenter ret og maske. Mens ret er den boolske fortæller, at funktionen køres med succes eller ej, og masken er det endelige output af funktionen, dvs. det behandlede billede.
Derefter er det andet koncept at betjene webcam i opencv, der udføres af cv2.VideoCapture (0) -funktionen, som gemmer billedet i en objektkappe , som cap kan læses med cap.read () -funktionen, også her for at bemærke den cap. læse () er inde i det uendelige mens sløjfe, da det kontinuerligt skulle tage billederne for at give det en fornemmelse af en live video, hvor billedhastigheden for videoen ville være billedhastigheden på dit webcam, som for det meste er mellem 24 og 60 fps.
cap.read () returnerer ret og frame, hvor ret er den boolske, hvilket indikerer, at funktionen blev udført med succes eller ikke, og rammen indeholder det billede, der er taget af webcam.
Nedenfor er den komplette Python OpenCV-kode til kørsel af Live Sketch
import cv2 import numpy som np #skitsgenererende funktion def skitse (billede): #konverter billede til gråtoner img_gray = cv2.cvtColor (billede, cv2.COLOR_BGR2GRAY) #oprydning af billedet ved hjælp af Gaussisk sløring img_gray_blur = cv2.GaussianBlur (img_gray_blur = cv2.GaussianBlur 5,5), 0) #extract kanter canny_edges = cv2.Canny (img_gray_blur, 10,70) #do en invert binarize billedpræsentationsmidlet Ret, maske = cv2.threshold (canny_edges, 70,255, cv2.THRESH_BINARY_INV) tilbagevenden maske #initialize webcam, kasket er det objekt, som video capture #it indeholder en boolesk angiver, om det var en succes (RET) #it indeholder også de billeder, der er indsamlet fra webcam (frame) cap = cv2.VideoCapture (0) mens True: ret, frame = cap.read () cv2.imshow ('livesketcher', sketch (frame)) if cv2.waitKey (1) == 13: # 13 er enterkey break # frigør kamera og luk vindue, husk at frigive webkameraet ved hjælp af cap.release () cap.release () cv2.destroyAllWindows ()
Så dette er slutningen på del 2 af billedmanipulationer i Python-OpenCV. For at få en god underdrivelse af computersyn og OpenCV, skal du gennemgå tidligere artikler (Kom godt i gang med Python OpenCV og Image Manipulations i Python OpenCV (del 1), og du vil være i stand til at gøre noget sejt med Computer Vision.