OpenCV Edge Detection i Python med cv2.Canny() PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

OpenCV Edge Detection i Python med cv2.Canny()

Beskrivning

Kantdetektering är något vi gör naturligt, men det är inte lika lätt när det gäller att definiera regler för datorer. Även om olika metoder har utarbetats, utvecklades den härskande metoden av John F. Canny 1986. och heter det passande namnet Canny-metoden.

Den är snabb, ganska robust och fungerar nästan bäst den skulle kunna fungera för den typ av teknik det är. I slutet av guiden vet du hur du utför kantdetektering i realtid på videor och producerar något i stil med:

Canny Edge Detection

Vad är Canny-metoden? Den består av fyra distinkta operationer:

  • Gaussisk utjämning
  • Beräkningsgradienter
  • Icke-Max dämpning
  • Hysteres Tröskel

Gaussisk utjämning används som det första steget för att "stryka ut" ingångsbilden och dämpa bruset, vilket gör den slutliga utmatningen mycket renare.

Bildgradienter har använts i tidigare applikationer för kantdetektering. Framför allt är Sobel- och Scharr-filter beroende av bildgradienter. Sobel-filtret kokar ner till två kärnor (Gx och Gy), var Gx upptäcker horisontella förändringar, medan Gy upptäcker vertikala förändringar:

G

x

=

[

-
1

0

+
1

-
2

0

+
2

-
1

0

+
1

]

G

y

=

[

-
1

-
2

-
1

0

0

0

+
1

+
2

+
1

]

När du drar dem över en bild kommer de att "plocka upp" (framhäva) var och en av linjerna i sin respektive orientering. Scharr-kärnor fungerar på samma sätt, med olika värden:

G

x

=

[

+
3

0

-
3

+
10

0

-
10

+
3

0

-
3

]

G

y

=

[

+
3

+
10

+
3

0

0

0

-
3

-
10

-
3

]

Dessa filter kommer, när de väl har rullats över bilden, att producera funktionskartor:

OpenCV Edge Detection i Python med cv2.Canny() PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Bildkredit: Davidwkennedy

För dessa funktionskartor kan du beräkna gradientstorlek och gradientorientering – dvs hur intensiv förändringen är (hur sannolikt är det att något är en kant) och åt vilket håll förändringen pekar. Eftersom Gy betecknar den vertikala förändringen (Y-gradient), och Gx betecknar den horisontella förändringen (X-gradient) – kan du beräkna storleken genom att helt enkelt tillämpa Pythagoras sats, för att få hypotenusen till triangeln som bildas av "vänster" och "rätt" vägbeskrivning:

$$
{G} ={sqrt {{{G} _{x}}^{2}+{{G} _{y}}^{2}}}
$$

Med hjälp av magnituden och orienteringen kan du skapa en bild med dess kanter markerad:

OpenCV Edge Detection i Python med cv2.Canny() PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Bildkredit: Davidwkennedy

Men – du kan se hur mycket ljud som också fångades från tegelstenarnas tecture! Bildgradienter är mycket känsliga för brus. Det är därför som Sobel- och Scharr-filter användes som komponent, men inte det enda tillvägagångssättet i Cannys metod. Gaussisk utjämning hjälper även här.

Icke-Max dämpning

Ett märkbart problem med Sobel-filtret är att kanterna inte är riktigt tydliga. Det är inte som att någon tog en penna och ritade en linje för att skapa lineart av bilden. Kanterna är vanligtvis inte så tydliga i bilder, eftersom ljuset diffunderar gradvis. Men vi kan hitta den gemensamma linjen i kanterna och trycka ner resten av pixlarna runt den, vilket ger en ren, tunn separationslinje istället. Detta är känt som Non-Max dämpning! De icke-maxpixlar (de som är mindre än den vi jämför dem med i ett litet lokalt fält, till exempel en 3×3 kärna) dämpas. Konceptet är tillämpligt på fler uppgifter än detta, men låt oss binda det till detta sammanhang för nu.

Hysteres Tröskel

Många icke-kanter kan och kommer sannolikt att utvärderas som kanter, på grund av ljusförhållanden, materialen i bilden etc. På grund av de olika orsakerna till dessa felberäkningar är det svårt att göra en automatiserad utvärdering av vad en kant verkligen är och inte är. 't. Du kan tröskelgradienter och bara inkludera de starkare, förutsatt att "riktiga" kanter är mer intensiva än "falska" kanter.

