OpenCV Edge Detection in Python met cv2.Canny() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

OpenCV-randdetectie in Python met cv2.Cany()

Introductie

Randdetectie is iets dat we van nature doen, maar het is niet zo eenvoudig als het gaat om het definiëren van regels voor computers. Hoewel er verschillende methoden zijn bedacht, is de heersende methode in 1986 ontwikkeld door John F. Canny en wordt toepasselijk de Canny-methode genoemd.

Het is snel, redelijk robuust en werkt zo goed als het beste voor het type techniek dat het is. Aan het einde van de handleiding weet u hoe u realtime randdetectie op video's kunt uitvoeren en iets kunt produceren in de trant van:

Canny Edge-detectie

Wat is de Canny-methode? Het bestaat uit vier verschillende operaties:

  • Gauss-afvlakking
  • Verlopen berekenen
  • Niet-maximale onderdrukking
  • Hysterese Drempel

Gauss-afvlakking wordt gebruikt als de eerste stap om het invoerbeeld te "strijken" en de ruis te verzachten, waardoor de uiteindelijke uitvoer veel schoner wordt.

Afbeeldingsverlopen zijn in eerdere toepassingen voor randdetectie gebruikt. Het meest opvallende is dat Sobel- en Scharr-filters afhankelijk zijn van beeldovergangen. Het Sobel-filter komt neer op twee korrels (Gx en Gy), waar Gx detecteert horizontale veranderingen, terwijl Gy detecteert verticale veranderingen:

G

x

=

[

-
1

0

+
1

-
2

0

+
2

-
1

0

+
1

]

G

y

=

[

-
1

-
2

-
1

0

0

0

+
1

+
2

+
1

]

Wanneer je ze over een afbeelding schuift, zullen ze elk de lijnen in hun respectievelijke richting "oppakken" (benadrukken). Scharr-kernels werken op dezelfde manier, met verschillende waarden:

G

x

=

[

+
3

0

-
3

+
10

0

-
10

+
3

0

-
3

]

G

y

=

[

+
3

+
10

+
3

0

0

0

-
3

-
10

-
3

]

Deze filters, eenmaal geconverteerd over de afbeelding, zullen feature maps produceren:

OpenCV Edge Detection in Python met cv2.Canny() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Afbeelding tegoed: Davidwkennedy

Voor deze feature maps kun je de gradiëntgrootte en gradiëntoriëntatie – dwz hoe intens de verandering is (hoe waarschijnlijk is het dat iets een rand is) en in welke richting de verandering wijst. Aangezien Gy de verticale verandering (Y-gradiënt) aangeeft, en Gx de horizontale verandering (X-gradiënt) aangeeft, kun je de grootte berekenen door simpelweg de stelling van Pythagoras toe te passen, om de hypothenusa te krijgen van de driehoek gevormd door de "links" en "juiste" richtingen:

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

Met behulp van de grootte en oriëntatie kunt u een afbeelding maken waarvan de randen zijn gemarkeerd:

OpenCV Edge Detection in Python met cv2.Canny() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Afbeelding tegoed: Davidwkennedy

Maar - je kunt zien hoeveel geluid er ook werd opgevangen door de structuur van de stenen! Beeldverlopen zijn erg gevoelig voor ruis. Dit is de reden waarom Sobel- en Scharr-filters als component werden gebruikt, maar niet de enige benadering in Canny's methode. Gaussiaanse afvlakking helpt hier ook.

Niet-maximale onderdrukking

Een opvallend probleem met het Sobel-filter is dat de randen niet echt duidelijk zijn. Het is niet alsof iemand een potlood nam en een lijn tekende om een ​​lineair beeld van de afbeelding te maken. De randen zijn meestal niet zo duidelijk in afbeeldingen, omdat het licht geleidelijk diffundeert. We kunnen echter de gemeenschappelijke lijn in de randen vinden en de rest van de pixels eromheen onderdrukken, waardoor in plaats daarvan een schone, dunne scheidingslijn ontstaat. Dit staat bekend als Non-Max Supression! De niet-max pixels (die kleiner zijn dan degene waarmee we ze vergelijken in een klein lokaal veld, zoals een 3×3-kernel) worden onderdrukt. Het concept is van toepassing op meer taken dan dit, maar laten we het voor nu aan deze context binden.

