Titelbild bunte Farbsplashes kommen aus einem Bildschirm

Das Atelier auf deinem Rechner

Methoden zur Generierung von Bildern mit KI

Von: Dr. Gerhard Heinzerling

Teil 1: Bilder generieren

Bilder aus dem Nichts zu erzeugen wäre wie Gold aus unedlen Metallen zu erschaffen. Wahrscheinlich ist dies nicht möglich. Hat man jedoch schon Bilder zur Verfügung, so lassen sich neue Bilder daraus generieren. Wenn dann noch Beschreibungen der Bilder vorliegen, kann man sogar aus den Texten neue Bilder generieren. Dieser Blogbeitrag zeigt verschiedene Möglichkeiten, wie dies geschehen kann.

Es ist immer sehr praktisch, wenn man fertige Datensätze findet. Glücklicherweise haben Forscher der Chinese University of Hong Kong sich die Mühe gemacht, den Datensatz: „Large-scale CelebFaces Attributes (CelebA)“ zu erstellen.

Der Datensatz verfügt über:

  • 10.177 Identitäten
  • 202.599 Bilder von Gesichtern
  • 40 Attribute, die die Gesichter beschreiben.

Beschreibungen können dabei sein, „trägt eine Brille“, „lächelt“, „Schnurrbart“, „gelocktes Haar“ usw. Die Autoren haben viele Details zu dem Datensatz unter dem Titel „Deep Learning Face Attributes in the Wild” zusammengestellt, der hier gefunden werden kann.
Der Datensatz kann direkt hier heruntergeladen werden.

Der Download des Datensatzes kann auch zur Laufzeit eines Programms geschehen. Der Datensatz ist Teil der Tensorflow-Beispielbibliothek.

import tensorflow_datasets as tfds
import matplotlib.pyplot as plt
import numpy as np
import os

ds_train, ds_info = tfds.load('celeb_a', split='test', shuffle_files=False, with_info=True)

Coding für das automatische Herunterladen des „celeb_a“ Datensatzes.

Mit einem einfachen Befehl lassen sich einige Bilder des Datensatzes anzeigen.

fig = tfds.show_examples(ds_info, ds_train)
9 Beispielbilder generierter Gesichter

Beispielbilder aus dem „celeb_a“-Datensatz.

Teil 2: Ein durchschnittliches Gesicht erzeugen

Da ein Computer von Haus aus keine Bilder kennt, braucht man zunächst eine Reihe von Bildern, um daraus ein neues Bild ableiten zu können. Die Bilder haben wir mit dem celeb_a Datensatz gefunden. Die zu den Bildern gehörigen Attribute lassen sich auch einfach anzeigen:

def sample(req_attribs):
    sample_bool = []
    for i in range(sample_size):
        match = True
        for req_attrib in req_attribs:
            if features['attributes'][req_attrib][i] == False:
                match = False
                break
        sample_bool.append(match)
    return features['image'][np.array(sample_bool, dtype=np.bool)]
