Grafik von Sebastian Svenson – https://unsplash.com/@sebastiansvenson

Image Segmentation: Untersuchung von Anwendungsfällen von Microsofts Pretrained Transformer Kosmos2

Die Bildsegmentierung ist für die Objekterkennung und fortgeschrittene Bildverarbeitung von entscheidender Bedeutung, und das neuronale Netz Kosmos-2 verbessert sie, indem es Text in der visuellen Welt verankert, Objektbeschreibungen wahrnimmt und sie mit den entsprechenden Bildregionen verknüpft. Heute werden wir Anwendungsfälle für ein solches Modell untersuchen.

Henrik Bartsch

Henrik Bartsch

Die Texte in diesem Artikel wurden teilweise mit Hilfe künstlicher Intelligenz erarbeitet und von uns korrigiert und überarbeitet. Für die Generierung wurden folgende Dienste verwendet:

Einführung

Ob im E-Commerce, im Gesundheitswesen, in den sozialen Medien oder bei selbstfahrenden Autos - die Identifizierung und Lokalisierung von Objekten in Bildern ist eine nützliche Fähigkeit von Algorithmen. Diese Fähigkeit spielt in der heutigen digitalen Welt eine entscheidende Rolle, da sie eine Vielzahl von Anwendungen ermöglicht. Es ist auch eine sehr komplexe Aufgabe, da sie ein hohes Maß an Genauigkeit und Detail erfordert.

In diesem Beitrag möchte ich einen Pretrained Transformer für diese Aufgabe vorstellen: Kosmos2 von Microsoft.

Image Segmentation

Die Bildsegmentierung (Image Segmentation) ist eine Technik der digitalen Bildverarbeitung und des maschinellen Sehens. Dabei wird ein digitales Bild in mehrere Segmente unterteilt, die auch als Image Regions oder Image Objects bezeichnet werden. Ziel der Segmentierung ist es, die Darstellung eines Bildes zu vereinfachen und/oder in etwas zu verändern, das aussagekräftiger und einfacher zu analysieren ist. Genauer gesagt ist die Bildsegmentierung der Prozess, bei dem jedem Pixel in einem Bild ein Name zugewiesen wird, so dass Pixel mit demselben Namen bestimmte Eigenschaften gemeinsam haben. Das Ergebnis der Bildsegmentierung ist ein Satz von Segmenten, die zusammen das gesamte Bild abdecken, oder ein Satz von aus dem Bild extrahierten Konturen. Alle Pixel in einer Region ähneln sich hinsichtlich bestimmter charakteristischer oder berechneter Eigenschaften wie Farbe, Intensität oder Textur. 1 2 3

Image Segmentation wird typischerweise verwendet, um Objekte und Grenzen (Linien, Kurven usw.) in Bildern zu lokalisieren. Bei Anwendung auf einen Image Stack (eine Reihe von Bildern), wie er in der medizinischen Bildgebung üblich ist, können die aus der Bildsegmentierung resultierenden Konturen mit Hilfe von geometrischen Rekonstruktionsalgorithmen zur Erstellung von 3D-Rekonstruktionen verwendet werden. 1 2

Kosmos 2

Kosmos-2 ist ein Multimodal Large Language Model (MLLM), das von Microsoft Research entwickelt wurde. Es wurde entwickelt, um Objektbeschreibungen (z.B. Begrenzungsrahmen) zu generieren und Text in die visuelle Welt zu integrieren. Das bedeutet, dass Textbeschreibungen mit den entsprechenden visuellen Repräsentationen verknüpft werden können.

Kosmos-2 stellt Referenzausdrücke als Links in Markdown dar, wobei Objektbeschreibungen Sequenzen von Orts-Tokens sind. Für das Training werden umfangreiche Daten von grounded image-text pairs (sog. GrIT) verwendet. Zusätzlich zu den bestehenden Fähigkeiten von MLLMs (z.B. allgemeine Modalitäten wahrnehmen, Anweisungen folgen und kontextbezogenes Lernen) ist es möglich, Kosmos-2 in nachgelagerte Anwendungen zu integrieren. Es wird anhand einer breiten Palette von Aufgaben evaluiert, darunter multimodales Grounding, multimodale Referenzierung, Sprachwahrnehmungsaufgaben, Sprachverständnis und Sprachgenerierung.