Hysterese Drempel

Veel niet-randen kunnen en zullen waarschijnlijk worden beoordeeld als randen, vanwege de lichtomstandigheden, de materialen in de afbeelding, enz. Vanwege de verschillende redenen waarom deze misrekeningen optreden - is het moeilijk om een ​​geautomatiseerde evaluatie te maken van wat een rand zeker is en is 't. U kunt gradiënten drempelen en alleen de sterkere opnemen, ervan uitgaande dat "echte" randen intenser zijn dan "nep" -randen.

Drempelwaarde werkt op vrijwel dezelfde manier als gewoonlijk - als de helling onder een lagere drempel ligt, verwijder deze dan (nul uit) en als deze boven een bepaalde bovendrempel is, houdt u deze. Alles tussen de ondergrens en de bovengrens bevindt zich in de "grijze zone". Als een rand tussen de drempels is verbonden met een definitieve voorsprong (degenen boven de drempel) - ze worden ook als randen beschouwd. Als ze niet zijn aangesloten, zijn ze waarschijnlijk arficats van een verkeerd berekend voordeel.

Dat is hysteresisdrempeling! In feite helpt het de uiteindelijke uitvoer op te schonen en valse randen te verwijderen, afhankelijk van wat u classificeert als een valse rand. Om goede drempelwaarden te vinden, experimenteert u over het algemeen met verschillende onder- en bovengrenzen voor de drempels, of gebruikt u een geautomatiseerde methode zoals de methode van Otsu of de Triangle-methode.

Laten we een afbeelding laden en deze in grijstinten (Canny, net zoals Sobel/Scharr vereist dat afbeeldingen in grijstinten worden weergegeven):

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 in Python met cv2.Canny() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Het close-upbeeld van een vinger zal dienen als een goede proeftuin voor randdetectie - het is niet gemakkelijk om een ​​vingerafdruk van het beeld te onderscheiden, maar we kunnen er een benaderen.

Randdetectie op afbeeldingen met cv2.Canny()

Canny's algoritme kan worden toegepast met behulp van OpenCV's Canny() methode:

cv2.Canny(input_img, lower_bound, upper_bound)

Bekijk onze praktische, praktische gids voor het leren van Git, met best-practices, door de industrie geaccepteerde normen en bijgevoegd spiekbriefje. Stop met Googlen op Git-commando's en eigenlijk leren het!

Het vinden van de juiste balans tussen de ondergrens en de bovengrens kan lastig zijn. Als beide laag zijn, heb je weinig randen. Als de ondergrens laag is en de bovengrens hoog, dan heb je ruis. Als beide hoog en dicht bij elkaar zijn, heb je weinig randen. De juiste plek heeft net genoeg ruimte tussen de grenzen en heeft ze op de juiste schaal. Experiment!

Het invoerbeeld wordt vervaagd door de Canny-methode, maar vaak heb je er baat bij om het te vervagen vaardigheden het gaat er ook in. De methode past een 5×5 Gaussiaanse vervaging toe op de invoer voordat de rest van de bewerkingen wordt uitgevoerd, maar zelfs met deze vervaging kan er nog wat ruis doorheen sijpelen, dus we hebben het beeld wazig gemaakt voordat het in het algoritme wordt ingevoerd:


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')

Dit resulteert in:

OpenCV Edge Detection in Python met cv2.Canny() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

De waarden van 20 en 30 hier zijn niet willekeurig - ik heb de methode op verschillende parameters getest en een set gekozen die een behoorlijk resultaat leek te produceren. Kunnen we dit proberen te automatiseren?

Geautomatiseerde drempelwaarde voor cv2.Cany()?