list(features['attributes'].keys())
['5_o_Clock_Shadow', 'Arched_Eyebrows', 'Attractive', 'Bags_Under_Eyes', 'Bald', 'Bangs', 'Big_Lips', 'Big_Nose', 'Black_Hair', 'Blond_Hair', 'Blurry', 'Brown_Hair', 'Bushy_Eyebrows', 'Chubby', 'Double_Chin', 'Eyeglasses', 'Goatee', 'Gray_Hair', 'Heavy_Makeup', 'High_Cheekbones', 'Male', 'Mouth_Slightly_Open', 'Mustache', 'Narrow_Eyes', 'No_Beard', 'Oval_Face', 'Pale_Skin', 'Pointy_Nose', 'Receding_Hairline', 'Rosy_Cheeks', 'Sideburns', 'Smiling', 'Straight_Hair', 'Wavy_Hair', 'Wearing_Earrings', 'Wearing_Hat', 'Wearing_Lipstick', 'Wearing_Necklace', 'Wearing_Necktie', 'Young']
Die vierzig Attribute, die die Bilder der Celebrities beschreiben:
['5_o_Clock_Shadow', 'Arched_Eyebrows', 'Attractive', 'Bags_Under_Eyes', 'Bald', 'Bangs', 'Big_Lips', 'Big_Nose', 'Black_Hair', 'Blond_Hair', 'Blurry', 'Brown_Hair', 'Bushy_Eyebrows', 'Chubby', 'Double_Chin', 'Eyeglasses', 'Goatee', 'Gray_Hair', 'Heavy_Makeup', 'High_Cheekbones', 'Male', 'Mouth_Slightly_Open', 'Mustache', 'Narrow_Eyes', 'No_Beard', 'Oval_Face', 'Pale_Skin', 'Pointy_Nose', 'Receding_Hairline', 'Rosy_Cheeks', 'Sideburns', 'Smiling', 'Straight_Hair', 'Wavy_Hair', 'Wearing_Earrings', 'Wearing_Hat', 'Wearing_Lipstick', 'Wearing_Necklace', 'Wearing_Necktie', 'Young']

Aus diesen Bildern lässt sich mit Hilfe des Mittelwertes der Pixel ein neues Bild erzeugen. Dazu werden 2000 Beispielbilder ausgewählt und mit numpy.mean der Mittelwert gebildet.

ds_train = ds_train.batch(2000)
features = next(iter(ds_train.take(1)))
n, h, w, c = features['image'].shape
figure = plt.figure(figsize=(8,6))
sample_images = features['image']
new_img = np.mean(sample_images, axis=0)

plt.imshow(new_img.astype(np.uint8))
plt.axis('off')
plt.show()
„Durchschnittsbild“ aus den 2000 Beispielbildern

Rechts: „Durchschnittsbild“ aus den 2000 Beispielbildern.

Nun lässt sich das Bild durch die Eingabe von Attributen verändern. Legt man etwa die beiden Attribute „Smiling“ und „Blond_Hair“ fest, so verändert sich das Bild einfach dadurch, dass für das Erstellen des neuen Bildes nur Bilder mit den entsprechenden Attributen herangezogen werden.

attributes_dict = {'Smiling':True, 'Blond_Hair':True}
show_attribs = {}

for k, v in attributes_dict.items():
    show_attribs[k] = v
    img = sample_dataset(show_attribs)
    new_img = np.mean(img, axis=0)
    figure = plt.figure(figsize=(5,3.5))

    plt.axis('off')
    plt.imshow(new_img.astype(np.uint8))
    plt.show()
Generierte Bilder Frau lächelnd und Frau lächelnd blond

Neue Bilder: links lächelnd, rechts lächelnd und blond.

So lassen sich neue Bilder aus einer Vielzahl von Beispielbildern erzeugen. Das Ganze lässt sich aber deutlich steigern, indem nicht „nur“ 200.000 Bilder von Gesichtern herangezogen werden, sondern mehreren Millionen Bilder für alle möglichen Klassen von Bildern. Das ist mit dem CLIP-Modell möglich.

Teil 3: CLIP

CLIP steht für Contrastive Language–Image Pre-training. Es wurde zunächst in dem Aufsatz „Learning Transferable Visual Models From Natural Language Supervision“ von Alec Radford et al. vorgestellt.

CLIP

„Learning Transferable Visual Models From Natural Language Supervision.“

(1) Das kontrastive Lernen ist eine Methode, bei der ein Modell lernen soll, ähnliche und unähnliche Merkmale in Datensätzen zu unterscheiden. Texte und Bilder werden enkodiert und miteinander „assoziiert“.

(2) Um mehr Variabilität in das Text-Enkoding zu bringen, werden aus den Labeln kurze Phrasen. Aus dem Eigennamen „pepper“ wird so „pepper the aussie pub“ oder aus „car“ wird „A photo of a car“.