Diese Arbeit legt den Grundstein für die Entwicklung von Embodiment AI und zeigt die Konvergenz von Sprache, multimodaler Wahrnehmung, Handlung und Weltmodellierung auf, was einen wichtigen Schritt in Richtung artificial general intelligence (AGI) darstellt. 4 5 6 7

Verwendung des Modells

Wie sonst auch immer, beginnen wir damit alle notwendigen Imports zu laden.

kosmos2.py
from PIL import Image
from transformers import AutoProcessor, AutoModelForVision2Seq

import cv2

import numpy as np

Anschließend können wir uns mithilfe der huggingface-API sowohl das eigentliche neuronale Netz als auch den Processor herunterladen.

kosmos2.py
model = AutoModelForVision2Seq.from_pretrained("microsoft/kosmos-2-patch14-224")
processor = AutoProcessor.from_pretrained("microsoft/kosmos-2-patch14-224")

Nun können wir genauer auf die beiden großen Anwendungsfelder dieses Modells eingehen: Bildbeschreibungen und Bildsegmentierung. Wir beginnen an dieser Stelle aufgrund der Einfachheit und Bekanntheit mit dem Anwendungsfall der Textbeschreibung.

Bildbeschreibung

Für eine Textbeschreibung ist es notwendig, dass wir uns ein Bild heraussuchen welches wir beschreiben wollen lassen. Wir haben dazu dieses Bild als Beispiel ausgewählt:

Grafik von Jay Mantri - https://unsplash.com/@jaymantri

Wir können nun beginnen, dieses Bild durch PIL einzuladen.

kosmos2.py
image = Image.open("Kosmos-Images/test-image.jpeg")
prompt = "<grounding>An image of"

Anschließend können wir das Bild dann mit dem hier definierten Prompt in das Modell zur Verarbeitung geben.

kosmos2.py
inputs = processor(text=prompt, images=image, return_tensors="pt")

generated_ids = model.generate(
    pixel_values=inputs["pixel_values"],
    input_ids=inputs["input_ids"],
    attention_mask=inputs["attention_mask"],
    image_embeds=None,
    image_embeds_position_mask=inputs["image_embeds_position_mask"],
    use_cache=True,
    max_new_tokens=128,
)

generated_text = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]

Die Variable generated_text enthält nun eine einfache Beschreibung. Diese Beschreibung sieht nun wie folgt aus:

<image>. the, to and of as in I that' for is was- on it with The as at bet he have from by are " you his “ this said not has an ( but had we her they will my or were their): up about out who one all been she can more would It</image><grounding> An image of<phrase> a forest with fog</phrase><object><patch_index_0224><patch_index_1023></object>

Dieser Text ist für uns erstmal nicht direkt klar verständlich, enthält allerdings die relevanten Informationen. Glücklicherweise liefert Microsoft direkt den passenden Post-Processing-Prozess mit, damit wir entsprechenden einen lesbareren Text erhalten können:

kosmos2.py
processed_text = processor.post_process_generation(generated_text, cleanup_and_extract=False)

print(processed_text)

<grounding> An image of<phrase> a forest with fog</phrase><object><patch_index_0224><patch_index_1023></object>

Hier erhalten wir noch eine Textbeschreibung, welche Modelltoken enthält. Dies kann von Vorteil sein wenn Nutzerinnen mehr über die Struktur der Ausgabe wissen wollen. Sollten Nutzerinnen dies nicht wollen, haben wir hier auch noch den passenden Teil Code, welcher uns einen lesbaren Text und die Position und Größe aller Objekte in dem Bild ausgibt:

kosmos2.py
processed_text, entities = processor.post_process_generation(generated_text)

print(processed_text)
print(entities)

An image of a forest with fog

[(‘a forest with fog’, (12, 29), [(0.015625, 0.234375, 0.984375, 0.984375)])]

Nachdem wir gesehen haben, dass dieses Modell auch Bildbeschreibungen erstellen kann, gehen wir nun zur Bildsegmentierung über. Hierfür nutzen wir die untere Zeile der Ausgabe.

Image Segmentation

Für die Bildsegmentierung, welche wir gleich anhand des Beispiels von oben durchführen werden, haben wir den Quellcode von der Quelle 5 genutzt. Hierfür definieren wir die Funktionen und wenden diese anschließend auf unser Beispielbild an.

