"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Un guide sur la segmentation d'images non supervisée à l'aide de coupes normalisées (NCut) en Python

Un guide sur la segmentation d'images non supervisée à l'aide de coupes normalisées (NCut) en Python

Publié le 2024-11-08
Parcourir:853

A Guide to Unsupervised Image Segmentation using Normalized Cuts (NCut) in Python

Introduction

La segmentation d'images joue un rôle essentiel dans la compréhension et l'analyse des données visuelles, et les coupes normalisées (NCut) sont une méthode largement utilisée pour la segmentation basée sur des graphiques. Dans cet article, nous explorerons comment appliquer NCut pour la segmentation d'images non supervisée en Python à l'aide d'un ensemble de données de Microsoft Research, en mettant l'accent sur l'amélioration de la qualité de la segmentation à l'aide de superpixels.
Présentation de l'ensemble de données
L'ensemble de données utilisé pour cette tâche peut être téléchargé à partir du lien suivant : MSRC Object Category Image Database. Cet ensemble de données contient des images originales ainsi que leur segmentation sémantique en neuf classes d'objets (indiquées par des fichiers images se terminant par « _GT »). Ces images sont regroupées en sous-ensembles thématiques, où le premier numéro du nom du fichier fait référence à un sous-ensemble de classe. Cet ensemble de données est parfait pour expérimenter des tâches de segmentation.

Énoncé du problème

Nous effectuons une segmentation d'image sur une image de l'ensemble de données à l'aide de l'algorithme NCut. La segmentation au niveau des pixels est coûteuse en calcul et souvent bruyante. Pour surmonter ce problème, nous utilisons SLIC (Simple Linear Iterative Clustering) pour générer des superpixels, qui regroupent les pixels similaires et réduisent la taille du problème. Pour évaluer l'exactitude de la segmentation, différentes mesures (par exemple, Intersection over Union, SSIM, Rand Index) peuvent être utilisées.

Mise en œuvre

1. Installer les bibliothèques requises
Nous utilisons skimage pour le traitement d'images, numpy pour les calculs numériques et matplotlib pour la visualisation.

pip install numpy matplotlib
pip install scikit-image==0.24.0
**2. Load and Preprocess the Dataset**

Après avoir téléchargé et extrait l'ensemble de données, chargez les images et la segmentation de la vérité terrain :

wget http://download.microsoft.com/download/A/1/1/A116CD80-5B79-407E-B5CE-3D5C6ED8B0D5/msrc_objcategimagedatabase_v1.zip -O msrc_objcategimagedatabase_v1.zip
unzip msrc_objcategimagedatabase_v1.zip
rm msrc_objcategimagedatabase_v1.zip

Nous sommes maintenant prêts à commencer à coder.

from skimage import io, segmentation, color, measure
from skimage import graph
import numpy as np
import matplotlib.pyplot as plt

# Load the image and its ground truth
image = io.imread('/content/MSRC_ObjCategImageDatabase_v1/1_16_s.bmp')
ground_truth = io.imread('/content/MSRC_ObjCategImageDatabase_v1/1_16_s_GT.bmp')

# show images side by side
fig, ax = plt.subplots(1, 2, figsize=(10, 5))
ax[0].imshow(image)
ax[0].set_title('Image')
ax[1].imshow(ground_truth)
ax[1].set_title('Ground Truth')
plt.show()

3. Générez des superpixels à l'aide de SLIC et créez un graphique de contiguïté de région

Nous utilisons l'algorithme SLIC pour calculer les superpixels avant d'appliquer NCut. À l'aide des superpixels générés, nous construisons un graphique de contiguïté de région (RAG) basé sur la similarité moyenne des couleurs :

from skimage.util import img_as_ubyte, img_as_float, img_as_uint, img_as_float64

