Détection de bords OpenCV en Python avec cv2.Canny() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Détection des bords OpenCV en Python avec cv2.Canny()

Introduction

La détection des contours est quelque chose que nous faisons naturellement, mais ce n'est pas aussi facile lorsqu'il s'agit de définir des règles pour les ordinateurs. Alors que diverses méthodes ont été conçues, la méthode régnante a été développée par John F. Canny en 1986., et porte bien son nom de méthode Canny.

C'est rapide, assez robuste et fonctionne à peu près du mieux qu'il pourrait fonctionner pour le type de technique dont il s'agit. À la fin du guide, vous saurez comment effectuer une détection de bord en temps réel sur des vidéos et produire quelque chose comme :

Détection de Canny Edge

Qu'est-ce que la méthode Canny ? Il se compose de quatre opérations distinctes :

  • Lissage gaussien
  • Calcul des gradients
  • Suppression non maximale
  • Seuil d'hystérésis

Lissage gaussien est utilisé comme première étape pour "lisser" l'image d'entrée et adoucir le bruit, rendant la sortie finale beaucoup plus propre.

Dégradés d'images ont été utilisés dans des applications antérieures pour la détection des bords. Plus particulièrement, les filtres Sobel et Scharr reposent sur des gradients d'image. Le filtre Sobel se résume à deux noyaux (Gx ainsi que Gy), où Gx détecte les changements horizontaux, tandis que Gy détecte les changements verticaux :

G

x

=

[

-
1

0

+
1

-
2

0

+
2

-
1

0

+
1

]

G

y

=

[

-
1

-
2

-
1

0

0

0

+
1

+
2

+
1

]

Lorsque vous les faites glisser sur une image, ils vont chacun "prendre" (accentuer) les lignes dans leur orientation respective. Les noyaux de Scharr fonctionnent de la même manière, avec des valeurs différentes :

G

x

=

[

+
3

0

-
3

+
10

0

-
10

+
3

0

-
3

]

G

y

=

[

+
3

+
10

+
3

0

0

0

-
3

-
10

-
3

]

Ces filtres, une fois convolués sur l'image, produiront des cartes d'entités :

Détection de bords OpenCV en Python avec cv2.Canny() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Crédit image : Davidwkennedy

Pour ces cartes d'entités, vous pouvez calculer la amplitude du gradient ainsi que orientation dégradée – c'est-à-dire quelle est l'intensité du changement (quelle est la probabilité que quelque chose soit un bord) et dans quelle direction le changement pointe. Puisque Gy désigne le changement vertical (gradient Y) et Gx désigne le changement horizontal (gradient X) - vous pouvez calculer la magnitude en appliquant simplement le théorème de Pythagore, pour obtenir l'hypothénuse du triangle formé par la "gauche" et "bonnes" directions :

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

En utilisant la magnitude et l'orientation, vous pouvez produire une image avec ses bords en surbrillance :

Détection de bords OpenCV en Python avec cv2.Canny() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Crédit image : Davidwkennedy

Cependant, vous pouvez voir combien de bruit a également été capté par la structure des briques ! Les dégradés d'image sont très sensibles au bruit. C'est pourquoi les filtres Sobel et Scharr ont été utilisés comme composant, mais pas la seule approche dans la méthode de Canny. Le lissage gaussien aide ici aussi.

Suppression non maximale