Tröskelvärde fungerar på ungefär samma sätt som vanligt – om gradienten är under en lägre tröskel, ta bort den (nollställ den), och om den är över en given övre tröskel, behåll den. Allt mellan den nedre och övre gränsen är i "gråzonen". Om någon kant mellan trösklarna är ansluten till en definitiv kant (de över tröskeln) – de betraktas också som kanter. Om de inte är anslutna är de sannolikt arficater av en felberäknad kant.

Det är hysteres tröskel! I själva verket hjälper det till att rensa upp det slutliga resultatet och ta bort falska kanter, beroende på vad du klassificerar som en falsk kant. För att hitta bra tröskelvärden kommer du i allmänhet att experimentera med olika nedre och övre gränser för tröskelvärdena, eller använda en automatiserad metod som Otsus metod eller Triangelmetoden.

Låt oss ladda in en bild och gråskala den (Canny, precis som Sobel/Scharr kräver att bilder gråskalas):

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('finger.jpg', cv2.IMREAD_GRAYSCALE)
img_blur = cv2.GaussianBlur(img, (3,3), 0)

plt.imshow(img_blur, cmap='gray')

OpenCV Edge Detection i Python med cv2.Canny() PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Närbildsbilden av ett finger kommer att fungera som en bra testplats för kantdetektering – det är inte lätt att urskilja ett fingeravtryck från bilden, men vi kan uppskatta ett.

Kantdetektering på bilder med cv2.Canny()

Cannys algoritm kan tillämpas med OpenCV:s Canny() metod:

cv2.Canny(input_img, lower_bound, upper_bound)

Kolla in vår praktiska, praktiska guide för att lära dig Git, med bästa praxis, branschaccepterade standarder och medföljande fuskblad. Sluta googla Git-kommandon och faktiskt lära Det!

Att hitta rätt balans mellan den nedre och övre gränsen kan vara knepigt. Om båda är låga – har du få kanter. Om den nedre gränsen är låg och den övre är hög – kommer du att ha brus. Om båda är höga och nära varandra – har du få kanter. Rätt plats har precis tillräckligt med gap mellan gränserna och har dem på rätt skala. Experimentera!

Ingångsbilden blir suddig med Canny-metoden, men ofta kan du dra nytta av att göra den suddig innan den går in också. Metoden applicerar en 5×5 Gaussisk oskärpa på ingången innan du går igenom resten av operationerna, men även med denna oskärpa kan visst brus fortfarande sippra igenom, så vi har suddat ut bilden innan den matas in i algoritmen:


edge = cv2.Canny(img_blur, 20, 30)

fig, ax = plt.subplots(1, 2, figsize=(18, 6), dpi=150)
ax[0].imshow(img, cmap='gray')
ax[1].imshow(edge, cmap='gray')

Detta resulterar i:

OpenCV Edge Detection i Python med cv2.Canny() PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Värdena för 20 och 30 här är inte godtyckliga – jag har testat metoden på olika parametrar och valde en uppsättning som verkade ge ett anständigt resultat. Kan vi försöka automatisera detta?

Automatiserad tröskelvärde för cv2.Canny()?

Kan du hitta en optimal uppsättning tröskelvärden? Ja, men det fungerar inte alltid. Du kan göra din egen beräkning för ett bra värde och sedan justera intervallet med a sigma runt den tröskeln:

lower_bound = (1-sigma)*threshold
upper_bound = (1+sigma)*threshold

När sigma, är att säga, 0.33 – gränserna blir 0.66*threshold och 1.33*threshold, vilket tillåter ett ~1/3-intervall runt den. Men att hitta threshold är det som är svårare. OpenCV förser oss med Otsus metod (fungerar utmärkt för bimodala bilder) och Triangelmetoden. Låt oss prova båda, samt ta en enkel median av pixelvärdena som det tredje alternativet:

otsu_thresh, _ = cv2.threshold(img_blur, 0, 255, cv2.THRESH_OTSU)
triangle_thresh, _ = cv2.threshold(img_blur, 0, 255, cv2.THRESH_TRIANGLE)
manual_thresh = np.median(img_blur)