kosmos2.py
def is_overlapping(rect1, rect2):
    x1, y1, x2, y2 = rect1
    x3, y3, x4, y4 = rect2
    return not (x2 < x3 or x1 > x4 or y2 < y3 or y1 > y4)
kosmos2.py
draw_entity_boxes_on_image(image, entities, show=False, save_path="Kosmos-Images/test-image-modified.jpeg")
kosmos2.py
def draw_entity_boxes_on_image(image, entities, show=False, save_path=None):
    """_summary_
    Args:
        image (_type_): image or image path
        collect_entity_location (_type_): _description_
    """

    image_h = image.height
    image_w = image.width
    image = np.array(image)[:, :, [2, 1, 0]]

    if len(entities) == 0:
        return image

    new_image = image.copy()
    previous_bboxes = []
    text_size = 1
    text_line = 1
    box_line = 3
    text_spaces = 3

    (c_width, text_height), _ = cv2.getTextSize("F", cv2.FONT_HERSHEY_COMPLEX, text_size, text_line)
    base_height = int(text_height * 0.675)
    text_offset_original = text_height - base_height

    for entity_name, (start, end), bboxes in entities:
        for (x1_norm, y1_norm, x2_norm, y2_norm) in bboxes:
            orig_x1, orig_y1, orig_x2, orig_y2 = int(x1_norm * image_w), int(y1_norm * image_h), int(x2_norm * image_w), int(y2_norm * image_h)

            # random color
            color = tuple(np.random.randint(0, 255, size=3).tolist())
            new_image = cv2.rectangle(new_image, (orig_x1, orig_y1), (orig_x2, orig_y2), color, box_line)

            l_o, r_o = box_line // 2 + box_line % 2, box_line // 2 + box_line % 2 + 1

            x1 = orig_x1 - l_o
            y1 = orig_y1 - l_o

            if y1 < text_height + text_offset_original + 2 * text_spaces:
                y1 = orig_y1 + r_o + text_height + text_offset_original + 2 * text_spaces
                x1 = orig_x1 + r_o

            # add text background
            (text_width, text_height), _ = cv2.getTextSize(f"  {entity_name}", cv2.FONT_HERSHEY_COMPLEX, text_size, text_line)
            text_bg_x1, text_bg_y1, text_bg_x2, text_bg_y2 = x1, y1 - (text_height + text_offset_original + 2 * text_spaces), x1 + text_width, y1

            for prev_bbox in previous_bboxes:
                while is_overlapping((text_bg_x1, text_bg_y1, text_bg_x2, text_bg_y2), prev_bbox):
                    text_bg_y1 += (text_height + text_offset_original + 2 * text_spaces)
                    text_bg_y2 += (text_height + text_offset_original + 2 * text_spaces)
                    y1 += (text_height + text_offset_original + 2 * text_spaces)

                    if text_bg_y2 >= image_h:
                        text_bg_y1 = max(0, image_h - (text_height + text_offset_original + 2 * text_spaces))
                        text_bg_y2 = image_h
                        y1 = image_h
                        break

            alpha = 0.5
            for i in range(text_bg_y1, text_bg_y2):
                for j in range(text_bg_x1, text_bg_x2):
                    if i < image_h and j < image_w:
                        if j < text_bg_x1 + 1.35 * c_width:
                            # original color
                            bg_color = color
                        else:
                            # white
                            bg_color = [255, 255, 255]
                        new_image[i, j] = (alpha * new_image[i, j] + (1 - alpha) * np.array(bg_color)).astype(np.uint8)

            cv2.putText(
                new_image, f"  {entity_name}", (x1, y1 - text_offset_original - 1 * text_spaces), cv2.FONT_HERSHEY_COMPLEX, text_size, (0, 0, 0), text_line, cv2.LINE_AA
            )
            # previous_locations.append((x1, y1))
            previous_bboxes.append((text_bg_x1, text_bg_y1, text_bg_x2, text_bg_y2))

    pil_image = Image.fromarray(new_image[:, :, [2, 1, 0]])
    
    if save_path:
        pil_image.save(save_path)
    if show:
        pil_image.show()

    return new_image

Zugrunde liegende Grafik von Jay Mantri - https://unsplash.com/@jaymantri

In diesem Bild sehen wir nun einen Rahmen um unseren Wald, welcher den Namen “Wald mit Nebel” trägt - eine passende Beschreibung des Inhalts dieses Bilds.

