- 1. Bitvis operasjon og maskering
- 2. Konvolusjon og uskarphet
- 3. Skarphet - Å reversere bildet blir uskarpt
- 4. Threshoding (binærisering)
- 5. Utvidelse, erosjon, åpning / lukking
- 6. Kanten deteksjon og bilde gradienter
- 14. Perspektiv & Affine Transform
- 8. Live Sketch-applikasjon
I de foregående opplæringene har vi lært om OpenCV og gjort noen grunnleggende bildebehandling, og i neste opplæring har vi gjort litt bildemanipulering i OpenCV som beskjæring, rotasjon, bildetransformasjon osv. Så i fortsettelse med forrige Image Manipulation tutorial, her lærer vi noen flere bildemanipuleringsteknikker som og på slutten av opplæringen, vil vi bygge et python-opencv-program for å lage live-skisser fra live-feedet til webkameraet. Denne applikasjonen vil bruke mange av bildebehandlingsfunksjonene som vi har lært så langt eller vil lære i denne opplæringen, så dette vil være et godt praktisk eksempel for å dekke alle funksjonene.
Som fortalt i forrige opplæring, er OpenCV Open Source Commuter Vision Library som har C ++, Python og Java-grensesnitt og støtter Windows, Linux, Mac OS, iOS og Android. Så det kan enkelt installeres i Raspberry Pi med Python og Linux-miljø. Og Raspberry Pi med OpenCV og tilkoblet kamera kan brukes til å lage mange sanntids bildebehandlingsapplikasjoner som ansiktsgjenkjenning, ansiktslås, gjenstandssporing, registreringsnummer for bilnummer, hjemmesikkerhetssystem etc.
I denne opplæringen skal vi se noen flere bildemanipulasjoner ved hjelp av Python OpenCV. Her vil vi lære å bruke følgende funksjon på et bilde ved hjelp av Python OpenCV:
- Bitvis operasjon og maskering
- Konvolusjon og uskarphet
- Skarphet - Å reversere bildet blir uskarpt
- Terskel (binærisering)
- Utvidelse, erosjon, åpning / lukking
- Kantgjenkjenning og bildestigninger
- Perspective & Affine Transform
- Live Sketch-applikasjon
1. Bitvis operasjon og maskering
Bitvis operasjoner hjelper deg med bildemaskering og hjelper deg med å lage noen enkle bilder.
Å lage en firkant
import cv2 import numpy som np # vi bruker bare to dimensjoner fordi dette er et gråtonebilde. Hvis vi brukte et #farget bilde, hadde vi da brukt et rektangel = np.zeros ((300,300,3), np.uint8) # Å lage et kvadratisk kvadrat = np. nuller ((300 300), np.uint8) cv2. Rektangel (kvadrat, (50,50), (250 250), 255, -1) cv2.imshow ("kvadrat", kvadrat) cv2. waitKey (0)
Å lage en ellips
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 operasjoner
#AND_ viser bare hvor de to krysser hverandre
BitwiseAND = cv2.bitwise_and (kvadrat, ellipse) cv2.imshow ("AND", BitwiseAND) cv2.waitKey (0)
#OR_ viser bare hvor enten firkant eller ellips er
BitwiseOR = cv2.bitwise_or (kvadrat, ellipse) cv2.imshow ("ELLER", BitwiseOR) cv2.waitKey (0)
#XOR_ viser bare hvor den ene eksisterer av seg selv
BitwiseXOR = cv2.bitwise_xor (kvadrat, ellipse) cv2.imshow ("XOR", BitwiseXOR) cv2.waitKey (0)
#NOT_ viser alt som ikke er en del av ellipsen og IKKE-operasjonen kan bare brukes på en enkelt figur
BitwiseNOT_elp = cv2.bitwise_not (ellipse) cv2.imshow ("NOT_ellipse", BitwiseNOT_elp) cv2.waitKey (0) cv2.destroyAllWindows ()
2. Konvolusjon og uskarphet
En konvolusjon er en matematisk operasjon utført på to funksjoner som produserer en tredje funksjon som vanligvis er en modifisert versjon av originalfunksjonen.
Utdata bilde = bilde Funksjon Kjernestørrelse
I datasyn bruker vi kjernene til å spesifisere størrelsen som vi kjører vår manipulasjonsfunksjon over bildet vårt.
Uklarhet er en operasjon der vi gjennomsnittlig piksler i en region (Kernel)
OpenCV slører et bilde ved å bruke kjerner, en kjerne forteller deg hvordan du endrer verdien på en gitt piksel ved å kombinere den med forskjellige mengder nabopiksler kjernen blir brukt på hver piksel i bildet en etter en for å produsere det endelige bildet.
Enkelt sagt, en bildekonvolusjon er ganske enkelt en elementvis multiplikasjon av to matriser etterfulgt av en sum.
Vi kan ganske enkelt forstå det ved følgende eksempel.
Ovennevnte er en 3X3-kjerne.
Vi multipliserer med 1/25 for å normalisere, dvs. summe til 1 vi hadde økt intensiteten eller redusert intensiteten som i tilfelle lysere eller mørkere bilder.
La oss teste en opencv uskarphet metode filter2D, gitt av funksjonen cv2.filter2D (bilde, -1, kjerne)
importer cv2 import numpy som np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#creating a 3x3 kernel matrix
kernel_3x3 = np.ones ((3,3), np.float32) / 9
# vi bruker cv2.filter2D for å samle kjernen med et bilde
uskarpt = cv2.filter2D (bilde, -1, kernel_3x3) cv2.imshow ('3x3_blurring', uskarpt) cv2.waitKey (0)
#creating a 7x7 kernel matrix
kernel_7x7 = np.ones ((7,7), np.float32) / 49
# vi bruker cv2.filter2D for å samle kjernen med et bilde
uskarpt = cv2.filter2D (bilde, -1, kernel_7x7) cv2.imshow ('7x7_blurring', uskarpt) cv2.waitKey (0) cv2.destroyAllWindows ()
Det finnes andre typer uskarphetsmetoder også:
cv2.blur - Gjennomsnittlig verdi over et spesifisert vindu.
cv2.GaussianBlur - Ligner men bruker et Gaussisk vindu (mer vekt på punkter rundt sentrum).
cv2.medianBlur– Bruker medianen av alle elementene i vinduet.
cv2.bilateralFilter– Uklart mens kantene holdes skarpe, men det bevarer kantene og linjedetaljene.
Vi ser en etter en nedenfor, først viser originalbildet med koden nedenfor:
importer cv2 import numpy som np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
cv2.blur:
I denne metoden gjøres gjennomsnittsmåling ved å samle bildet med et normalisert boksfilter, dette tar plass under ruten og erstatter det sentrale elementet. Her må boksstørrelsen være merkelig og positiv .
# cv2.blur uskarphet = cv2.blur (bilde, (3,3)) cv2.imshow ('Gjennomsnitt', uskarphet) cv2.waitKey (0)
cv2.GaussianBlur:
# cv2.GaussianBlur # istedenfor boksfilter, la oss prøve Gaussian kernel Gaussian = cv2.GaussianBlur (image, (7,7), 0) cv2.imshow ('Gaussian blurring', Gaussian) cv2.waitKey (0)
cv2.medianBlur:
Det tar medianen av alle piksler under kjerneområdet, og sentralt element erstattes med denne medianverdien.
# cv2.medianBlur # tar medianen av alle piksler under kjerneområdet og det sentrale elementet # erstattes med denne medianverdien. median = cv2.medianBlur (image, 5) cv2.imshow ('medianuskarpheter', median) cv2.waitKey (0)
cv2.bilateralFilter:
Bilateral er veldig effektiv når det gjelder fjerning av støy, samtidig som kantene holdes skarpe
# cv2.bilateralFilter #Bilateral er veldig effektiv når det gjelder fjerning av støy, samtidig som kantene holdes skarpe bilaterale = cv2.bilateralFilter (bilde, 9,75,75) cv2.imshow ('bilateral uskarphet', bilateral) cv2.waitKey (0) cv2. destroyAllWindows ()
Image De-noising-non Local betyr benevnelse
importer cv2 import numpy som np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#parameter etter Ingen er filterstyrken 'h' (5-10 er et godt område) # neste er h for fargekomponenter, sett med samme verdi som h igjen
dst = cv2.fastNlMeansDenoisingColored (image, None, 6,6,7,21) cv2.imshow ('Fast means denois', dst) cv2.waitKey (0) cv2.destroyAllWindows ()
Det er fire variasjoner av ikke-lokale midler
cv2.fastNlMeansDenoising () - for enkelt gråskala bilde
cv2.fastNlMeansDenoisingColored () - Ettfargebilde
cv2.fastNlmeansDenoisingMulti () - for gråtoner i bildesekvensen
cv2.fastNlmeansDenoisingcoloredMulti () - for farget bildesekvens
3. Skarphet - Å reversere bildet blir uskarpt
Sliping er det motsatte av uskarphet, det styrker eller understreker på kantene i bildet.
Kernel =,,
Vår kjernematrise oppsummerer opptil en, så det er ikke nødvendig å normalisere (dvs. multiplisere med en faktor til samme lysstyrke som i originalen). Hvis kjernen ikke normaliseres til 1, vil bildet være lysere eller mørkere.
importer cv2 import numpy som np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
kernel_sharpening = np.array (,
])
# å bruke skjerpekjerne for å legge inn bilde
skjerpet = cv2.filter2D (bilde, -1, kernel_sharpening) cv2.imshow ('skjerpet bilde', skjerpet) cv2.waitKey (0) cv2.destroyAllWindows ()
4. Threshoding (binærisering)
Terskel er å konvertere et bilde til binær form. I opencv er det en egen funksjon for terskelverdier definert som
Cv2.threshold (bilde, terskelverdi, maks verdi, terskeltype)
Det er følgende terskeltyper:
- cv2.THRESH_BINARY - vanligst
- cv2. THRESH_BINARY_INV - vanligst
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2. THRESH_TOZERO_INV
MERK: bildet er nødvendig for å konverteres til gråtoner før terskelverdien
import cv2 import numpy as np #load image as grayscale image = cv2.imread ('gradient.jpg', 0) cv2.imshow ('original', image) cv2.waitKey (0)
#verdi under 127 går til 0 (svart), og over 127 går til 255 (hvit)
_, thresh1 = cv2.threshold (bilde, 127,255, cv2.THRESH_BINARY) cv2.imshow ('1 terskel', thresh1) cv2.waitKey (0)
#verdi under 127 går til 255 og verdier over 127 går til 0 (omvendt av ovenfor)
_, thresh2 = cv2.threshold (bilde, 127,255, cv2.THRESH_BINARY_INV) cv2.imshow ('2 terskel', thresh2) cv2.waitKey (0)
#verdi over 127 er avkortet (holdt) ved 127, 255-argumentet er ubrukt.
_, thresh3 = cv2.threshold (image, 127,255, cv2.THRESH_TRUNC) cv2.imshow ('3 thresh trunc ', thresh3) cv2.waitKey (0)
#verdier under 127 går til 0, over 127 er uendret
_, thresh4 = cv2.threshold (bilde, 127,255, cv2.THRESH_TOZERO) cv2.imshow ('4 terskel', thresh4) cv2.waitKey (0)
#Revesrse over, under 127 er uendret, over 127 går til null
_, thresh5 = cv2.threshold (bilde, 127,255, cv2.THRESH_TOZERO_INV) cv2.imshow ('5 terskel', thresh5) cv2.waitKey (0) cv2.destroyAllWindows ()
5. Utvidelse, erosjon, åpning / lukking
Dette er operasjonene innen matematisk morfologi
Utvidelse - det legger til piksler til grensene for objektet i et bilde.
Erosjon - Fjerner piksler ved grensene til objektet i et bilde.
Åpning - Erosjon etterfulgt av utvidelse.
Avslutning - utvidelse etterfulgt av erosjon.
Åpning er veldig nyttig for å benekte bildene, da det først tynner bildet ved erosjon (fjerner støyen) og utvider det.
Forvirring med utvidelse og erosjon
Noen ganger er det forvirring mellom utvidelse og erosjon, vanligvis i bilder med hvit bakgrunn, ettersom opencv anser hvit bakgrunn som bilde for å være utvidet eller erodert i stedet for originalbilde, så i dette tilfellet fungerer erosjon som utvidelse og omvendt, som vist i bildeeksempel Vist under.
Husk at utvidelse legger til piksler til grensene til objekter i et bilde mens Erosion fjerner piksler ved grensene til objekter i et bilde
importer cv2 import numpy som np image = cv2.imread ('imagecv.png', 0) cv2.imshow ('original', image) cv2.waitKey (0)
#Erosion
# la oss definere kjernestørrelsen
kjerne = np.ones ((5,5), np.uint8)
# nå eroderer vi bildet, her er iterasjon ikke noen ganger du vil erodere bildet
erosjon = cv2.erode (bilde, kjerne, iterasjoner = 1) cv2.imshow ('Erosjon', erosjon) cv2.waitKey (0)
# utvidelse
utvidelse = cv2.dilate (bilde, kjerne, iterasjoner = 1) cv2.imshow ('utvidelse', utvidelse) cv2.waitKey (0)
#åpning, bra for å fjerne støyen
opening = cv2.morphologyEx (image, cv2.MORPH_OPEN, kernel) cv2.imshow ('opening', opening) cv2.waitKey (0)
#closing, bra for å fjerne støy
lukking = cv2.morphologyEx (bilde, cv2.MORPH_CLOSE, kjerne) cv2.imshow ('lukking', lukking) cv2.waitKey (0) cv2.destroyAllWindows ()
6. Kanten deteksjon og bilde gradienter
Kantdeteksjon er veldig viktig område i datasynet, spesielt når du arbeider med konturer.
Kanter kan defineres som bildegrenser, faktisk er de kanter som definerer objekt i bilder, de bevarer mye informasjon om bildet.
Formelt kanter kan defineres som plutselige endringer (diskontinuiteter) i et bilde, og de kan kode like mye informasjon som piksler.
Ovenstående bilde viser hvordan datasyn identifiserer og gjenkjenner bildet.
Kantgjenkjenningsalgoritmer: - Det er tre hovedtyper av kantgjenkjenningsalgoritmer
- Sobel - for å legge vekt på vertikale eller horisontale bilder.
- Laplacian - optimal på grunn av lav feilrate, veldefinerte kanter og nøyaktig deteksjon.
- Canny Edge deteksjonsalgoritme (utgitt av john F. Canny i 1986)
1. Påfører Gaussisk uskarphet
2. Finner intensitetsgradient av bildet
3. bruker ikke-maksimal undertrykkelse (dvs. fjerner piksler som ikke er kanter).
4. Hysterese gjelder terskel (dvs. hvis piksel er innenfor øvre og nedre terskel, blir det sett på som en kant)
importer cv2 import numpy som np image = cv2.imread ('input.jpg', 0) høyde, bredde = image.shape
#sobel
#trekk ut sobelkantene
sobel_x = cv2.Sobel (bilde, cv2.CV_64F, 0,1, ksize = 5) sobel_y = cv2.Sobel (bilde, cv2.CV_64F, 1,0, ksize = 5) cv2.imshow ('original', bilde) 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 (bilde, cv2.CV_64F) cv2.imshow ('Laplacian', laplacian) cv2.waitKey (0)
#canny edge detection algoritme bruker gradientverdier som terskler
# i canny trenger vi å oppgi to verdier: terskel1 og terskel2.
#any gradient større enn terskel 2 anses å være en kant.
#any gradient større enn terskel 1 anses ikke å være en kant.
#values i mellom terskel og en terskel 2 er enten som kant eller ikke-kant
#on hvordan deres intensitet er forbundet, i dette tilfelle en hvilken som helst verdi under 60 blir ansett
#non kanter wheareas en verdi over 120 anses som kanter.
canny = cv2.Canny (bilde, 60,120) cv2.imshow ('canny', canny) cv2.waitKey (0) cv2.destroyAllWindows ()
14. Perspektiv & Affine Transform
La oss ta et skritt tilbake og se på affine og ikke-affine transformasjoner, det opprinnelige bildet vist nedenfor er tydeligvis et ikke-affint bilde, ettersom kantene kommer til å møtes på et tidspunkt, men vi kan rette det opp ved å vri og ta perspektiv forvandle.
For denne perspektivtransformasjonen trenger vi de fire koordinatene til det opprinnelige bildet og deretter de fire punktene i utgangsbildet, de er betegnet med poeng_A og poeng_B. For det første ved hjelp av disse punktene beregner vi en transformasjonsmatrise, M ved hjelp av getPerspectiveTransform-funksjonen.
Og så blir denne matrisen gitt til warpPerspective- funksjonen for å generere den endelige produksjonen.
La oss nå prøve perspektivtransformasjonen.
import cv2 import numpy as np import matplotlib.pyplot as plt image = cv2.imread ('paper.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#koordinat av 4 hjørner av originalbildet
poeng_A = np.float32 (,,,])
#koordinater med 4 hjørner av ønsket utskrift
# vi bruker forholdet A4-papir 1: 1,41
poeng_B = np.float32 (,,,])
# bruk de to settene med to punkter for å beregne den antatte transformasjonsmatrisen, M
M = cv2.getPerspectiveTransform (points_A, points_B) warped = cv2.warpPerspective (image, M, (420,594)) cv2.imshow ('warpprespective', warped) cv2.waitKey (0) cv2.destroyAllWindows ()
Affinetransformasjon er lettere enn ikke-affinetransformasjonen, da vi bare trenger tre poeng for å få transformasjonen. Hele prosessen går den samme, men i stedet for perspektivtransformasjon har vi nå affinetransformasjon, og vi definerer også cols og rader i warpAffine fra formfunksjonen i stedet for å manuelt legge den inn.
importer cv2 import numpy som np importer matplotlib.pyplot som plt image = cv2.imread ('box.jpg') rader, cols = image.shape cv2.imshow ('original', image) cv2.waitKey (0)
#koordinat av 3 hjørner av originalbildet
poeng_A = np.float32 (,,])
#koordinater på 3 hjørner av ønsket utskrift
# vi bruker forholdet A4-papir 1: 1,41
poeng_B = np.float32 (,,])
#Bruk de to settene med to punkter for å beregne Affine
#transformation-matrisen, M
M = cv2.getAffineTransform (poeng_A, poeng_B) vridd = cv2.warpAffine (bilde, M, (cols, rader)) cv2.imshow ('warpaffine', vridd) cv2.waitKey (0) cv2.destroyAllWindows ()
8. Live Sketch-applikasjon
Først av alt, gratulere deg selv med at du har gjort opp til dette miniprosjektet etter å ha lest alle bildemanipuleringsfunksjonene ovenfor. Så i dette miniprosjektet til Python OpenCV skal vi lære noen nye konsepter for sløyfer og funksjoner. Hvis du er kjent med programmering, må du ha en bredere ide om hva funksjonen og sløyfene er. Imidlertid forblir i python det grunnleggende konseptet med sløyfer og funksjoner det samme, men metoden for å definere dem endres litt.
Så ved starten av dette programmet kan vi se en bestemt gruppe utsagn overskriften under " def sketch (image): " dette er en formell definisjon av en funksjon en gruppe utsagn arbeider sammen for en bestemt utgang.
Så denne skissen er en funksjon, i pytonfunksjon er definert av “def” og ender med et “:” -merke. Også utsagnene som kreves for å være inne i funksjonen, eller du kan si hvilke som kreves for at funksjonen skal fungere skikkelig, blir sidelinjert automatisk av funksjonen. Så for å komme ut av funksjonene, måtte uttalelsene være helt venstrejustert. For ytterligere referanser kan du henvise til google om hvordan funksjonene er definert i python.
Så i denne skissefunksjonen har vi introdusert flere lag med bildebehandling som kombineres for å gi et resultat. For det første konverteres bildet til gråtoner, slik at opencv kan behandle det enkelt, og deretter påføres en Gaussisk uskarphet på gråskalabildet for å redusere støyen. Deretter blir kantene ekstrahert ved hjelp av kaninens kantdeteksjonsalgoritme, og deretter brukes en binær invers på det kantdefinerte bildet, her kan binær invers også gjøres av bitwise_NOT, men vi hadde bevisst valgt denne terskelen binær invers, da den gir frihet å sette parametrene til vi får et klart bilde.
Også for å merke seg at funksjonen tar argumentbildet og returnerer de to argumentene ret og maske. Mens ret er boolsk forteller at funksjonen kjøres vellykket eller ikke, og masken er den endelige utgangen av funksjonen, dvs. det behandlede bildet.
Da den andre konseptet er å operere webkamera i OpenCV som er gjort av cv2.VideoCapture (0) funksjon, som lagrer bildet i en gjenstand hette som hetten kan leses med cap.read () funksjon, også her å merke seg at hetten. read () er inne i den uendelige mens sløyfen da den kontinuerlig måtte ta bilder, for å gi den en følelse av en live video, der bildefrekvensen til videoen ville være bildefrekvensen til webkameraet ditt, som stort sett er mellom 24 og 60 fps.
cap.read () returnerer ret og ramme, der ret er boolsk, noe som indikerer at funksjonen ble kjørt eller ikke, og rammen inneholder bildet tatt av webkameraet.
Nedenfor er den komplette Python OpenCV-koden for å kjøre Live Sketch
import cv2 import numpy as np #sketch generating function def sketch (image): #convert image to grayscale img_gray = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) #cleansing up image using Gaussian blur img_gray_blur = cv2.GaussianBlur (img_gray_blur = cv2.GaussianBlur 5,5), 0) #extract kanter canny_edges = cv2.Canny (img_gray_blur, 1070) #do en invert binarize bilde RET mask = cv2.threshold (canny_edges, 70,255, cv2.THRESH_BINARY_INV) retur maske #initialize webkamera, hetten er gjenstanden ved video capture #it inneholder en boolsk verdi som angir om det var vellykket (ret) #it inneholder også bildene samlet fra webkameraet (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 # slipp kamera og lukk vindu, husk å slippe webkameraet ved hjelp av cap.release () cap.release () cv2.destroyAllWindows ()
Så dette er slutten på del 2 av bildemanipulasjoner i Python-OpenCV. For å få god undervisning i datasyn og OpenCV, gå gjennom tidligere artikler (Komme i gang med Python OpenCV og Image Manipulations i Python OpenCV (del 1), og du vil kunne gjøre noe kult med Computer Vision.