def get_range(threshold, sigma=0.33):
    return (1-sigma) * threshold, (1+sigma) * threshold

otsu_thresh = get_range(otsu_thresh)
triangle_thresh = get_range(triangle_thresh)
manual_thresh = get_range(manual_thresh)

print(f"Otsu's Threshold: {otsu_thresh} nTriangle Threshold: {triangle_thresh} nManual Threshold: {manual_thresh}")

Detta resulterar i:

Otsu's Threshold: (70.35, 139.65) 
Triangle Threshold: (17.419999999999998, 34.58) 
Manual Threshold: (105.18999999999998, 208.81)

Dessa är ganska olika! Från de värden vi har sett tidigare kan vi förutse att Triangelmetoden fungerar bäst här. Den manuella tröskeln är inte särskilt informerad, eftersom den bara tar medianpixelvärdet och slutar med en hög baströskel som multipliceras ytterligare till ett brett intervall för denna bild. Otsus metod lider mindre av detta, men lider ändå.

Om vi ​​kör Canny() metod med dessa tröskelintervall:

edge_otsu = cv2.Canny(img_blur, *otsu_thresh)
edge_triangle = cv2.Canny(img_blur, *triangle_thresh)
edge_manual = cv2.Canny(img_blur, *manual_thresh)

fig, ax = plt.subplots(1, 3, figsize=(18, 6), dpi=150)
ax[0].imshow(edge_otsu, cmap='gray')
ax[1].imshow(edge_triangle, cmap='gray')
ax[2].imshow(edge_manual, cmap='gray')

Notera: Funktionen förväntar sig flera argument, och våra trösklar är en enda tupel. Vi kan destrukturera tuple in i flera argument genom att prefixet det med *. Detta fungerar också på listor och uppsättningar, och är ett utmärkt sätt att tillhandahålla flera argument efter att ha erhållit dem med programmatiska medel.

Detta resulterar i:

OpenCV Edge Detection i Python med cv2.Canny() PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Triangelmetoden fungerade ganska bra här! Detta är ingen garanti för att det kommer att fungera bra i andra fall också.

Kantdetektering i realtid på videor med cv2.Canny()

Slutligen, låt oss tillämpa Canny edge-detektering på en video i realtid! Vi kommer att visa videon som bearbetas (varje bildruta när den är klar) med hjälp av cv2.imshow() som visar ett fönster med den ram vi vill visa. Men vi kommer också att spara videon i en MP4-fil som senare kan inspekteras och delas.

För att ladda en video med OpenCV använder vi VideoCapture() metod. Om vi ​​passerar in 0 – det kommer att spela in från den aktuella webbkameran, så att du kan köra koden på din webbkamera också! Om du skickar in ett filnamn, kommer det att ladda filen:

def edge_detection_video(filename):
    cap = cv2.VideoCapture(filename)
    
    fourcc = cv2.VideoWriter_fourcc(*'MP4V')
    out = cv2.VideoWriter('output.mp4', fourcc, 30.0, (int(cap.get(3)), int(cap.get(4))), isColor=False)
    
    while cap.isOpened():
        (ret, frame) = cap.read()
        if ret == True:
            frame = cv2.GaussianBlur(frame, (3, 3), 0)
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            edge = cv2.Canny(frame, 50, 100)
            out.write(edge)
            cv2.imshow('Edge detection', edge)
        else:
            break

        if cv2.waitKey(10) & 0xFF == ord('q'):
            break

    cap.release()
    out.release()
    cv2.destroyAllWindows()

edge_detection_video('secret_video.mp4')

Smakämnen VideoWriter accepterar flera parametrar – utdatafilnamnet, FourCC (fyra codec-koder, anger den codec som används för att koda videon), framerate och upplösningen som en tupel. För att inte gissa eller ändra storlek på videon – vi har använt bredden och höjden på originalvideon, erhållen genom VideoCapture instans som innehåller data om själva videon, såsom bredd, höjd, totalt antal bildrutor, etc.