Kun je een optimale set drempelwaarden vinden? Ja, maar het werkt niet altijd. U kunt uw eigen berekening maken voor een goede prijs en vervolgens het bereik aanpassen met a sigma rond die drempel:

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

. sigma, zeg maar, 0.33 – de grenzen zullen zijn 0.66*threshold en 1.33*threshold, waardoor een bereik van ~ 1/3 er omheen mogelijk is. Hoewel, het vinden van de threshold is wat moeilijker is. OpenCV biedt ons de methode van Otsu (werkt uitstekend voor bimodale afbeeldingen) en de Triangle-methode. Laten we ze allebei uitproberen en als derde optie een eenvoudige mediaan van de pixelwaarden nemen:

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}")

Dit resulteert in:

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

Deze zijn behoorlijk verschillend! Op basis van de waarden die we eerder hebben gezien, kunnen we anticiperen dat de Triangle-methode hier het beste werkt. De handmatige drempelwaarde is niet erg goed geïnformeerd, omdat deze alleen de mediane pixelwaarde neemt en uiteindelijk een hoge basisdrempel heeft die verder wordt vermenigvuldigd tot een breed bereik voor deze afbeelding. De methode van Otsu heeft hier minder last van, maar toch.

Als we de Canny() methode met deze drempelbereiken:

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')

Opmerking: De functie verwacht meerdere argumenten en onze drempels zijn een enkele tupel. Wij kunnen destructureren de tuple in meerdere argumenten door het vooraf te laten gaan met *. Dit werkt ook op lijsten en sets, en is een geweldige manier om meerdere argumenten aan te leveren nadat ze programmatisch zijn verkregen.

Dit resulteert in:

OpenCV Edge Detection in Python met cv2.Canny() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

De Triangle-methode werkte hier best goed! Dit is geen garantie dat het ook in andere gevallen goed zal werken.

Realtime randdetectie op video's met cv2.Cranny()

Laten we tot slot Canny-randdetectie in realtime toepassen op een video! We geven de video weer die wordt verwerkt (elk frame zoals het is gedaan) met behulp van cv2.imshow() waarin een venster wordt weergegeven met het frame dat we willen weergeven. We zullen de video echter ook opslaan in een MP4-bestand dat later kan worden geïnspecteerd en gedeeld.

Om een ​​video te laden met OpenCV, gebruiken we de VideoCapture() methode. Als we binnenkomen 0 – het neemt op vanaf de huidige webcam, dus u kunt de code ook op uw webcam uitvoeren! Als u een bestandsnaam doorgeeft, wordt het bestand geladen:

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')

De VideoWriter accepteert verschillende parameters - de naam van het uitvoerbestand, de FourCC (vier codec-codes, die de codec aangeven die wordt gebruikt om de video te coderen), de framerate en de resolutie als een tuple. Om de video niet te raden of het formaat ervan aan te passen, hebben we de breedte en hoogte van de originele video gebruikt, verkregen via de VideoCapture instantie die gegevens over de video zelf bevat, zoals de breedte, hoogte, totaal aantal frames, enz.

Terwijl de opname geopend is, proberen we het volgende frame te lezen met cap.read(), die een resultaatcode en het volgende frame retourneert. De resultaatcode is True or False, wat duidt op de aanwezigheid van het volgende frame of het ontbreken daarvan. Pas als er een frame is, proberen we het verder te verwerken, anders doorbreken we de lus. Voor elk geldig frame doorlopen we een gaussiaanse vervaging, converteren het naar grijswaarden, run cv2.Canny() erop en schrijf het met de VideoWriter naar de schijf en geef weer met cv2.imshow() voor een liveweergave.

Ten slotte geven we de opname- en videoschrijver vrij, omdat ze allebei met bestanden op de schijf werken en alle bestaande vensters vernietigen.

Wanneer u de methode uitvoert met a secret_video.mp4 input – je ziet een pop-upvenster en als het klaar is, een bestand in je werkdirectory:

OpenCV Edge Detection in Python met cv2.Canny() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Conclusie

In deze gids hebben we bekeken hoe Canny-randdetectie werkt en de samenstellende delen ervan: Gaussiaanse afvlakking, Sobel-filters en beeldovergangen, Non-Max Supression en Hysteresis Thresholding. Ten slotte hebben we methoden onderzocht voor het automatisch zoeken naar drempelbereiken voor Canny-randdetectie met: cv2.Canny(), en paste de techniek toe op een video, waardoor realtime randdetectie werd geboden en de resultaten werden opgeslagen in een videobestand.

Verder gaan - Praktisch diep leren voor computervisie

Je leergierige karakter maakt dat je verder wilt gaan? We raden aan om onze Type cursus: "Praktisch diep leren voor computervisie met Python".

OpenCV Edge Detection in Python met cv2.Canny() PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Nog een cursus computervisie?

We zullen geen classificatie van MNIST-cijfers of MNIST-mode doen. Ze hebben lang geleden hun deel gediend. Te veel leermiddelen zijn gericht op basisgegevenssets en basisarchitecturen voordat geavanceerde black-box-architecturen de last van de prestaties op zich nemen.

We willen ons concentreren op demystificatie, uitvoerbaarheid, begrip, intuïtie en echte projecten. Willen leren hoe je kan een verschil maken? We nemen je mee op een reis van de manier waarop onze hersenen afbeeldingen verwerken tot het schrijven van een onderzoeksclassificatie voor diep leren voor borstkanker tot diepgaande leernetwerken die 'hallucineren', je de principes en theorie leren door middel van praktisch werk, en je uitrusten met de knowhow en tools om een ​​expert te worden in het toepassen van deep learning om computervisie op te lossen.

Wat zit erin?

  • De eerste principes van visie en hoe computers kunnen worden geleerd om te "zien"
  • Verschillende taken en toepassingen van computervisie
  • De tools van het vak die uw werk gemakkelijker maken
  • Datasets zoeken, maken en gebruiken voor computervisie
  • De theorie en toepassing van convolutionele neurale netwerken
  • Omgaan met domeinverschuiving, gelijktijdig voorkomen en andere vooroordelen in datasets
  • Overdragen Leren en de trainingstijd en computerbronnen van anderen gebruiken in uw voordeel
  • Het bouwen en trainen van een state-of-the-art classifier voor borstkanker
  • Hoe je een gezonde dosis scepsis toepast op mainstream ideeën en de implicaties begrijpt van algemeen aanvaarde technieken?
  • De "conceptruimte" van een ConvNet visualiseren met t-SNE en PCA
  • Casestudy's van hoe bedrijven computervisietechnieken gebruiken om betere resultaten te behalen
  • Correcte modelevaluatie, visualisatie van de latente ruimte en het identificeren van de aandacht van het model
  • Domeinonderzoek doen, eigen datasets verwerken en modeltesten opzetten
  • Geavanceerde architecturen, de voortgang van ideeën, wat ze uniek maakt en hoe ze te implementeren
  • KerasCV – een WIP-bibliotheek voor het maken van ultramoderne pijplijnen en modellen
  • Hoe papers te ontleden en te lezen en ze zelf te implementeren?
  • Modellen selecteren afhankelijk van uw toepassing
  • Een end-to-end machine learning-pijplijn maken
  • Landschap en intuïtie bij objectdetectie met snellere R-CNN's, RetinaNets, SSD's en YOLO
  • Instantie en semantische segmentatie
  • Realtime objectherkenning met YOLOv5
  • YOLOv5-objectdetectoren trainen
  • Werken met Transformers met KerasNLP (industriële WIP-bibliotheek)
  • Transformers integreren met ConvNets om bijschriften van afbeeldingen te genereren
  • DeepDream
  • Optimalisatie van Deep Learning-modellen voor computervisie

Tijdstempel:

Meer van Stapelmisbruik