Un problème notable avec le filtre Sobel est que les bords ne sont pas vraiment clairs. Ce n'est pas comme si quelqu'un avait pris un crayon et tracé une ligne pour créer un lineart de l'image. Les bords ne sont généralement pas aussi nets dans les images, car la lumière se diffuse progressivement. Cependant, nous pouvons trouver la ligne commune dans les bords et supprimer le reste des pixels qui l'entourent, ce qui donne à la place une ligne de séparation nette et fine. C'est ce qu'on appelle la suppression non maximale ! Les pixels non max (ceux plus petits que celui auquel nous les comparons dans un petit champ local, tel qu'un noyau 3 × 3) sont supprimés. Le concept s'applique à plus de tâches que cela, mais lions-le à ce contexte pour l'instant.

Seuil d'hystérésis

De nombreux non-bords peuvent et seront probablement évalués comme des bords, en raison des conditions d'éclairage, des matériaux de l'image, etc. En raison des diverses raisons pour lesquelles ces erreurs de calcul se produisent - il est difficile de faire une évaluation automatisée de ce qu'est certainement un bord 't. Vous pouvez limiter les gradients et n'inclure que les plus forts, en supposant que les bords "réels" sont plus intenses que les "faux" bords.

Le seuil fonctionne à peu près de la même manière que d'habitude - si le gradient est inférieur à un seuil inférieur, supprimez-le (zéro), et s'il est supérieur à un seuil supérieur donné, conservez-le. Tout ce qui se situe entre la borne inférieure et la borne supérieure se trouve dans la « zone grise ». Si un front entre les seuils est connecté à un bord définitif (ceux au-dessus du seuil) - ils sont également considérés comme des bords. S'ils ne sont pas connectés, ce sont probablement des arficats d'un bord mal calculé.

C'est le seuillage d'hystérésis ! En effet, cela aide à nettoyer la sortie finale et à supprimer les faux bords, selon ce que vous classez comme un faux bord. Pour trouver de bonnes valeurs de seuil, vous expérimenterez généralement différentes limites inférieures et supérieures pour les seuils, ou utiliserez une méthode automatisée telle que la méthode d'Otsu ou la méthode Triangle.

Chargeons une image et mettons-la en niveaux de gris (Canny, tout comme Sobel/Scharr exige que les images soient en niveaux de gris) :

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

Détection de bords OpenCV en Python avec cv2.Canny() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

L'image en gros plan d'un doigt servira de bon terrain d'essai pour la détection des bords - il n'est pas facile de discerner une empreinte digitale de l'image, mais nous pouvons nous en approcher.

Détection des bords sur les images avec cv2.Canny()

L'algorithme de Canny peut être appliqué à l'aide d'OpenCV Canny() méthode:

cv2.Canny(input_img, lower_bound, upper_bound)

Consultez notre guide pratique et pratique pour apprendre Git, avec les meilleures pratiques, les normes acceptées par l'industrie et la feuille de triche incluse. Arrêtez de googler les commandes Git et en fait apprendre il!

Trouver le bon équilibre entre la limite inférieure et la limite supérieure peut être délicat. Si les deux sont faibles, vous aurez peu d'avantages. Si la limite inférieure est basse et la limite supérieure est élevée, vous aurez du bruit. Si les deux sont hauts et proches l'un de l'autre, vous aurez peu d'arêtes. Le bon endroit a juste assez d'écart entre les limites et les a sur la bonne échelle. Expérience!

L'image d'entrée sera floue par la méthode Canny, mais souvent, vous bénéficierez d'un flou before ça rentre aussi. La méthode applique un flou gaussien 5 × 5 à l'entrée avant de passer par le reste des opérations, mais même avec ce flou, du bruit peut encore s'infiltrer, nous avons donc flouté l'image avant de l'introduire dans l'algorithme :


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

Cela se traduit par:

Détection de bords OpenCV en Python avec cv2.Canny() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Les valeurs de 20 ainsi que 30 ici ne sont pas arbitraires - j'ai testé la méthode sur divers paramètres et j'ai choisi un ensemble qui semblait produire un résultat décent. Peut-on essayer d'automatiser cela ?

Seuil automatisé pour cv2.Canny() ?

Pouvez-vous trouver un ensemble optimal de valeurs de seuil ? Oui, mais ça ne marche pas toujours. Vous pouvez faire votre propre calcul pour une bonne valeur, puis ajuster la plage avec un sigma autour de ce seuil :

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

Quand sigma, c'est-à-dire 0.33 – les limites seront 0.66*threshold ainsi que 1.33*threshold, permettant une plage d'environ 1/3 autour de lui. Cependant, trouver le threshold c'est ce qu'il y a de plus difficile. OpenCV nous fournit la méthode d'Otsu (fonctionne très bien pour les images bimodales) et la méthode Triangle. Essayons les deux, en prenant une simple médiane des valeurs de pixel comme troisième option :

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

Cela se traduit par:

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

Ceux-ci sont assez différents ! D'après les valeurs que nous avons vues auparavant, nous pouvons anticiper que la méthode Triangle fonctionne le mieux ici. Le seuil manuel n'est pas très informé, puisqu'il ne prend que la valeur médiane du pixel, et finit par avoir un seuil de base élevé qui est encore multiplié dans une large plage pour cette image. La méthode d'Otsu en souffre moins, mais en souffre quand même.

Si nous exécutons le Canny() méthode avec ces plages de seuil :

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

Remarque: La fonction attend plusieurs arguments et nos seuils sont un seul tuple. Nous pouvons déstructurer le tuple en plusieurs arguments en le préfixant avec *. Cela fonctionne également sur les listes et les ensembles, et c'est un excellent moyen de fournir plusieurs arguments après les avoir obtenus par des moyens programmatiques.

Cela se traduit par:

Détection de bords OpenCV en Python avec cv2.Canny() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

La méthode Triangle a plutôt bien fonctionné ici ! Ce n'est pas une garantie que cela fonctionnera bien dans d'autres cas également.

Détection des bords en temps réel sur les vidéos avec cv2.Canny()

Enfin, appliquons la détection des contours Canny à une vidéo en temps réel ! Nous afficherons la vidéo en cours de traitement (chaque image au fur et à mesure) en utilisant cv2.imshow() qui affiche une fenêtre avec le cadre que nous aimerions afficher. Cependant, nous enregistrerons également la vidéo dans un fichier MP4 qui pourra ensuite être inspecté et partagé.

Pour charger une vidéo à l'aide d'OpenCV, nous utilisons le VideoCapture() méthode. Si nous passons dans 0 – il enregistrera à partir de la webcam actuelle, vous pouvez donc également exécuter le code sur votre webcam ! Si vous passez un nom de fichier, il chargera le fichier :

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

Les VideoWriter accepte plusieurs paramètres - le nom du fichier de sortie, le FourCC (quatre codes codec, désignant le codec utilisé pour encoder la vidéo), le framerate et la résolution sous forme de tuple. Pour ne pas deviner ou redimensionner la vidéo - nous avons utilisé la largeur et la hauteur de la vidéo d'origine, obtenues via le VideoCapture instance qui contient des données sur la vidéo elle-même, telles que la largeur, la hauteur, le nombre total d'images, etc.

Pendant que la capture est ouverte, nous essayons de lire l'image suivante avec cap.read(), qui renvoie un code de résultat et l'image suivante. Le code de résultat est True or False, indiquant la présence de la trame suivante ou son absence. Ce n'est que lorsqu'il y a une image que nous essaierons de la traiter davantage, sinon nous casserons la boucle. Pour chaque image valide, nous la passons à travers un flou gaussien, la convertissons en niveaux de gris, exécutons cv2.Canny() dessus et écrivez-le à l'aide du VideoWriter sur le disque et afficher à l'aide cv2.imshow() pour une vue en direct.

Enfin, nous libérons la capture et le graveur vidéo, car ils travaillent tous les deux avec des fichiers sur le disque, et détruisons toutes les fenêtres existantes.

Lorsque vous exécutez la méthode avec un secret_video.mp4 input – vous verrez une fenêtre pop-up et une fois que c'est terminé, un fichier dans votre répertoire de travail :

Détection de bords OpenCV en Python avec cv2.Canny() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Conclusion

Dans ce guide, nous avons examiné le fonctionnement de la détection des contours Canny et ses éléments constitutifs - lissage gaussien, filtres Sobel et gradients d'image, suppression non maximale et seuil d'hystérésis. Enfin, nous avons exploré des méthodes de recherche automatisée de plage de seuil pour la détection de bord Canny avec cv2.Canny(), et a utilisé la technique sur une vidéo, fournissant une détection des contours en temps réel et enregistrant les résultats dans un fichier vidéo.

Aller plus loin - Apprentissage profond pratique pour la vision par ordinateur

Votre nature curieuse vous donne envie d'aller plus loin ? Nous vous recommandons de consulter notre Cours: "Apprentissage profond pratique pour la vision par ordinateur avec Python".

Détection de bords OpenCV en Python avec cv2.Canny() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Un autre cours de vision par ordinateur ?

Nous ne ferons pas de classification des chiffres MNIST ou de la mode MNIST. Ils ont fait leur part il y a longtemps. Trop de ressources d'apprentissage se concentrent sur les ensembles de données de base et les architectures de base avant de laisser les architectures de boîte noire avancées assumer le fardeau des performances.

Nous voulons nous concentrer sur démystification, pratique, compréhension, intuition ainsi que de vrais projets. Vouloir apprendre how tu peux faire la différence? Nous vous emmènerons dans un voyage de la façon dont notre cerveau traite les images à l'écriture d'un classificateur d'apprentissage en profondeur de qualité recherche pour le cancer du sein aux réseaux d'apprentissage en profondeur qui "hallucinent", vous enseignant les principes et la théorie par le biais de travaux pratiques, vous équipant du savoir-faire et outils pour devenir un expert dans l'application de l'apprentissage profond pour résoudre la vision par ordinateur.

Qu'est-ce qu'il y a à l'intérieur?

  • Les premiers principes de la vision et comment apprendre aux ordinateurs à « voir »
  • Différentes tâches et applications de la vision par ordinateur
  • Les outils du métier qui faciliteront votre travail
  • Trouver, créer et utiliser des ensembles de données pour la vision par ordinateur
  • La théorie et l'application des réseaux de neurones convolutifs
  • Gestion du changement de domaine, de la cooccurrence et d'autres biais dans les ensembles de données
  • Transférer Apprendre et utiliser le temps de formation et les ressources informatiques des autres à votre avantage
  • Construire et former un classificateur de pointe du cancer du sein
  • Comment appliquer une bonne dose de scepticisme aux idées dominantes et comprendre les implications des techniques largement adoptées
  • Visualiser « l'espace conceptuel » d'un ConvNet à l'aide de t-SNE et PCA
  • Études de cas sur la façon dont les entreprises utilisent les techniques de vision par ordinateur pour obtenir de meilleurs résultats
  • Évaluation appropriée du modèle, visualisation de l'espace latent et identification de l'attention du modèle
  • Effectuer des recherches de domaine, traiter vos propres ensembles de données et établir des tests de modèles
  • Les architectures de pointe, la progression des idées, ce qui les rend uniques et comment les mettre en œuvre
  • KerasCV - une bibliothèque WIP pour créer des pipelines et des modèles de pointe
  • Comment analyser et lire des articles et les mettre en œuvre vous-même
  • Sélection de modèles en fonction de votre application
  • Création d'un pipeline d'apprentissage automatique de bout en bout
  • Paysage et intuition sur la détection d'objets avec Faster R-CNN, RetinaNets, SSD et YOLO
  • Instance et segmentation sémantique
  • Reconnaissance d'objets en temps réel avec YOLOv5
  • Formation aux détecteurs d'objets YOLOv5
  • Travailler avec des transformateurs à l'aide de KerasNLP (bibliothèque WIP de pointe)
  • Intégration de Transformers avec ConvNets pour générer des légendes d'images
  • Rêve profond
  • Optimisation du modèle de Deep Learning pour la vision par ordinateur

Horodatage:

Plus de Stackabuse