„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > Ein Leitfaden zur unbeaufsichtigten Bildsegmentierung mit normalisierten Schnitten (NCut) in Python

Ein Leitfaden zur unbeaufsichtigten Bildsegmentierung mit normalisierten Schnitten (NCut) in Python

Veröffentlicht am 08.11.2024
Durchsuche:241

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

Einführung

Bildsegmentierung spielt eine entscheidende Rolle beim Verständnis und der Analyse visueller Daten, und Normalized Cuts (NCut) ist eine weit verbreitete Methode zur diagrammbasierten Segmentierung. In diesem Artikel untersuchen wir, wie man NCut für die unbeaufsichtigte Bildsegmentierung in Python mithilfe eines Datensatzes von Microsoft Research anwendet, wobei der Schwerpunkt auf der Verbesserung der Segmentierungsqualität mithilfe von Superpixeln liegt.
Datensatzübersicht
Der für diese Aufgabe verwendete Datensatz kann unter folgendem Link heruntergeladen werden: MSRC Object Category Image Database. Dieser Datensatz enthält Originalbilder sowie deren semantische Segmentierung in neun Objektklassen (gekennzeichnet durch Bilddateien mit der Endung „_GT“). Diese Bilder sind in thematische Teilmengen gruppiert, wobei sich die erste Zahl im Dateinamen auf eine Klassenteilmenge bezieht. Dieser Datensatz eignet sich perfekt zum Experimentieren mit Segmentierungsaufgaben.

Problemstellung

Wir führen eine Bildsegmentierung für ein Bild im Datensatz mithilfe des NCut-Algorithmus durch. Die Segmentierung auf Pixelebene ist rechenintensiv und häufig verrauscht. Um dies zu überwinden, verwenden wir SLIC (Simple Linear Iterative Clustering), um Superpixel zu generieren, wodurch ähnliche Pixel gruppiert und die Problemgröße reduziert werden. Um die Genauigkeit der Segmentierung zu bewerten, können verschiedene Metriken (z. B. Intersection over Union, SSIM, Rand Index) verwendet werden.

Durchführung

1. Erforderliche Bibliotheken installieren
Wir verwenden Skimage für die Bildverarbeitung, Numpy für numerische Berechnungen und Matplotlib für die Visualisierung.

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

Laden Sie nach dem Herunterladen und Extrahieren des Datensatzes die Bilder und die Ground-Truth-Segmentierung:

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

Jetzt können wir mit dem Codieren beginnen.

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. Generieren Sie Superpixel mit SLIC und erstellen Sie ein Region Adjacency Graph

Wir verwenden den SLIC-Algorithmus, um Superpixel zu berechnen, bevor wir NCut anwenden. Mithilfe der generierten Superpixel erstellen wir einen Region Adjacency Graph (RAG) basierend auf der mittleren Farbähnlichkeit:

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

Kompaktheit steuert das Gleichgewicht zwischen der Farbähnlichkeit und der räumlichen Nähe von Pixeln bei der Bildung von Superpixeln. Es bestimmt, wie viel Wert darauf gelegt wird, die Superpixel kompakt zu halten (räumlich näher beieinander zu halten) oder sicherzustellen, dass sie homogener nach Farben gruppiert sind.
Höhere Werte: Ein höherer Kompaktheitswert führt dazu, dass der Algorithmus die Erstellung von Superpixeln priorisiert, die räumlich eng und gleichmäßig groß sind, wobei der Farbähnlichkeit weniger Aufmerksamkeit geschenkt wird. Dies kann dazu führen, dass Superpixel weniger empfindlich auf Kanten oder Farbverläufe reagieren.
Niedrigere Werte: Ein niedrigerer Kompaktheitswert ermöglicht es den Superpixeln, in ihrer räumlichen Größe stärker zu variieren, um die Farbunterschiede genauer zu berücksichtigen. Dies führt typischerweise zu Superpixeln, die den Grenzen von Objekten im Bild genauer folgen.

n_segments steuert die Anzahl der Superpixel (oder Segmente), die der SLIC-Algorithmus im Bild zu generieren versucht. Im Wesentlichen legt es die Auflösung der Segmentierung fest.
Höhere Werte: Ein höherer n_segments-Wert erzeugt mehr Superpixel, was bedeutet, dass jedes Superpixel kleiner und die Segmentierung feinkörniger ist. Dies kann nützlich sein, wenn das Bild komplexe Texturen oder kleine Objekte aufweist.
Niedrigere Werte: Ein niedrigerer n_segments-Wert erzeugt weniger, größere Superpixel. Dies ist nützlich, wenn Sie eine grobe Segmentierung des Bildes wünschen und größere Bereiche in einzelne Superpixel gruppieren möchten.

4. Anwenden normalisierter Schnitte (NCut) und Visualisieren des Ergebnisses

# 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. Bewertungsmetriken
Die größte Herausforderung bei der unbeaufsichtigten Segmentierung besteht darin, dass NCut die genaue Anzahl der Klassen im Bild nicht kennt. Die Anzahl der von Ncut gefundenen Segmente kann die tatsächliche Anzahl der Ground-Truth-Regionen überschreiten. Daher benötigen wir robuste Metriken zur Beurteilung der Segmentierungsqualität.

Intersection over Union (IoU) ist eine weit verbreitete Metrik zur Bewertung von Segmentierungsaufgaben, insbesondere in der Computer Vision. Es misst die Überlappung zwischen den vorhergesagten segmentierten Regionen und den Ground-Truth-Regionen. Insbesondere berechnet IoU das Verhältnis der Überlappungsfläche zwischen der vorhergesagten Segmentierung und der Grundwahrheit zur Fläche ihrer Vereinigung.

Structural Similarity Index (SSIM) ist eine Metrik zur Beurteilung der wahrgenommenen Qualität eines Bildes durch den Vergleich zweier Bilder hinsichtlich Luminanz, Kontrast und Struktur.

Um diese Metriken anzuwenden, müssen die Vorhersage und das Ground-Truth-Bild dieselben Bezeichnungen haben. Um die Beschriftungen zu berechnen, berechnen wir eine Maske auf dem Boden und weisen bei der Vorhersage jeder auf dem Bild gefundenen Farbe eine ID zu
Bei der Segmentierung mit NCut werden jedoch möglicherweise mehr Regionen als die Grundwahrheit gefunden, was die Genauigkeit verringert.

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)

Jetzt berechnen wir die Genauigkeitswerte

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

Abschluss

Normalized Cuts ist eine leistungsstarke Methode zur unbeaufsichtigten Bildsegmentierung, bringt jedoch Herausforderungen wie Übersegmentierung und Optimierung der Parameter mit sich. Durch die Einbeziehung von Superpixeln und die Bewertung der Leistung anhand geeigneter Metriken kann NCut komplexe Bilder effektiv segmentieren. Die IoU- und Rand-Index-Metriken liefern aussagekräftige Einblicke in die Qualität der Segmentierung, obwohl eine weitere Verfeinerung erforderlich ist, um Mehrklassenszenarien effektiv zu bewältigen.
Ein vollständiges Beispiel finden Sie schließlich hier in meinem Notizbuch.

Freigabeerklärung Dieser Artikel ist abgedruckt unter: https://dev.to/sopralapanca/a-guide-to-unsupervised-image-segmentation-using-normalized-cuts-ncut-in-python-13pk?1 Wenn es einen Verstoß gibt, bitte Kontaktieren Sie Study_golang@163 .comdelete
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3