Medan inspelningen är öppen försöker vi läsa nästa bildruta med cap.read(), som returnerar en resultatkod och nästa bildruta. Resultatkoden är True or False, som betecknar närvaron av nästa ram eller brist på denna. Först när det finns en ram kommer vi att försöka bearbeta den ytterligare, annars bryter vi slingan. För varje giltig ram kör vi den genom en gaussisk oskärpa, konverterar den till gråskala, kör cv2.Canny() på den och skriv den med hjälp av VideoWriter till disken och visa med hjälp av cv2.imshow() för en livevisning.

Slutligen släpper vi infångnings- och videoskrivaren, eftersom de båda arbetar med filer på disken och förstör alla befintliga fönster.

När du kör metoden med en secret_video.mp4 input – du kommer att se ett fönster som poppar upp och när det är klart, en fil i din arbetskatalog:

OpenCV Edge Detection i Python med cv2.Canny() PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Slutsats

I den här guiden har vi tagit en titt på hur Canny-kantdetektering fungerar, och dess beståndsdelar – gaussisk utjämning, Sobel-filter och bildgradienter, Non-Max-undertryckning och hysteres-tröskel. Slutligen har vi utforskat metoder för automatisk sökning av tröskelintervall för Canny edge-detektion med cv2.Canny(), och använde tekniken på en video, vilket gav kantdetektering i realtid och sparade resultaten i en videofil.

Going Further – Praktisk djupinlärning för datorseende

Din nyfikna natur gör att du vill gå längre? Vi rekommenderar att du kollar in vår Kurs: "Praktisk djupinlärning för datorseende med Python".

OpenCV Edge Detection i Python med cv2.Canny() PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Ännu en kurs i datorseende?

Vi kommer inte att göra klassificering av MNIST-siffror eller MNIST-mode. De tjänade sin del för länge sedan. Alltför många inlärningsresurser fokuserar på grundläggande datamängder och grundläggande arkitekturer innan de låter avancerade blackbox-arkitekturer bära bördan av prestanda.

Vi vill fokusera på avmystifiering, praktiskhet, förståelse, intuition och riktiga projekt. Vill lära sig hur du kan göra skillnad? Vi tar dig med på en tur från hur våra hjärnor bearbetar bilder till att skriva en klassificerare för djupinlärning för bröstcancer i forskningsklass till nätverk för djupinlärning som "hallucinerar", lär dig principer och teorier genom praktiskt arbete, och utrustar dig med kunskap och verktyg för att bli expert på att tillämpa djupinlärning för att lösa datorseende.

Vad är inuti?

  • De första principerna för syn och hur datorer kan läras att "se"
  • Olika uppgifter och tillämpningar av datorseende
  • Branschens verktyg som gör ditt arbete enklare
  • Hitta, skapa och använda datauppsättningar för datorseende
  • Teorin och tillämpningen av Convolutional Neural Networks
  • Hantera domänskifte, samtidig förekomst och andra fördomar i datamängder
  • Överför Lärande och utnyttja andras träningstid och beräkningsresurser till din fördel
  • Bygga och träna en toppmodern klassificerare för bröstcancer
  • Hur man applicerar en hälsosam dos av skepsis på mainstream idéer och förstår implikationerna av allmänt använda tekniker
  • Visualisera ett ConvNets "konceptutrymme" med t-SNE och PCA
  • Fallstudier av hur företag använder datorseendetekniker för att uppnå bättre resultat
  • Korrekt modellutvärdering, latent rumsvisualisering och identifiering av modellens uppmärksamhet
  • Utföra domänforskning, bearbeta dina egna datamängder och upprätta modelltester
  • Banbrytande arkitekturer, utvecklingen av idéer, vad som gör dem unika och hur man implementerar dem
  • KerasCV – ett WIP-bibliotek för att skapa toppmoderna pipelines och modeller
  • Hur man analyserar och läser uppsatser och implementerar dem själv
  • Välja modeller beroende på din applikation
  • Skapa en komplett maskininlärningspipeline
  • Landskap och intuition på objektdetektering med snabbare R-CNN, RetinaNets, SSD och YOLO
  • Instans och semantisk segmentering
  • Objektigenkänning i realtid med YOLOv5
  • Träning av YOLOv5-objektdetektorer
  • Arbeta med transformatorer med KerasNLP (industristarkt WIP-bibliotek)
  • Integrering av Transformers med ConvNets för att generera bildtexter
  • DeepDream
  • Deep Learning-modelloptimering för datorseende

Tidsstämpel:

Mer från Stackabuse