Seuil OpenCV en Python avec cv2.threshold() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Seuil OpenCV en Python avec cv2.threshold()

Introduction

Le seuillage est une technique simple et efficace pour effectuer une segmentation de base dans une image, et pour la binariser (la transformer en une image binaire) où les pixels sont soit 0 or 1 (ou 255 si vous utilisez des nombres entiers pour les représenter).

En règle générale, vous pouvez utiliser le seuillage pour effectuer une simple segmentation arrière-plan-avant-plan dans une image, et cela se résume à des variantes d'une technique simple pour chaque pixel :

if pixel_value > threshold:
    pixel_value = MAX
else:
    pixel_value = 0

Ce processus essentiel est connu sous le nom de Seuil binaire. Maintenant - il existe différentes façons de modifier cette idée générale, notamment en inversant les opérations (changer le > signer avec un < signe), en définissant le pixel_value à la threshold au lieu d'une valeur maximale/0 (appelée troncature), en gardant le pixel_value lui-même s'il est au-dessus du threshold ou s'il est en dessous du threshold.

Tous ces éléments ont été commodément implémentés dans OpenCV comme:

  • cv2.THRESH_BINARY
  • cv2.THRESH_BINARY_INV
  • cv2.THRESH_TRUNC
  • cv2.THRESH_TOZERO
  • cv2.THRESH_TOZERO_INV

… respectivement. Ce sont des méthodes relativement "naïves" en ce sens qu'elles sont assez simples, ne tiennent pas compte du contexte dans les images, savent quelles formes sont courantes, etc. Pour ces propriétés - nous devrions utiliser beaucoup plus de calculs coûteux et puissants techniques.

Maintenant, même avec les méthodes "naïves" - quelques des heuristiques peuvent être mises en place, pour trouver de bons seuils, parmi lesquelles la méthode Otsu et la méthode Triangle :

  • cv2.THRESH_OTSU
  • cv2.THRESH_TRIANGLE

Remarque: Le seuillage OpenCV est une technique rudimentaire et est sensible aux changements d'éclairage et aux dégradés, à l'hétérogénéité des couleurs, etc. Il est préférable de l'appliquer sur des images relativement propres, après les avoir floutées pour réduire le bruit, sans trop de variation de couleur dans les objets que vous souhaitez segmenter.

Une autre façon de surmonter certains des problèmes liés au seuillage de base avec une seule valeur de seuil consiste à utiliser seuillage adaptatif qui applique une valeur de seuil sur chaque petite région d'une image, plutôt que globalement.

Seuil simple avec OpenCV

Le seuillage dans l'API Python d'OpenCV se fait via le cv2.threshold() méthode - qui accepte une image (tableau NumPy, représenté par des entiers), le seuil, la valeur maximale et la méthode de seuillage (comment le threshold ainsi que maximum_value sont utilisés):

img = cv2.imread('objects.jpg')

img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)


blurred = cv2.GaussianBlur(img, (7, 7), 0)

ret, img_masked = cv2.threshold(blurred, 220, 255, cv2.THRESH_BINARY)

Le code de retour n'est que le seuil appliqué :

print(f"Threshold: {ret}") 

Ici, puisque le seuil est 220 et nous avons utilisé le THRESH_BINARY méthode - chaque valeur de pixel ci-dessus 220 sera porté à 255, tandis que chaque valeur de pixel ci-dessous 220 sera abaissé à 0, créant une image en noir et blanc, avec un « masque », recouvrant les objets de premier plan.

Pourquoi 220 ? Savoir à quoi ressemble l'image vous permet de faire des suppositions approximatives sur le seuil que vous pouvez choisir. En pratique, vous souhaiterez rarement définir un seuil manuel, et nous aborderons la sélection automatique du seuil dans un instant.

Traçons le résultat ! Les fenêtres OpenCV peuvent être un peu capricieuses, nous allons donc tracer l'image d'origine, l'image floue et les résultats à l'aide de Matplotlib :

fig, ax = plt.subplots(1, 3, figsize=(12, 8))
ax[0].imshow(img)
ax[1].imshow(blurred)
ax[2].imshow(img_masked)

Méthodes de seuil

Comme mentionné précédemment, il existe différentes manières d'utiliser le seuil et la valeur maximale dans une fonction. Nous avons d'abord examiné le seuil binaire. Créons une liste de méthodes et appliquons-les une par une, en traçant les résultats :

methods = [cv2.THRESH_BINARY, cv2.THRESH_BINARY_INV, cv2.THRESH_TRUNC, cv2.THRESH_TOZERO, cv2.THRESH_TOZERO_INV]
names = ['Binary Threshold', 'Inverse Binary Threshold', 'Truncated Threshold', 'To-Zero Threshold', 'Inverse To-Zero Threshold']

def thresh(img_path, method, index):
    img = cv2.imread(img_path)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    blurred = cv2.GaussianBlur(img, (7, 7), 0)
    ret, img_masked = cv2.threshold(blurred, 220, 255, method)

    fig, ax = plt.subplots(1, 3, figsize=(12, 4))
    fig.suptitle(names[index], fontsize=18)
    ax[0].imshow(img)
    ax[1].imshow(blurred)
    ax[2].imshow(img_masked)
    plt.tight_layout()

for index, method in enumerate(methods):
    thresh('coins.jpeg', method, index)

THRESH_BINARY ainsi que THRESH_BINARY_INV sont inverses l'un de l'autre et binarisent une image entre 0 ainsi que 255, en les affectant respectivement à l'arrière-plan et au premier plan, et vice versa.

THRESH_TRUNC binarise l'image entre threshold ainsi que 255.