Ergebnisse des Modells

Im Folgenden möchten wir nun einmal ein paar unserer Experimente mit diesem Modell präsentieren.

Originales BildModifiziertes Bild
Grafik von 3darts renders - https://unsplash.com/@3d_arts
Originales BildModifiziertes Bild
Grafik von Dan Asaki - https://unsplash.com/@danasaki
Originales BildModifiziertes Bild
Grafik von Daniel Ramírez - https://unsplash.com/@danramirez1998
Originales BildModifiziertes Bild
Grafik von Filip Mroz - https://unsplash.com/@mroz
Originales BildModifiziertes Bild
Grafik von Francesco Ungaro - https://unsplash.com/@francesco_ungaro
Originales BildModifiziertes Bild
Grafik von Icons8 Team - https://unsplash.com/@icons8
Originales BildModifiziertes Bild
Grafik von Igor Omilaev - https://unsplash.com/@omilaev
Originales BildModifiziertes Bild
Grafik von Jaromír Kavan - https://unsplash.com/@jerrykavan
Originales BildModifiziertes Bild
Grafik von kameli̯ə - https://unsplash.com/@camelieinpic
Originales BildModifiziertes Bild
Grafik von Maksym Mazur - https://unsplash.com/@withmazur
Originales BildModifiziertes Bild
Grafik von Maria Teneva - https://unsplash.com/@miteneva
Originales BildModifiziertes Bild
Grafik von Nadzeya Matskevich - https://unsplash.com/@nadzeya1104
Originales BildModifiziertes Bild
Grafik von Olga Deeva - https://unsplash.com/@loniel
Originales BildModifiziertes Bild
Grafik von Red Zeppelin - https://unsplash.com/@redzeppelin
Originales BildModifiziertes Bild
Grafik von Shubham Dhage - https://unsplash.com/@theshubhamdhage
Originales BildModifiziertes Bild
Grafik von Sophie Gerrie - https://unsplash.com/@sophiegerrie
Originales BildModifiziertes Bild
Grafik von Volodymyr M - https://unsplash.com/@huzhewseh

Unserer Meinung nach liefert dieses Modell gute Ergebnisse. Es gibt jedoch einige Ausnahmen, die wir uns anders vorgestellt hätten:

  1. In diesem Bild, in diesem Bild und in diesem Bild hätten wir uns gewünscht, dass auch der Berg eine eigene Box erhält.
  2. In diesem Bild hätten wir uns gewünscht, dass die Häuser einzeln geboxt worden wären.

Anwendungsfelder

Einige praktische Anwendungen der Bildsegmentierung umfassen: 1 2 3

  1. Inhaltsbasierte Bildsuche
  2. Computer Vision
  3. Medizinische Bildgebung, einschließlich volumengerenderter Bilder aus Computertomographie, Magnetresonanztomographie und Volumenelektronenmikroskopie
  4. Lokalisierung von Tumoren und anderen Pathologien
  5. Messung des Gewebevolumens
  6. Diagnose, Untersuchung der anatomischen Struktur
  7. Operationsplanung
  8. Simulation einer virtuellen Operation
  9. Navigation innerhalb der Operation
  10. Strahlentherapie
  11. Objekterkennung

TL;DR

Bildsegmentierungstechniken reichen von der einfachen, intuitiven heuristischen Analyse bis zur hochmodernen Implementierung von Deep Learning. Herkömmliche Bildsegmentierungsalgorithmen verarbeiten visuelle Merkmale jedes Pixels auf hoher Ebene, wie Farbe oder Helligkeit, um Objektgrenzen und Hintergrundbereiche zu identifizieren. Maschinelles Lernen, das spezielle Datensätze nutzt, wird verwendet, um Modelle zu trainieren, um die spezifischen Arten von Objekten und Regionen, die ein Bild enthält, genau zu klassifizieren. Kosmos2 ist ein solches Modell, welches gute Ergebnisse erzielt. Allerdings wünschen wir uns an der ein oder anderen Stelle hierbei ein wenig mehr Detail, da ab und an Objekte nicht direkt identifiziert werden.

Quellen

Footnotes

  1. ibm.com 2 3

  2. wikipedia.org 2 3

  3. huggingface.co 2

  4. arxiv.org

  5. huggingface.co 2

  6. github.com

  7. medium.com