compactness=30 
n_segments=100 
labels = segmentation.slic(image, compactness=compactness, n_segments=n_segments, enforce_connectivity=True)
image_with_boundaries = segmentation.mark_boundaries(image, labels, color=(0, 0, 0))
image_with_boundaries = img_as_ubyte(image_with_boundaries)
pixel_labels = color.label2rgb(labels, image_with_boundaries, kind='avg', bg_label=0

compacité contrôle l'équilibre entre la similarité des couleurs et la proximité spatiale des pixels lors de la formation des superpixels. Il détermine dans quelle mesure l'accent est mis sur le maintien de la compacité des superpixels (plus proches en termes spatiaux) plutôt que sur la garantie qu'ils sont regroupés de manière plus homogène par couleur.
Valeurs plus élevées : une valeur de compacité plus élevée amène l'algorithme à donner la priorité à la création de superpixels spatialement restreints et de taille uniforme, avec moins d'attention à la similarité des couleurs. Cela peut donner lieu à des superpixels moins sensibles aux contours ou aux dégradés de couleurs.
Valeurs inférieures : Une valeur de compacité inférieure permet aux superpixels de varier davantage en taille spatiale afin de respecter plus précisément les différences de couleur. Cela se traduit généralement par des superpixels qui suivent de plus près les limites des objets dans l'image.

n_segments contrôle le nombre de superpixels (ou segments) que l'algorithme SLIC tente de générer dans l'image. Essentiellement, il définit la résolution de la segmentation.
Valeurs plus élevées : une valeur n_segments plus élevée crée plus de superpixels, ce qui signifie que chaque superpixel sera plus petit et que la segmentation sera plus fine. Cela peut être utile lorsque l'image comporte des textures complexes ou de petits objets.
Valeurs inférieures : une valeur n_segments inférieure produit des superpixels moins nombreux et plus grands. Ceci est utile lorsque vous souhaitez une segmentation grossière de l'image, regroupant des zones plus grandes en superpixels uniques.

4. Appliquez des coupes normalisées (NCut) et visualisez le résultat

# using the labels found with the superpixeled image
# compute the Region Adjacency Graph using mean colors
g = graph.rag_mean_color(image, labels, mode='similarity')

# perform Normalized Graph cut on the Region Adjacency Graph
labels2 = graph.cut_normalized(labels, g)
segmented_image = color.label2rgb(labels2, image, kind='avg')
f, axarr = plt.subplots(nrows=1, ncols=4, figsize=(25, 20))

axarr[0].imshow(image)
axarr[0].set_title("Original")

#plot boundaries
axarr[1].imshow(image_with_boundaries)
axarr[1].set_title("Superpixels Boundaries")

#plot labels
axarr[2].imshow(pixel_labels)
axarr[2].set_title('Superpixel Labels')

#compute segmentation
axarr[3].imshow(segmented_image)
axarr[3].set_title('Segmented image (normalized cut)')

5. Paramètres d'évaluation
Le principal défi de la segmentation non supervisée est que NCut ne connaît pas le nombre exact de classes dans l'image. Le nombre de segments trouvés par NCut peut dépasser le nombre réel de régions de vérité terrain. Par conséquent, nous avons besoin de mesures robustes pour évaluer la qualité de la segmentation.

Intersection over Union (IoU) est une métrique largement utilisée pour évaluer les tâches de segmentation, en particulier en vision par ordinateur. Il mesure le chevauchement entre les régions segmentées prédites et les régions de vérité terrain. Plus précisément, IoU calcule le rapport entre la zone de chevauchement entre la segmentation prédite et la vérité terrain et la zone de leur union.

L'indice de similarité structurelle (SSIM) est une mesure utilisée pour évaluer la qualité perçue d'une image en comparant deux images en termes de luminance, de contraste et de structure.

Pour appliquer ces métriques, nous avons besoin que la prédiction et l'image de vérité terrain aient les mêmes étiquettes. Pour calculer les étiquettes nous calculons un masque au sol et sur la prédiction attribuons un identifiant à chaque couleur trouvée sur l'image
La segmentation à l'aide de NCut peut cependant trouver plus de régions que la vérité terrain, ce qui réduira la précision.

def compute_mask(image):
  color_dict = {}

  # Get the shape of the image
  height,width,_ = image.shape

  # Create an empty array for labels
  labels = np.zeros((height,width),dtype=int)
  id=0
  # Loop over each pixel
  for i in range(height):
      for j in range(width):
          # Get the color of the pixel
          color = tuple(image[i,j])
          # Check if it is in the dictionary
          if color in color_dict:
              # Assign the label from the dictionary
              labels[i,j] = color_dict[color]
          else:
              color_dict[color]=id
              labels[i,j] = id
              id =1

  return(labels)
def show_img(prediction, groundtruth):
  f, axarr = plt.subplots(nrows=1, ncols=2, figsize=(15, 10))

  axarr[0].imshow(groundtruth)
  axarr[0].set_title("groundtruth")
  axarr[1].imshow(prediction)
  axarr[1].set_title(f"prediction")
prediction_mask = compute_mask(segmented_image)
groundtruth_mask = compute_mask(ground_truth)

#usign the original image as baseline to convert from labels to color
prediction_img = color.label2rgb(prediction_mask, image, kind='avg', bg_label=0)
groundtruth_img = color.label2rgb(groundtruth_mask, image, kind='avg', bg_label=0)

show_img(prediction_img, groundtruth_img)

Nous calculons maintenant les scores de précision

from sklearn.metrics import jaccard_score
from skimage.metrics import structural_similarity as ssim

ssim_score = ssim(prediction_img, groundtruth_img, channel_axis=2)
print(f"SSIM SCORE: {ssim_score}")

jac = jaccard_score(y_true=np.asarray(groundtruth_mask).flatten(),
                        y_pred=np.asarray(prediction_mask).flatten(),
                        average = None)

# compute mean IoU score across all classes
mean_iou = np.mean(jac)
print(f"Mean IoU: {mean_iou}")

Conclusion

Les coupes normalisées sont une méthode puissante pour la segmentation d'images non supervisée, mais elle présente des défis tels que la sur-segmentation et le réglage des paramètres. En incorporant des superpixels et en évaluant les performances à l'aide de mesures appropriées, NCut peut segmenter efficacement des images complexes. Les métriques IoU et Rand Index fournissent des informations significatives sur la qualité de la segmentation, bien que des affinements supplémentaires soient nécessaires pour gérer efficacement les scénarios multi-classes.
Enfin, un exemple complet est disponible dans mon carnet ici.

Déclaration de sortie Cet article est reproduit sur : https://dev.to/sopralapanca/a-guide-to-unsupervised-image-segmentation-using-normalized-cuts-ncut-in-python-13pk?1 En cas de violation, veuillez contacter study_golang@163 .comdelete
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3