THRESH_TOZERO ainsi que THRESH_TOZERO_INV binariser entre 0 et la valeur actuelle du pixel (src(x, y)). Jetons un coup d'œil aux images obtenues :

Seuil OpenCV en Python avec cv2.threshold() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

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!

Seuil OpenCV en Python avec cv2.threshold() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.
Seuil OpenCV en Python avec cv2.threshold() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.
Seuil OpenCV en Python avec cv2.threshold() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.
Seuil OpenCV en Python avec cv2.threshold() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Ces méthodes sont assez intuitives – mais comment pouvons-nous automatiser une bonne valeur de seuil, et que signifie même une « bonne valeur de seuil » ? Jusqu'à présent, la plupart des résultats avaient des masques non idéaux, avec des marques et des taches. Cela se produit en raison de la différence entre les surfaces réfléchissantes des pièces - elles ne sont pas uniformément colorées en raison de la différence dans la façon dont les crêtes réfléchissent la lumière.

Nous pouvons, dans une certaine mesure, lutter contre cela en trouvant un meilleur seuil global.

Seuil automatique/optimisé avec OpenCV

OpenCV utilise deux méthodes efficaces de recherche de seuil global - la méthode d'Otsu et la méthode Triangle.

La méthode d'Otsu suppose qu'elle fonctionne sur bimodal images. Les images bimodales sont des images dont les histogrammes de couleur ne contiennent que deux pics (c'est-à-dire n'ont que deux valeurs de pixel distinctes). Considérant que les pics appartiennent chacun à une classe telle qu'un «arrière-plan» et un «premier plan» - le seuil idéal se situe en plein milieu d'eux.

Seuil OpenCV en Python avec cv2.threshold() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.
Crédit image: https://scipy-lectures.org/

Vous pouvez rendre certaines images plus bimodales avec des flous gaussiens, mais pas toutes.

Un algorithme alternatif, souvent plus performant, est l'algorithme du triangle, qui calcule la distance entre le maximum et le minimum de l'histogramme de niveaux de gris et trace une ligne. Le point auquel cette ligne est au maximum éloignée du reste de l'histogramme est choisi comme seuil :

Seuil OpenCV en Python avec cv2.threshold() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Les deux supposent une image en niveaux de gris, nous devrons donc convertir l'image d'entrée en gris via cv2.cvtColor():

img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)

ret, mask1 = cv2.threshold(blurred, 0, 255, cv2.THRESH_OTSU)
ret, mask2 = cv2.threshold(blurred, 0, 255, cv2.THRESH_TRIANGLE)

masked = cv2.bitwise_and(img, img, mask=mask1)

Exécutons l'image avec les deux méthodes et visualisons les résultats :

methods = [cv2.THRESH_OTSU, cv2.THRESH_TRIANGLE]
names = ['Otsu Method', 'Triangle Method']

def thresh(img_path, method, index):
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (7, 7), 0)

    ret, img_masked = cv2.threshold(blurred, 0, 255, method)
    print(f"Threshold: {ret}")

    fig, ax = plt.subplots(1, 3, figsize=(12, 5))
    fig.suptitle(names[index], fontsize=18)
    ax[0].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    ax[1].imshow(cv2.cvtColor(gray, cv2.COLOR_BGR2RGB))
    ax[2].imshow(cv2.cvtColor(img_masked, cv2.COLOR_BGR2RGB))

for index, method in enumerate(methods):
    thresh('coins.jpeg', method, index)

Seuil OpenCV en Python avec cv2.threshold() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.
Seuil OpenCV en Python avec cv2.threshold() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Ici, la méthode du triangle surpasse la méthode d'Otsu, car l'image n'est pas bimodale :

import numpy as np

img = cv2.imread('coins.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)

histogram_gray, bin_edges_gray = np.histogram(gray, bins=256, range=(0, 255))
histogram_blurred, bin_edges_blurred = np.histogram(blurred, bins=256, range=(0, 255))

fig, ax = plt.subplots(1, 2, figsize=(12, 4))

ax[0].plot(bin_edges_gray[0:-1], histogram_gray)
ax[1].plot(bin_edges_blurred[0:-1], histogram_blurred)

Seuil OpenCV en Python avec cv2.threshold() PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Cependant, il est clair que la méthode du triangle a pu fonctionner avec l'image et produire un résultat plus satisfaisant.

Limites du seuil OpenCV

Le seuillage avec OpenCV est simple, facile et efficace. Pourtant, c'est assez limité. Dès que vous introduisez des éléments colorés, des arrière-plans non uniformes et des conditions d'éclairage changeantes, le seuillage global en tant que concept devient trop rigide.

Les images sont généralement trop complexes pour qu'un seul seuil soit suffisant, et cela peut être partiellement résolu par seuillage adaptatif, où de nombreux seuils locaux sont appliqués au lieu d'un seul global. Bien qu'il soit également limité, le seuillage adaptatif est beaucoup plus flexible que le seuillage global.

Conclusion

Ces dernières années, la segmentation binaire (comme ce que nous avons fait ici) et la segmentation multi-étiquettes (où vous pouvez avoir un nombre arbitraire de classes encodées) ont été modélisées avec succès avec des réseaux d'apprentissage en profondeur, qui sont beaucoup plus puissants et flexibles. De plus, ils peuvent encoder le contexte global et local dans les images qu'ils segmentent. L'inconvénient est que vous avez besoin de données pour les former, ainsi que de temps et d'expertise.

Pour un seuillage simple à la volée, vous pouvez utiliser OpenCV. Pour une segmentation précise au niveau de la production, vous souhaiterez utiliser des réseaux de neurones.

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".

Seuil OpenCV en Python avec cv2.threshold() 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