- 1. Bitvis användning och maskering
- 2. Konvolution och suddighet
- 3. Skärpning - Omvänd bild blir suddig
- 4. Tröskodning (binärisering)
- 5. Utspänning, erosion, öppning / stängning
- 6. Kantavkänning och bildgradienter
- 14. Perspektiv & Affine Transform
- 8. Live Sketch-applikation
I de tidigare självstudierna har vi lärt oss om OpenCV och gjort lite grundläggande bildbehandling och sedan i nästa handledning har vi gjort en del bildmanipulation i OpenCV som beskärning, rotation, bildtransformation etc. Så i fortsättning med föregående bildmanipuleringshandledning, här lär vi oss några fler bildmanipuleringstekniker som och i slutet av självstudien kommer vi att bygga ett python-opencv-program för att skapa live-skisser från webbflödets live-flöde. Denna applikation kommer att använda många av bildbehandlingsfunktionerna som vi har lärt oss hittills eller kommer att lära oss i denna handledning, så detta kommer att vara ett bra praktiskt exempel för att täcka alla funktioner.
Som sagt i föregående handledning är OpenCV Open Source Commuter Vision Library som har C ++, Python och Java-gränssnitt och stöder Windows, Linux, Mac OS, iOS och Android. Så det kan enkelt installeras i Raspberry Pi med Python och Linux-miljö. Och Raspberry Pi med OpenCV och ansluten kamera kan användas för att skapa många realtidsbildbearbetningsapplikationer som ansiktsavkänning, ansiktslås, objektspårning, bilnummerplåtsdetektering, hemskyddssystem etc.
I den här handledningen kommer vi att se några fler bildmanipulationer med Python OpenCV. Här lär vi oss att tillämpa följande funktion på en bild med Python OpenCV:
- Bitvis drift och maskering
- Konvolution och suddighet
- Skärpning - Omvänd bild blir suddig
- Tröskelvärde (binärisering)
- Utspänning, erosion, öppning / stängning
- Kantavkänning och bildgradienter
- Perspektiv & Affine Transform
- Live Sketch-applikation
1. Bitvis användning och maskering
Bitvis operation hjälper dig med bildmaskering och hjälper dig att skapa några enkla bilder.
Göra en fyrkant
importera cv2 import numpy som np # vi använder bara två dimensioner eftersom det här är en gråskalebild, om vi använde en #färgad bild hade vi sedan använt en rektangel = np. nollor ((300,300,3), np.uint8) # Göra en fyrkantig kvadrat = np. nollor ((300 300), np.uint8) cv2. rektangel (kvadrat, (50,50), (250 250), 255, -1) cv2.imshow ("kvadrat", kvadrat) cv2. waitKey (0)
Gör en ellips
ellips = np. nollor ((300,300), np.uint8) cv2.ellips (ellips, (150,150), (150,150), 30,0,180,255, -1) cv2.imshow ("ellips", ellips) cv2.waitKey (0)
Experimentera med bitvisa operationer
#AND_ visar bara var de två skär varandra
BitwiseAND = cv2.bitwise_and (kvadrat, ellips) cv2.imshow ("AND", BitwiseAND) cv2.waitKey (0)
#OR_visar bara var antingen kvadratisk eller ellips är
BitwiseOR = cv2.bitwise_or (kvadrat, ellips) cv2.imshow ("ELLER", BitwiseOR) cv2.waitKey (0)
#XOR_ visar bara där endera existerar av sig själv
BitwiseXOR = cv2.bitwise_xor (kvadrat, ellips) cv2.imshow ("XOR", BitwiseXOR) cv2.waitKey (0)
#NOT_shows allt som inte är en del av ellipsen och INTE kan endast användas på en siffra
BitwiseNOT_elp = cv2.bitwise_not (ellipse) cv2.imshow ("NOT_ellipse", BitwiseNOT_elp) cv2.waitKey (0) cv2.destroyAllWindows ()
2. Konvolution och suddighet
En faltning är en matematisk operation som utförs på två funktioner som producerar en tredje funktion som vanligtvis är en modifierad version av den ursprungliga funktionen.
Utmatningsbild = bild Funktion Kärnstorlek
I datorsyn använder vi kärnor för att ange storleken över vilken vi kör vår manipuleringsfunktion över vår bild.
Oskärpa är en operation där vi genomsnittliga pixlarna inom en region (Kärna)
OpenCV suddar en bild genom att använda kärnor, en kärna berättar hur du ändrar värdet på en viss pixel genom att kombinera den med olika mängd närliggande pixlar som kärnan appliceras på varje pixel i bilden en efter en för att producera den slutliga bilden.
Enkelt sagt är en bildkonvolution helt enkelt en elementvis multiplikation av två matriser följt av en summa.
Vi kan helt enkelt förstå det genom följande exempel.
Ovanstående är en 3X3-kärna.
Vi multiplicerar med 1/25 för att normalisera dvs summan till 1 vi hade ökat intensiteten eller minskat intensiteten som i fallet med ljusare eller mörkare bilder.
Låt oss testa en opencv-suddighetsmetod filter2D, ges av funktionen cv2.filter2D (bild, -1, kärna)
importera cv2 importera numpy som np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
# skapar en 3x3 kärnmatris
kernel_3x3 = np.ones ((3,3), np.float32) / 9
# vi använder cv2.filter2D för att konvolvera kärnan med en bild
suddig = cv2.filter2D (bild, -1, kernel_3x3) cv2.imshow ('3x3_blurring', suddig) cv2.waitKey (0)
# skapar en 7x7 kärnmatris
kernel_7x7 = np.ones ((7,7), np.float32) / 49
# vi använder cv2.filter2D för att konvolvera kärnan med en bild
suddig = cv2.filter2D (bild, -1, kernel_7x7) cv2.imshow ('7x7_blurring', suddig) cv2.waitKey (0) cv2.destroyAllWindows ()
Det finns andra typer av suddighetsmetoder också:
cv2.blur - Medelvärde över ett angivet fönster.
cv2.GaussianBlur - Liknar men använder ett Gaussiskt fönster (mer tonvikt på punkter runt mitten).
cv2.medianBlur– Använder medianen av alla element i fönstret.
cv2.bilateralFilter– Oskärpa medan kanterna hålls vassa, men det bevarar kanterna och linjedetaljerna.
Vi ser en efter en nedan, först visar originalbilden med hjälp av nedanstående kod:
importera cv2 importera numpy som np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
cv2.blur:
I den här metoden görs medelvärdet genom att konvolvera bilden med ett normaliserat boxfilter, detta tar plats under rutan och ersätter det centrala elementet. Här måste lådstorleken vara udda och positiv .
# cv2.blur oskärpa = cv2.blur (bild, (3,3)) cv2.imshow ('Averaging', oskärpa) cv2.waitKey (0)
cv2.GaussianBlur:
# cv2.GaussianBlur # istället för boxfilter, låt oss prova Gaussisk kärna Gaussian = cv2.GaussianBlur (bild, (7,7), 0) cv2.imshow ('Gaussian blurring', Gaussian) cv2.waitKey (0)
cv2.medianBlur:
Det tar medianen av alla pixlar under kärnområdet och centralt element ersätts med detta medianvärde.
# cv2.medianBlur # tar medianen av alla pixlar under kärnområdet och det centrala elementet # ersätts med detta medianvärde. median = cv2.medianBlur (bild, 5) cv2.imshow ('median suddighet', median) cv2.waitKey (0)
cv2.bilateralFilter:
Bilateralt är mycket effektivt vid avlägsnande av ljud samtidigt som kanterna hålls skarpa
# cv2.bilateralFilter #Bilateral är mycket effektivt vid avlägsnande av brus samtidigt som kanterna hålls skarpa bilaterala = cv2.bilateralFilter (bild, 9,75,75) cv2.imshow ('bilateral suddighet', bilateral) cv2.waitKey (0) cv2. destroyAllWindows ()
Bild De-noising-non Lokalt betyder denoising
importera cv2 importera numpy som np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#parameter efter Ingen är filterstyrkan 'h' (5-10 är ett bra intervall) # nästa är h för färgkomponenter, ställ in samma värde som h igen
dst = cv2.fastNlMeansDenoisingColored (image, None, 6,6,7,21) cv2.imshow ('Fast means denois', dst) cv2.waitKey (0) cv2.destroyAllWindows ()
Det finns fyra varianter av icke-lokala medel denoising
cv2.fastNlMeansDenoising () - för en gråskalebild
cv2.fastNlMeansDenoisingColored () - Enfärgad bild
cv2.fastNlmeansDenoisingMulti () - för bildsekvens gråskala
cv2.fastNlmeansDenoisingcoloredMulti () - för bildsekvens färgad
3. Skärpning - Omvänd bild blir suddig
Slipning är motsatsen till suddighet, den stärker eller betonar på kanterna i bilden.
Kernel =,,
Vår kärnmatris summeras upp till en, så det finns inget behov av att normalisera (dvs. multiplicera med en faktor till samma ljusstyrka som originalet), om kärnan inte normaliseras till 1 skulle bilden bli ljusare eller mörkare.
importera cv2 importera numpy som np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
kernel_sharpening = np.array (,
])
#applicera skärpningskärna för inmatad bild
skärpt = cv2.filter2D (bild, -1, kernel_sharpening) cv2.imshow ('skärpt bild', skärpt) cv2.waitKey (0) cv2.destroyAllWindows ()
4. Tröskodning (binärisering)
Tröskelvärde är att konvertera en bild till binär form. I opencv finns en separat funktion för tröskling definierad som
Cv2.threshold (bild, tröskelvärde, maxvärde, tröskeltyp)
Det finns följande tröskeltyper:
- cv2.THRESH_BINARY - vanligast
- cv2. THRESH_BINARY_INV - vanligast
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2. THRESH_TOZERO_INV
OBS: bilden behövs för att konverteras till gråskala innan tröskelvärde
importera cv2 importera numpy som np #load image as gråskalebild = cv2.imread ('gradient.jpg', 0) cv2.imshow ('original', image) cv2.waitKey (0)
#värde under 127 går till 0 (svart) och över 127 går till 255 (vit)
_, thresh1 = cv2.threshold (bild, 127,255, cv2.THRESH_BINARY) cv2.imshow ('1 tröskel', thresh1) cv2.waitKey (0)
#värde under 127 går till 255 och värden över 127 går till 0 (omvänd av ovan)
_, thresh2 = cv2.threshold (bild, 127,255, cv2.THRESH_BINARY_INV) cv2.imshow ('2 tröskel', thresh2) cv2.waitKey (0)
#värde över 127 trunkeras (hålls) vid 127, argumentet 255 är oanvänt.
_, thresh3 = cv2.threshold (image, 127,255, cv2.THRESH_TRUNC) cv2.imshow ('3 thresh trunc', thresh3) cv2.waitKey (0)
#värden under 127 går till 0, över 127 är oförändrade
_, thresh4 = cv2.threshold (bild, 127,255, cv2.THRESH_TOZERO) cv2.imshow ('4 tröskel', thresh4) cv2.waitKey (0)
#Revesrse ovan, under 127 är oförändrad, över 127 går till noll
_, thresh5 = cv2.threshold (bild, 127,255, cv2.THRESH_TOZERO_INV) cv2.imshow ('5 tröskel', thresh5) cv2.waitKey (0) cv2.destroyAllWindows ()
5. Utspänning, erosion, öppning / stängning
Dessa är operationerna inom matematisk morfologi
Utvidgning - det lägger till pixlar till gränserna för objektet i en bild.
Erosion - Tar bort pixlar vid gränserna för objektet i en bild.
Öppning - Erosion följt av utvidgning.
Avslutning - utspädning följt av erosion.
Öppning är till stor hjälp för att avbilda bilderna eftersom den först tunnar ut bilden genom erosion (tar bort ljudet) och utvidgar den sedan.
Förvirring med utvidgning och erosion
Ibland är det förvirring mellan utvidgning och erosion vanligtvis i bilder med vit bakgrund, eftersom opencv betraktar vit bakgrund som bild som ska utvidgas eller eroderas istället för originalbild, så i detta fall fungerar erosion som utvidgning och vice versa, som visas i bildprovet visas nedan.
Kom ihåg att Dilation lägger till pixlar till gränserna för objekt i en bild medan Erosion tar bort pixlar vid gränserna för objekt i en bild
importera cv2 importera numpy som np image = cv2.imread ('imagecv.png', 0) cv2.imshow ('original', image) cv2.waitKey (0)
#Erosion
# låt oss definiera vår kärnstorlek
kärna = np.ones ((5,5), np.uint8)
#nod eroderar vi bilden, här är iteration inte gånger du vill erodera bilden
erosion = cv2.erode (bild, kärna, iterationer = 1) cv2.imshow ('Erosion', erosion) cv2.waitKey (0)
#utvidgning
utvidgning = cv2.dilate (bild, kärna, iterationer = 1) cv2.imshow ('utvidgning', utvidgning) cv2.waitKey (0)
#öppning, bra för att ta bort bullret
opening = cv2.morphologyEx (image, cv2.MORPH_OPEN, kärna) cv2.imshow ('opening', opening) cv2.waitKey (0)
#closing, Bra för att ta bort buller
stängning = cv2.morphologyEx (bild, cv2.MORPH_CLOSE, kärna) cv2.imshow ('stängning', stängning) cv2.waitKey (0) cv2.destroyAllWindows ()
6. Kantavkänning och bildgradienter
Kantavkänning är ett mycket viktigt område i datorns syn, särskilt när man hanterar konturer.
Kanter kan definieras som bildgränser, faktiskt är de kanter som definierar objekt i bilder, de bevarar mycket information om bilden.
Formellt kanter kan definieras som plötsliga förändringar (diskontinuiteter) i en bild och de kan koda lika mycket information som pixlar.
Ovanstående bild visar hur datorvision identifierar och känner igen bilden.
Kantdetekteringsalgoritmer: - Det finns tre huvudtyper av kantdetekteringsalgoritmer
- Sobel - för att betona vertikala eller horisontella bilder.
- Laplacian - optimal på grund av låg felfrekvens, väldefinierade kanter och noggrann detektering.
- Canny Edge-detekteringsalgoritm (utvecklats av john F. Canny 1986)
1. Tillämpar Gaussisk suddighet
2. Hittar bildens intensitetsgradient
3. tillämpar icke-maximal undertryckning (dvs. tar bort pixlar som inte är kanter).
4. Hysteres tillämpar tröskeln (dvs om pixel ligger inom den övre och nedre tröskeln, anses den som en kant)
importera cv2 importera numpy som np image = cv2.imread ('input.jpg', 0) höjd, bredd = image.shape
#sobel
#extraherar sobelkanter
sobel_x = cv2.Sobel (bild, cv2.CV_64F, 0,1, ksize = 5) sobel_y = cv2.Sobel (bild, cv2.CV_64F, 1,0, ksize = 5) cv2.imshow ('original', bild) 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 (bild, cv2.CV_64F) cv2.imshow ('Laplacian', laplacian) cv2.waitKey (0)
#canny edge detection algoritm använder gradientvärden som tröskelvärden
# i canny behöver vi ge två värden: tröskel1 och tröskel2.
# någon gradient större än tröskel 2 anses vara en kant.
# någon gradient större än tröskel 1 anses inte vara en kant.
#values däremellan tröskelvärde 1 och tröskel 2 är antingen som kant eller icke-kant
#on hur deras intensiteter är, förbundna i detta fall något värde under 60 är betraktas
#non kanter wheareas något värde ovanför 120 betraktas som kanter.
canny = cv2.Canny (bild, 60,120) cv2.imshow ('canny', canny) cv2.waitKey (0) cv2.destroyAllWindows ()
14. Perspektiv & Affine Transform
Låt oss ta ett steg tillbaka och titta på affina och icke-affina transformationer, originalbilden som visas nedan är helt klart en icke-affin bild eftersom kanterna kommer att mötas någon gång, men vi kan räta ut den genom att vrida och ta perspektiv omvandla.
För denna perspektivtransformation behöver vi de fyra koordinaterna för originalbilden och sedan de fyra punkterna i den utgående bilden, de betecknas med punkter_A och punkter_B. Först med hjälp av dessa punkter beräknar vi en transformationsmatris, M med hjälp av getPerspectiveTransform-funktionen.
Och sedan ges denna matris till warpPerspective- funktionen för att generera den slutliga utgången.
Låt oss nu försöka Perspektivtransformen.
importera cv2 importera numpy som np importera matplotlib.pyplot som plt image = cv2.imread ('paper.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#koordinat av fyra hörn av originalbilden
poäng_A = np.float32 (,,,])
#koordinater med 4 hörn av önskad utgång
# vi använder ett förhållande mellan A4-papper 1: 1,41
poäng_B = np.float32 (,,,])
#använd de två uppsättningarna med två punkter för att beräkna den förväntade transformationsmatrisen, M
M = cv2.getPerspectiveTransform (points_A, points_B) warped = cv2.warpPerspective (image, M, (420,594)) cv2.imshow ('warpprespective', warped) cv2.waitKey (0) cv2.destroyAllWindows ()
Affinetransformation är lättare än icke-affinetransformationen eftersom vi bara behöver tre poäng för att få transformationen. Hela processen går detsamma men istället för perspektivtransform har vi nu affinetransform och också definierar vi kol och rader i warpAffine från formfunktionen istället för att manuellt ange den.
importera cv2 importera numpy som np importera matplotlib.pyplot som plt image = cv2.imread ('box.jpg') rader, cols = image.shape cv2.imshow ('original', image) cv2.waitKey (0)
#koordinat av 3 hörn av originalbilden
poäng_A = np.float32 (,,])
#koordinater med 3 hörn av önskad utgång
# vi använder ett förhållande mellan A4-papper 1: 1,41
poäng_B = np.float32 (,,])
# använd de två uppsättningarna av två punkter för att beräkna
Affine #transformation-matrisen, M
M = cv2.getAffineTransform (points_A, points_B) warped = cv2.warpAffine (image, M, (cols, rows)) cv2.imshow ('warpaffine', warped) cv2.waitKey (0) cv2.destroyAllWindows ()
8. Live Sketch-applikation
Först och främst, gratulera dig själv att du har gjort upp det här miniprojektet efter att ha läst alla bildmanipulationsfunktionerna ovan. Så i detta miniprojekt av Python OpenCV ska vi lära oss några nya koncept för loopar och funktioner. Om du är bekant med programmering måste du ha en bredare uppfattning om vad funktionen och slingorna är. I python förblir dock det grundläggande begreppet loopar och funktioner detsamma men metoden för att definiera dem förändras lite.
Så vid början av detta program kan vi se en viss grupp av uttalanden rubrik under " def skiss (bild): " detta är en formell definition av en funktion en grupp av uttalanden som arbetar tillsammans för en viss output.
Så denna skiss är en funktion, i python-funktionen definieras av "def" och slutar med ett ":" -märke. Även de påståenden som krävs för att vara inne i funktionen eller så kan du säga vilka som krävs för att funktionen ska fungera ordentligt, sidojusteras automatiskt av funktionen. Så för att komma ur funktionerna behövde uttalandena vara helt vänsterjusterade. För ytterligare referenser kan du hänvisa till google om hur funktionerna definieras i python.
Så i den här skissfunktionen har vi introducerat flera lager av bildbehandling som kombineras för att ge en output. Först omvandlas bilden till gråskala så att opencv enkelt kan bearbeta den och sedan appliceras en Gaussisk suddighet på gråskalebilden för att minska bullret. Sedan extraheras kanterna med hjälp av kaninens kantdetekteringsalgoritm, sedan appliceras en binär invers på den kantdefinierade bilden, här kan binär invers också göras av bitvis_NOT men vi hade medvetet valt denna tröskel binära invers eftersom det ger frihet för att ställa in dess parametrar tills vi får en tydlig bild.
Också för att notera att funktionen tar argumentbilden och returnerar de två argumenten ret och mask. Medan ret är den booleska som säger att funktionen körs framgångsrikt eller inte och masken är den slutliga utgången för funktionen, dvs. den bearbetade bilden.
Då andra konceptet är att driva webbkamera i OpenCV som görs av cv2.VideoCapture (0) funktion, som lagrar bilden i ett objekt cap att locket kan läsas med cap.read () funktion, även här att notera att locket. läs () är inne i det oändliga medan slingan eftersom det kontinuerligt var tvungen att ta bilder, för att ge det en känsla av en livevideo, där bildhastigheten för videon skulle vara bildfrekvensen för din webbkamera som mestadels är mellan 24 och 60 fps.
cap.read () returnerar ret och ram, där ret är den booleska som indikerar att funktionen har körts eller inte och ramen innehåller bilden som tagits av webbkameran.
Nedan är den fullständiga Python OpenCV-koden för att köra Live Sketch
importera cv2 importera numpy som np # skissgenererande funktion def skiss (bild): # konvertera bild till gråskala img_gray = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) #cleansing up the image using Gaussian oskärpa 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 vänd binärisera bild RET mask = cv2.threshold (canny_edges, 70,255, cv2.THRESH_BINARY_INV) returmask #initialize webbkamera, locket är föremål från video capture #it innehåller en Boolean som anger om det lyckades (RET) #it innehåller också bilderna som samlats in från webbkameran (frame) cap = cv2.VideoCapture (0) medan True: ret, frame = cap.read () cv2.imshow ('livesketcher', sketch (frame)) om cv2.waitKey (1) == 13: # 13 är enterkey break # släpp kamera och stäng fönster, kom ihåg att släppa webbkameran med hjälp av cap.release () cap.release () cv2.destroyAllWindows ()
Så detta är slutet på del 2 av bildmanipulationer i Python-OpenCV. För att få en bra undervärdering av datorns syn och OpenCV, gå igenom tidigare artiklar (Komma igång med Python OpenCV och Image Manipulations i Python OpenCV (del 1) så kommer du att kunna göra något coolt med Computer Vision.