(3) Erstaunlicherweise lassen sich so sogar zero shot Vorhersagen treffen, bei denen Elemente im Bild klassifiziert werden können, die nie in den Trainingsdaten verwendet worden sind.

Wie kannst du das nutzen? Nun, man nimmt etwa den ImageNet-Datensatz, der mit riesigem Aufwand erstellt worden ist und über 25.000 Mitarbeiter erforderte, um 14 Mio. Bilder für 22.000 Objektkategorien zu kommentieren. Es ist leicht nachvollziehbar, welche Kosten dabei entstanden sind.

Im Gegensatz dazu lernt CLIP aus Text-Bild-Paaren, die bereits im Internet öffentlich verfügbar sind. CLIP nutzt dabei über 400 Mio. Bild-Text-Paare. Was StabilityAI nun mit seinem Stable Diffusion Modell daraus macht, schauen wir uns im nächsten Abschnitt an.

Teil 4: Stable Diffusion von Stability AI

Stable Diffusion ist ein großartiges Open-Source-Modell zur Generierung von Bildern aus Texten. Das Modell gibt es in verschiedenen Varianten. Hier wird auf eine Variante eingegangen, die mit der Python-Bibliothek Keras erstellt wurde. Die Funktion von Keras verkapselt allerdings das Innenleben der Funktion, weshalb hier eine graphische Darstellung und eine Beschreibung der verschiedenen Funktionsblöcke dargestellt wird. Die URL zu dem Programm ist hier zu finden.
Zunächst aber der einfache Aufruf des Programms.

!pip install --upgrade keras-cv
import time
import keras_cv
from tensorflow import keras
import matplotlib.pyplot as plt

model = keras_cv.models.StableDiffusion(img_width=512, img_height=512)
images = model.text_to_image("Ein blauer Hase als Aquarellbild", batch_size=3)

def plot_images(images):
    plt.figure(figsize=(20, 20))
    for i in range(len(images)):
        ax = plt.subplot(1, len(images), i + 1)
        plt.imshow(images[i])
        plt.axis("off")

plot_images(images)
Abbildung blauer Hase

Der Benutzer kann selbst mit einer einfachen CPU eigene Bilder generieren, in dem er in der Methode text_to_image eine eigene Texteingabe mitgibt. Wichtig ist, dass hier tatsächlich von „generieren“ gesprochen werden kann, da nicht etwa einfach im Internet nach einem Bild mit einem möglichst ähnlichen „label“ oder „tag“ gesucht wird, sondern tatsächlich ein neues Bild erstellt wird. Wie das geht, sehen wir uns gleich an. Hier zunächst eine Skizze, die zeigt, dass Stable Diffusion kein monolithischer Block ist, sondern in mehrere Komponenten zerlegt werden kann.

Architekt des Stable Diffusion Modells.

  1. Texteingabe und Indizierung mit Hilfe eines Bag of Words
  2. Token Embedding in Vektoren
  3. Einspeisung in das vortrainierte CLIP Modell
  4. Text Encoding als Matrix mit 77 x 768 Zeichen
  5. Noise Prediction via Unet
  6. Das Conditioning mit dem Cross Attention Mechanismus
  7. Generierung des Ergebnisbildes via Superresolution

Im nächsten Blogabschnitt werden die Schritte einzeln genau betrachtet. Fortsetzung folgt.

Dr. Gerhard Heinzerling Profilbild

Über den Autor: Dr. Gerhard Heinzerling

Dr. Gerhard Heinzerling beschäftigt sich seit vielen Jahren mit Künstlicher Intelligenz. Er arbeitet als KI-Berater bei der Firma Arineo GmbH in Göttingen. Bei der heise academy veröffentlicht er dazu interessante Lernvideos.


Diese Beiträge könnten dich auch interessieren: