Python Tutorials & Projekte – Pollux Labs https://polluxlabs.net Arduino, ESP32 & ESP8266 | Projekte & Tutorials Sun, 17 Nov 2024 12:18:35 +0000 de hourly 1 https://wordpress.org/?v=6.6.2 https://polluxlabs.net/wp-content/uploads/2020/05/cropped-pollux-labs-p-32x32.png Python Tutorials & Projekte – Pollux Labs https://polluxlabs.net 32 32 Geheime Botschaften: Verschlüsselte Nachrichten als Audio übertragen https://polluxlabs.net/python-tutorials-und-projekte/geheime-botschaften-verschluesselte-nachrichten-als-audio-uebertragen/ Sun, 17 Nov 2024 12:18:33 +0000 https://polluxlabs.net/?p=17906 Geheime Botschaften: Verschlüsselte Nachrichten als Audio übertragen Weiterlesen »

]]>
Nachrichten zu versenden, die Ende-zu-Ende-verschlüsselt sind, gehört mittlerweile zum Standard vieler Nachrichten-Apps wie Signal, Threema und WhatsApp. Aber wie wäre es mit etwas spielerischem Retro-Charme? In diesem Projekt wandelst du Textnachrichten in Töne um und versendest sie als Audio-Dateien im Anhang einer E-Mail. Der Empfänger kann diese Audio-Dateien dann mit Hilfe eines zuvor zwischen euch vereinbarten Schlüsselworts entschlüsseln und lesen. Nicht Eingeweihte hören nur eine Abfolge von Tönen, wie in diesem Beispiel:

Zum Einsatz kommen hierbei zwei Python-Scripte – je eines für den Sender und den Empfänger. Als E-Mail-Provider dient Gmail.

Gmail für den Versand der E-Mails einrichten

Zunächst benötigst du einen E-Mail-Provider, den du aus dem Python-Script des Senders ansteuern und für den Versand der E-Mails nutzen kannst. Hier bietet sich Googles Gmail an, da die Einrichtung unkompliziert ist. Wichtig: Falls du bereits eine Mail-Adresse bei Gmail besitzt, richte dir für dieses Projekt trotzdem eine neue ein. So stellst du sicher, dass zum Beispiel ein fehlerhaftes Versenden von vielen E-Mails hintereinander zu einer vorübergehenden Sperrung deines Kontos führt.

Wie du eine E-Mail-Adresse bei Gmail und sie für den Versand aus einem Python-Script einrichtest, erfährst du in diesem Tutorial.

Die benötigten Python-Bibliotheken

Im Folgenden verwendest du die Bibliotheken numpy und scipy. Die numpy-Bibliothek wird später verwendet, um numerische Operationen durchzuführen, die für die Analyse der Frequenzen in den Audiodaten benötigt werden. Die scipy-Bibliothek enthält die Funktion wavfile.read, die verwendet wird, um die erzeugten WAV-Datei einzulesen und die Audiodaten sowie die Abtastrate zu extrahieren. Diese Bibliotheken sind nicht standardmäßig in Python enthalten und müssen daher manuell installiert werden. Um sie zu installieren, verwenden Sie den folgenden Befehl:

pip install numpy scipy

Das Script für den Sender der verschlüsselten Nachrichten

Wenn du nun eine E-Mail-Adresse bei Gmail eingerichtet und die beiden benötigten Bibliotheken installiert hast, kann es direkt weitergehen mit dem Python-Script für den Sender. Hier der vollständige Code:

___STEADY_PAYWALL___

# Verschlüsselte Nachrichten - Script für den Sender
# Pollux Labs, polluxlabs.net

import numpy as np
from scipy.io.wavfile import write
import smtplib
from email.message import EmailMessage
import socket

# Parameter, die vom Benutzer bearbeitet werden müssen
user_parameters = {
    "sample_rate": 44100,  # Abtastrate (Hz)
    "bit_duration": 0.1,   # Dauer eines Bits (in Sekunden)
    "freq_0": 1000,        # Frequenz für "0" (Hz)
    "freq_1": 2000,        # Frequenz für "1" (Hz)
    "encryption_key": "geheimer_schluessel",  # Verschlüsselungsschlüssel (beide Parteien müssen denselben Schlüssel verwenden)
    "sender_email": "Absender-Adresse",  # Absender-E-Mail-Adresse
    "sender_password": "App-Passwort",        # App-Passwort für die Absender-E-Mail
    "receiver_email": "Empfänger-Adresse",      # Empfänger-E-Mail-Adresse
    "email_subject": "Betreff",   # Betreff der E-Mail
    "email_body": "Inhalt der E-Mail, z.B. Hier kommt eine verschlüsselte Nachricht für dich.",  # E-Mail-Inhalt
    "wav_filename": "message.wav"           # Name der zu speichernden WAV-Datei
}

# Funktion zur Erstellung eines Tons für ein Bit
def generate_tone(frequency, duration, sample_rate):
    # Erzeugt eine Zeitachse von 0 bis zur angegebenen Dauer mit der entsprechenden Anzahl an Samples
    t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
    # Berechnet den Sinuswert für die gegebene Frequenz über die Zeitachse
    return np.sin(2 * np.pi * frequency * t)

# Nachricht in Binärdaten umwandeln
def text_to_binary(text):
    # Wandelt jeden Buchstaben der Nachricht in eine 8-Bit Binärdarstellung um
    binary_data = ''.join(format(ord(char), '08b') for char in text)
    return binary_data

# Nachricht mit dem Schlüssel verschlüsseln
def encrypt_message(text, key):
    encrypted_message = ""
    for i in range(len(text)):
        encrypted_char = chr(ord(text[i]) ^ ord(key[i % len(key)]))
        encrypted_message += encrypted_char
    return encrypted_message

# Nachricht in modulierte Audiodaten umwandeln
def encode_to_audio(binary_data, bit_duration, sample_rate, freq_0, freq_1):
    # Initialisiert ein leeres Array für die Audiodaten
    audio = np.array([])
    # Iteriert durch jedes Bit der Binärdaten
    for bit in binary_data:
        # Erzeugt einen Ton für "0" oder "1" und fügt ihn an das Audioarray an
        if bit == '0':
            audio = np.append(audio, generate_tone(freq_0, bit_duration, sample_rate))
        else:
            audio = np.append(audio, generate_tone(freq_1, bit_duration, sample_rate))
    return audio

# Funktion zum Versenden der WAV-Datei per E-Mail
def send_email_with_attachment(receiver_email, subject, body, attachment_path):
    # Absender-E-Mail und Passwort
    sender_email = user_parameters["sender_email"]
    sender_password = user_parameters["sender_password"]

    # Erstellen der E-Mail-Nachricht
    msg = EmailMessage()
    msg['From'] = sender_email
    msg['To'] = receiver_email
    msg['Subject'] = subject
    msg.set_content(body)

    # Anhang hinzufügen (die WAV-Datei)
    with open(attachment_path, 'rb') as attachment:
        msg.add_attachment(attachment.read(), maintype='audio', subtype='wav', filename=attachment_path)

    try:
        # SMTP-Server einrichten und die E-Mail senden
        with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
            smtp.login(sender_email, sender_password)  # Anmelden am SMTP-Server
            smtp.send_message(msg)  # E-Mail senden
    except socket.gaierror:
        print("Fehler: Der SMTP-Server konnte nicht erreicht werden. Bitte überprüfen Sie die Serveradresse.")
    except smtplib.SMTPAuthenticationError:
        print("Fehler: Authentifizierung fehlgeschlagen. Bitte überprüfen Sie Ihre E-Mail-Adresse und Ihr Passwort.")
    except Exception as e:
        print(f"Ein unerwarteter Fehler ist aufgetreten: {e}")

# Hauptprogramm
if __name__ == "__main__":
    # Nachricht erstellen
    email_message = "Das Pferd frisst keinen Gurkensalat."
    
    # Nachricht verschlüsseln
    encrypted_message = encrypt_message(email_message, user_parameters["encryption_key"])
    
    # Verschlüsselte Nachricht in Binärdaten umwandeln
    binary_data = text_to_binary(encrypted_message)
    print(f"Binärdaten der Nachricht: {binary_data[:64]}...")  # Zeigt die ersten 64 Bits der Nachricht (für Debugging)
    
    # Binärdaten in Audiosignale umwandeln
    audio_data = encode_to_audio(binary_data, user_parameters["bit_duration"], user_parameters["sample_rate"], user_parameters["freq_0"], user_parameters["freq_1"])
    
    # WAV-Datei speichern
    wav_filename = user_parameters["wav_filename"]
    # Speichert die Audiodaten als 16-Bit Integer in eine WAV-Datei
    write(wav_filename, user_parameters["sample_rate"], (audio_data * 32767).astype(np.int16))
    print(f"WAV-Datei '{wav_filename}' erfolgreich erstellt!")

    # WAV-Datei per E-Mail versenden
    send_email_with_attachment(user_parameters["receiver_email"], user_parameters["email_subject"], user_parameters["email_body"], wav_filename)
    print(f"WAV-Datei '{wav_filename}' erfolgreich per E-Mail versendet!")

So funktioniert das Script

Das Sender-Script verschlüsselt eine Nachricht, wandelt sie in Binärdaten um und erzeugt daraus eine Audiodatei, die dann per E-Mail verschickt wird:

  1. Variablen, die bearbeitet werden müssen: Zu Beginn und auch an einer Stelle weiter unten im Code gibt es Einstellungen, die du vorab unbedingt vornehmen musst. Dazu gehören der geheime Schlüssel (den der Empfänger in seinem Script auch hinterlegen muss), die E-Mail-Adressen, das Passwort aus Gmail und natürlich die zu verschlüsselnde Nachricht selbst.
"encryption_key": "geheimer_schluessel",  # Schlüssel (beide Parteien müssen denselben Schlüssel verwenden)
"sender_email": "Absender-Adresse",  # Absender-E-Mail-Adresse
"sender_password": "App-Passwort",        # App-Passwort für die Absender-E-Mail
"receiver_email": "Empfänger-Adresse",      # Empfänger-E-Mail-Adresse
"email_subject": "Betreff",   # Betreff der E-Mail
"email_body": "Inhalt der E-Mail, z.B. Hier kommt eine verschlüsselte Nachricht für dich.",  # E-Mail-Inhalt
"wav_filename": "message.wav"           # Name der zu speichernden WAV-Datei
 
email_message = "Das Pferd frisst keinen Gurkensalat."  # Die eigentliche Textnachricht, die verschlüsselt und versendet wird
  1. Nachricht mit dem Schlüssel verschlüsseln Die Funktion encrypt_message() verwendet eine einfache XOR-Verschlüsselung, um die Nachricht zu verschlüsseln. Dabei wird jedes Zeichen der Nachricht mit einem Zeichen des Schlüssels kombiniert:
   def encrypt_message(text, key):
       encrypted_message = ""
       for i in range(len(text)):
           encrypted_char = chr(ord(text[i]) ^ ord(key[i % len(key)]))
           encrypted_message += encrypted_char
       return encrypted_message

Diese Methode sorgt dafür, dass sowohl der Sender als auch der Empfänger denselben Schlüssel benötigen, um die Nachricht zu entschlüsseln.

  1. Nachricht in Binärdaten umwandeln Nachdem die Nachricht verschlüsselt wurde, wird sie in Binärdaten umgewandelt, um sie später als Audio darstellen zu können:
   def text_to_binary(text):
       binary_data = ''.join(format(ord(char), '08b') for char in text)
       return binary_data

Jedes Zeichen der Nachricht wird in seine 8-Bit-Binärdarstellung konvertiert, sodass die gesamte Nachricht als eine Folge von Nullen und Einsen dargestellt wird.

  1. Erstellen eines Tons für jedes Bit Die Funktion generate_tone() erstellt einen Sinuston für ein einzelnes Bit (entweder “0” oder “1”). Diese Töne werden später aneinandergereiht, um die gesamte Nachricht in Audiodaten darzustellen:
   def generate_tone(frequency, duration, sample_rate):
       t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
       return np.sin(2 * np.pi * frequency * t)

Hierbei wird entweder eine Frequenz für “0” oder eine andere für “1” verwendet, um die Bits der Nachricht zu unterscheiden.

  1. Nachricht in Audiodaten kodieren Die Funktion encode_to_audio() wandelt die gesamte Binärnachricht in Audiodaten um, indem sie für jedes Bit den entsprechenden Ton erzeugt und diese aneinanderreiht:
   def encode_to_audio(binary_data, bit_duration, sample_rate, freq_0, freq_1):
       audio = np.array([])
       for bit in binary_data:
           if bit == '0':
               audio = np.append(audio, generate_tone(freq_0, bit_duration, sample_rate))
           else:
               audio = np.append(audio, generate_tone(freq_1, bit_duration, sample_rate))
       return audio

Das Ergebnis ist eine Audiodatei, die die verschlüsselte Nachricht repräsentiert.

  1. Erstellen und Versenden der Audiodatei Nachdem die Audiodaten erstellt wurden, wird die Nachricht als .wav-Datei gespeichert und per E-Mail versendet:
   write(wav_filename, sample_rate, (audio_data * 32767).astype(np.int16))

Diese Zeile speichert die Audiodaten als 16-Bit-Integer-Werte in einer WAV-Datei auf deinem Computer, die dann mit der Funktion send_email_with_attachment() per E-Mail versendet wird.

Ergänze das Script nun um deine Daten und hinterlege die Nachricht, die du versenden möchtest. Lass anschließend das Script einmal laufen – im Terminal solltest du die Nachricht lesen können, dass die E-Mail mit der Audio-Datei an deinen Empfänger gesendet wurde:

Und das war es für den Sender – nun zur anderen Seite, dem Empfänger deiner verschlüsselten Nachricht.

Das Script für den Empfänger

Der Empfänger der Nachricht benötigt also ein eigenes Script, das es ihm ermöglicht, die verschlüsselten Audiodaten wieder in Text umzuwandeln. Hier das vollständige Python-Script:

# Verschlüsselte Nachrichten - Script für den Sender
# Pollux Labs, polluxlabs.net

import numpy as np
from scipy.io.wavfile import read

# Parameter, die vom Benutzer bearbeitet werden müssen
user_parameters = {
    "sample_rate": 44100,  # Abtastrate (Hz)
    "bit_duration": 0.1,   # Dauer eines Bits (in Sekunden)
    "freq_0": 1000,        # Frequenz für "0" (Hz)
    "freq_1": 2000,        # Frequenz für "1" (Hz)
    "encryption_key": "geheimer_schluessel",  # Verschlüsselungsschlüssel (beide Parteien müssen denselben Schlüssel verwenden)
    "wav_filename": "message.wav"         # Name der zu lesenden WAV-Datei
}

# Funktion zum Dekodieren der Audiodaten in Binärdaten
def decode_audio_to_binary(audio_data, bit_duration, sample_rate, freq_0, freq_1):
    bit_length = int(sample_rate * bit_duration)
    binary_data = ""

    for i in range(0, len(audio_data), bit_length):
        segment = audio_data[i:i + bit_length]
        # Frequenz analysieren, um festzustellen, ob es sich um ein "0"- oder "1"-Bit handelt
        fft_result = np.fft.fft(segment)
        freqs = np.fft.fftfreq(len(segment), 1 / sample_rate)
        peak_freq = abs(freqs[np.argmax(np.abs(fft_result))])

        if abs(peak_freq - freq_0) < abs(peak_freq - freq_1):
            binary_data += "0"
        else:
            binary_data += "1"

    return binary_data

# Binärdaten in Text umwandeln
def binary_to_text(binary_data):
    text = ""
    for i in range(0, len(binary_data), 8):
        byte = binary_data[i:i + 8]
        if len(byte) == 8:
            text += chr(int(byte, 2))
    return text

# Nachricht entschlüsseln
def decrypt_message(encrypted_text, key):
    # Nachricht entschlüsseln, indem der Schlüssel mit den ursprünglichen Daten kombiniert wird (XOR)
    decrypted_message = ""
    for i in range(len(encrypted_text)):
        decrypted_char = chr(ord(encrypted_text[i]) ^ ord(key[i % len(key)]))
        decrypted_message += decrypted_char
    return decrypted_message

# Hauptprogramm
if __name__ == "__main__":
    # WAV-Datei lesen
    sample_rate, audio_data = read(user_parameters["wav_filename"])
    if audio_data.ndim > 1:
        audio_data = audio_data[:, 0]  # Falls Stereo, nur einen Kanal verwenden
    audio_data = audio_data / 32767.0  # Normalisieren auf den Bereich [-1, 1]

    # Audiodaten in Binärdaten dekodieren
    binary_data = decode_audio_to_binary(audio_data, user_parameters["bit_duration"], user_parameters["sample_rate"], user_parameters["freq_0"], user_parameters["freq_1"])
    print(f"Binärdaten der Nachricht: {binary_data[:64]}...")  # Zeigt die ersten 64 Bits der Nachricht (für Debugging)

    # Binärdaten in verschlüsselten Text umwandeln
    encrypted_message = binary_to_text(binary_data)

    # Nachricht entschlüsseln
    decrypted_message = decrypt_message(encrypted_message, user_parameters["encryption_key"])
    print(f"Entschlüsselte Nachricht: {decrypted_message}")

Auch hier gibt es Parameter, die eingestellt werden können – oder müssen:

user_parameters = {
    "sample_rate": 44100,  # Abtastrate (Hz)
    "bit_duration": 0.1,   # Dauer eines Bits (in Sekunden)
    "freq_0": 1000,        # Frequenz für "0" (Hz)
    "freq_1": 2000,        # Frequenz für "1" (Hz)
    "encryption_key": "geheimer_schluessel",  # Verschlüsselungsschlüssel (beide Parteien müssen denselben Schlüssel verwenden)
    "wav_filename": "message.wav"         # Name der zu lesenden WAV-Datei
}

Allen voran natürlich der geheime Schlüssel: Dieser muss unbedingt mit jenem übereinstimmen, den der Sender in seinem Script zum Verschlüsseln verwendet hat.

Aber auch die Parameter sample_rate, bit_duration und die Frequenzen müssen mit den Einstellungen des Senders übereinstimmen. Der Dateiname der wav_filename muss dem Namen der per E-Mail empfangenen Audio-Datei entsprechen – also vor im Script angepasst werden, bevor es ausgeführt wird.

So funktioniert das Script

Das Empfänger-Script liest also die Audiodatei, dekodiert die darin enthaltene Nachricht und entschlüsselt sie. Hier die einzelnen Schritte:

  1. WAV-Datei lesen Das Script beginnt mit dem Einlesen der Audiodatei mithilfe der Funktion scipy.io.wavfile.read(). Dabei wird die Abtastrate und die Audiodaten extrahiert:
   sample_rate, audio_data = read(user_parameters["wav_filename"])
   if audio_data.ndim > 1:
       audio_data = audio_data[:, 0]  # Falls Stereo, nur einen Kanal verwenden
   audio_data = audio_data / 32767.0  # Normalisieren auf den Bereich [-1, 1]

Diese Normalisierung ist notwendig, um die Audiodaten auf einen Bereich zwischen -1 und 1 zu skalieren.

  1. Audiodaten in Binärdaten dekodieren Die Funktion decode_audio_to_binary() analysiert die Audiodaten und konvertiert sie zurück in eine Binärfolge. Dabei wird die Fourier-Transformation verwendet, um die Frequenzen der einzelnen Segmente zu analysieren und zu entscheiden, ob es sich um ein Bit “0” oder “1” handelt:
   def decode_audio_to_binary(audio_data, bit_duration, sample_rate, freq_0, freq_1):
       bit_length = int(sample_rate * bit_duration)
       binary_data = ""

       for i in range(0, len(audio_data), bit_length):
           segment = audio_data[i:i + bit_length]
           fft_result = np.fft.fft(segment)
           freqs = np.fft.fftfreq(len(segment), 1 / sample_rate)
           peak_freq = abs(freqs[np.argmax(np.abs(fft_result))])

           if abs(peak_freq - freq_0) < abs(peak_freq - freq_1):
               binary_data += "0"
           else:
               binary_data += "1"

       return binary_data

Diese Funktion durchläuft die Audiodaten in Segmenten und bestimmt für jedes Segment, ob es sich um eine “0” oder “1” handelt.

  1. Binärdaten in Text umwandeln Nachdem die Audiodaten in Binärdaten umgewandelt wurden, werden diese in den ursprünglichen Text konvertiert. Hierbei wird jeder 8-Bit-Block in ein Zeichen umgewandelt:
   def binary_to_text(binary_data):
       text = ""
       for i in range(0, len(binary_data), 8):
           byte = binary_data[i:i + 8]
           if len(byte) == 8:
               text += chr(int(byte, 2))
       return text

So wird der verschlüsselte Text aus den Binärdaten wiederhergestellt.

  1. Nachricht entschlüsseln Die entschlüsselte Nachricht wird mit der Funktion decrypt_message() wieder in den Klartext umgewandelt. Dazu wird derselbe Schlüssel verwendet, der auch beim Verschlüsseln benutzt wurde:
   def decrypt_message(encrypted_text, key):
       decrypted_message = ""
       for i in range(len(encrypted_text)):
           decrypted_char = chr(ord(encrypted_text[i]) ^ ord(key[i % len(key)]))
           decrypted_message += decrypted_char
       return decrypted_message

Diese Methode führt eine XOR-Operation auf jedes Zeichen des verschlüsselten Textes durch, um die ursprüngliche Nachricht wiederherzustellen.

  1. Ergebnis anzeigen Schließlich wird die entschlüsselte Nachricht auf der Konsole ausgegeben:
   print(f"Entschlüsselte Nachricht: {decrypted_message}")

Damit erhält der Empfänger die ursprünglich gesendete Nachricht im Klartext in seinem Terminal:

Falls der Empfänger jedoch einen falschen Schlüssel in seinem Script verwendet, klappt es mit dem Entschlüsseln nicht. So sieht die gleiche Nachricht aus, wenn am Ende des Schlüssels zwei Zeichen fehlen:

Die Nachricht beginnt zwar korrekt, weil der Anfang des Schlüssels mit jenem des Senders übereinstimmt. Sie “zerfällt” dann aber zu Kauderwelsch, da der Schlüssel des Empfängers, wie gesagt, zu kurz ist und also zu früh wieder die ersten Zeichen des Schlüssels verwendet werden. Wenn der Schlüssel überhaupt nicht jenem des Senders entspricht, bleibt die Textnachricht vollständig unlesbar.

Wie geht es weiter?

Du kannst nun also Nachrichten verschlüsselt als Audio versenden und dir einigermaßen sicher sein, dass sie nur jemand entschlüsseln kann, der ein geeignetes Script und vor allem den richtigen Schlüssel dafür besitzt. Wie könnten Verbesserungen aussehen? Du hast vielleicht schon bemerkt, dass die erzeugten WAV-Dateien recht groß sind – die relative kurze Nachricht aus dem Beispiel oben hat bereits 2,6 MB.

Hier könnte eine Konvertierung in das MP3-Format weiterhelfen, um sicherzugehen, dass deine Nachricht nicht zu groß für den Anhang einer E-Mail ist.

]]>
Berechne den nächsten Überflug der ISS https://polluxlabs.net/python-tutorials-und-projekte/berechne-den-naechsten-ueberflug-der-iss/ Sun, 25 Aug 2024 19:17:18 +0000 https://polluxlabs.net/?p=17023 Berechne den nächsten Überflug der ISS Weiterlesen »

]]>
In diesem Tutorial erfährst du, wie den nächsten Überflug der ISS mit Python berechnest. Auf Pollux Labs gibt es bereits zwei Projekte, die sich mit der International Space Station auseinandersetzen: Ein Raspberry Pi Projekt, mit dem du die Flugbahn der ISS auf einer Karte darstellst und ein eine Erweiterung der LEGO ISS, die bei der Passage der Raumstation aufleuchtet.

Letzteres Projekt basierte auf einer API, die die Überflugsdaten für einen beliebigen Standort bereitstellen konnte. Leider wurde der Betrieb dieser API eingestellt, weswegen du diese Berechnung am besten selbst vornimmst – wie, lernst du hier.

Die Koordinaten für deinen Standort ermitteln

Um zu berechnen, wann die ISS über deinem Kopf fliegt (oder zumindest theoretisch sichtbar ist), benötigst du zunächst die Koordinaten für deinen Standort. Hierfür eignet sich z.B. die Website geoplaner.de – trage hier deinen Standort ein und du erhältst umgehend die zugehörigen Koordinaten (zum Herauskopieren eignet sich der gelbe Kasten):

Koordinaten für deinen Standort, um den Überflug der ISS zu berechnen

Im obigen Fall wären das für Karlsruhe circa 49° nördliche Breite und 8,4° östliche Länge. Diese Zahlen benötigst du später im Python-Script für die Berechnung des Überflugs bzw. der Sichtbarkeit der ISS.

Die benötigte Python-Bibliothek

Um den Überflug der ISS zu ermitteln, benötigst du die Bibliothek ephem, die im Terminal wie folgt installierst:

pip install ephem

Diese Bibliothek bietet umfangreiche Funktionen für astronomische Beobachtungen – du kannst damit neben verschiedenen Himmelskörpern wie Planeten, Asteroiden und Kometen auch die Flugbahnen von Satelliten berechnen, dazu gehört im weitesten Sinne auch die ISS. Mehr über dieses großartige Projekt erfährst du auf der offiziellen Webseite.

Die aktuellen TLE-Daten ermitteln

Damit die Bibliothek ephem den Überflug der ISS berechnen kann, benötigt sie neben deinem Standort auch aktuelle Daten der Raumstation. Hierfür kommt ein sogenanntes Two-Line Element zum Einsatz, kurz TLE. Hierbei handelt es sich um ein standardisiertes Format für eine Reihe von Daten eines Flugkörpers in der Umlaufbahn der Erde. Mehr über TLEs erfährst du auf Wikipedia (Englisch).

Um das aktuelle TLE der ISS zu erhalten, eignen sich die beiden Webseiten von ARISS und Celestrak. Auf beiden Seiten findest du die aktuellen Daten für das ISS-Modul Sarja (englisch Zarya). Hier ein Beispiel eines TLE:

ISS (ZARYA)
1 25544U 98067A   24238.20528372  .00032948  00000-0  58135-3 0  9999
2 25544  51.6406 333.3912 0006392 271.4643 173.4301 15.50058100469255

Die beiden Zeilen kannst du von der Webseite kopieren und gleich in dein Script eintragen. Ein wichtiger Hinweis: Das TLE für die Raumstation wird regelmäßig aktualisiert und an die tatsächlichen Begebenheiten der ISS angepasst. Damit deine Berechnung zuverlässige Daten liefert, kopiere am besten die aktuellen Werte in dein Script.

Den nächsten ISS Überflug berechnen

Nun zum Kern des Vorhabens: mit dem folgenden Python-Script berechnest du den nächsten Überflug der ISS:

import ephem

# Koordinaten deines Standorts
latitude = '49'
longitude = '8.4'

# Aktuelles TLE
tle1 = "1 25544U 98067A   24238.20528372  .00032948  00000-0  58135-3 0  9999"
tle2 = "2 25544  51.6406 333.3912 0006392 271.4643 173.4301 15.50058100469255"


# Instanz für deinen Standort erzeugen
observer = ephem.Observer()
observer.lat = latitude
observer.lon = longitude

# Instanz für die ISS erzeugen
iss = ephem.readtle("ISS (ZARYA)", tle1, tle2)

# Höhe deines Standorts (optional) und lokale Zeit einstellen
observer.elevation = 0  # Elevation in meters (optional)
observer.date = ephem.localtime(ephem.now())  # Use current date and time

print("Aktuelle Zeit (lokal):", observer.date)

# Nächsten Überflug berechnen
next_pass = observer.next_pass(iss)

# Daten ausgeben
print("Next pass of the ISS:")
print(f"Date and Time (lokale Zeit): {ephem.localtime(next_pass[0])}")
print(f"Rise (lokale Zeit): {ephem.localtime(next_pass[1])}")
print(f"Maximum Elevation (lokale Zeit): {ephem.localtime(next_pass[2])}")
print(f"Set (lokale Zeit): {ephem.localtime(next_pass[3])}")
print(f"Max Elevation (degrees): {next_pass[4]}")

So funktioniert das Script

Nachdem du die Bibliothek ephem eingebunden hast, hinterlegst du die Koordinaten deines Standorts. Anschließend folgen die Werte des aktuellen TLE. Als nächstes erzeugst du eine Instanz observer, die die Koordinaten deines Standorts enthält sowie eine Instanz für die ISS mit den Werten des TLE.

Zusätzlich zu den Koordinaten kannst du auch die Höhe deines Standorts eintragen. Liegt dieser z.B. 150 Meter über dem Meeresspiegel, trage hier einfach eine 150 ein. In der Zeile darunter stellst du die aktuelle Uhrzeit deiner Zeitzone ein.

Mit all diesen Daten rufst du die Funktion observer.next_pass(iss) auf und speicherst das Ergebnis in der Variablen next_pass. Die Berechnung berücksichtigt also deine Standortdaten in der Instanz observer sowie die TLE-Werte in der Insanz iss.

Zuletzt musst du nur noch die Ergebnisse ausgeben. Hier gibt es allerdings ein kleines Problem: Eigentlich erhältst du nicht nur einen Zeitpunkt, an dem die ISS am Himmel sichtbar ist, sondern auch den Zeitpunkt, an dem sie über den Horizont steigt und wieder dahinter verschwindet. Außerdem berechnet ephem auch den maximalen Winkel der ISS über dem Horizont. Leider gibt es – zumindest bei meinen Tests – nur eine sinnvollen Wert: den Zeitpunkt ihrer maximalen Höhe:

Next pass of the ISS:
Date and Time (lokale Zeit): 2024-08-26 02:50:05.657860
Rise (lokale Zeit): 1900-01-03 17:40:39.115906
Maximum Elevation (lokale Zeit): 2024-08-26 02:54:23.887056
Set (lokale Zeit): 1899-12-31 16:40:30.704498
Max Elevation (degrees): 2024/8/26 00:58:43

Wie du in der obigen Ausgabe siehst, sind die Zeitangaben für Rise und Set (also Aufgang und Untergang) unsinnig. Ebenso der Wert für Max Elevation. Einen guten (und für dein Projekt möglicherweise ausreichenden) Wert findest du jedoch hinter Maximum Elevation (lokale Zeit) – diese Zeitangabe sagt dir, wann der nächste Überflug der ISS an deinem Standort zu sehen ist.

Falls du einen Anhaltspunkt oder eine Lösung für diese Fehler hast, schreib mir gerne an info@polluxlabs.net – ich bin für jeden Hinweis dankbar.

Überprüfung der Ergebnisse

Falls du der Berechnung noch nicht so recht Glauben schenkst, kannst du z.B. eine App auf deinem Smartphone hinzuziehen und dort nachschauen, wo sich die Raumstation gerade befindet und wann du mit dem nächsten Überflug der ISS rechnen kannst. Ich selbst verwende hierfür die kostenlose App SkyView Lite.

Was kannst du damit bauen?

Falls du “nur” den Zeitpunkt für den nächsten Überflug der ISS benötigst, damit du sie am Abend- oder Morgenhimmel beobachten kannst, reicht dir dieses Script vermutlich schon. Falls du jedoch etwas bauen möchtest, könnte die oben verlinkte LEGO ISS interessant für dich sein. Dort habe ich zwar einen ESP8266 verwendet, darauf läuft jedoch kein Python. Stattdessen könntest du einen Raspberry Pi Zero verwenden, der ähnlich klein ist und sich in der aufgebauten Raumstation gut unterbringen lässt.

So könnte das beleuchtete Modell aussehen:

Lego-Set, das leuchtet beim Überflug der ISS

]]>
Codestral und Claude 3.5 Sonnet in VS Code verwenden https://polluxlabs.net/python-tutorials-und-projekte/codestral-und-claude-3-5-sonnet-in-vs-code-verwenden/ Thu, 13 Jun 2024 19:17:51 +0000 https://polluxlabs.net/?p=16572 Codestral und Claude 3.5 Sonnet in VS Code verwenden Weiterlesen »

]]>
Vielleicht kennst du schon den GitHub Copilot – ein Programmier-Assistent, den du z.B. in Visual Studio Code verwenden kannst. Eine Alternative bietet das französische KI-Unternehmen Mistral AI: Codestral – ein Sprachmodell, das auf Programmiersprachen spezialisiert ist.

Codestral kannst du entweder ähnlich wie den Copilot verwenden oder damit chatten, wie du es von ChatGPT gewohnt bist. Aktuell (Juni ’24) bietet Mistral für das Sprachmodell eine Testphase an, sodass du es kostenlos verwenden kannst. Aber auch nach Ende dieser Phase dürften die Preise der API anfallen, die nach Anzahl der tatsächlich verwendeten Token abgerechnet wird – im Gegensatz zu den pauschalen 10$ des GitHub Copilots.

In diesem Tutorial erfährst du, wie du mit Codestral Code erstellen kannst und es in Visual Studio Code einbettest, damit das Modell dir dort bei deinen Projekten zur Seite steht.

Update zu claude 3.5 Sonnet

Kurz nach der Veröffentlichung erschien das Modell Claude 3.5 Sonnet von Anthropic. Dieses Sprachmodell erzielt meiner Meinung noch bessere Ergebnisse. Wie du Claude 3.5 in VS Code einbettest, erfährst du weiter unten in diesem Tutorial.

Das ist Codestral

Ende Mai 2024 hat Mistral AI ihr neuestes Sprachmodell vorgestellt, das auf die Erstellung von Code spezialisiert ist. Codestral beherrscht laut Angaben des Entwicklers über 80 Programmiersprachen, darunter Python, C++, Java und JavaScript. Mit 22 Mrd. Parametern und einen Kontextfenster von 32.000 Token soll es alle anderen bis zur Veröffentlichung verfügbaren Sprachmodelle in vielen Benchmarks übertreffen.

Codestral Benchmark Ergebnisse

Auch wenn es hierbei um keine Quantensprünge im Vergleich zum in den einzelnen Sprachen jeweils dahinter liegenden LLM handelt, ist Codestral doch offensichtlich ein sehr ernstzunehmender Mitspieler.

Das Unternehmen Mistral AI wurde 2023 in Paris gegründet und versteht sich selbst als europäische Alternative zu amerikanischen Anbietern wie OpenAI, Meta oder Google. Die Qualität ihrer Arbeit kann dabei überzeugen – neben dem hier vorgestellten Sprachmodell hat es auch Mixtral 8x7B entwickelt, eins der besten derzeit verfügbaren Large Language Models.

Eine Besonderheit ist dabei die Veröffentlichung als Open Source. Du kannst die Modelle von Mistral AI deshalb zu nichtkommerziellen Zwecken also über Ollama lokal auf deinem eigenen Rechner installieren und nutzen – falls dieser stark genug dafür ist.

Chatten mit Codestral

Um die Fähigkeiten von Codestral zu testen, brauchst du nichts weiter als ein kostenloses Nutzerkonto. Um eines anzulegen, besuche die Webseite von Mistral AI, klicke auf Log in und dann auf Registrieren. Nachdem du deine verwendete E-Mail-Adresse verifiziert hast, musst du einen Workspace anlegen. Vergib einen Namen deiner Wahl und wähle Einzelnutzer (es sei denn du registriert dich als Unternehmen).

Lies und akzeptiere die Nutzungsbedingungen und klicke anschließend auf Workspace erstellen – fertig. Im Menü oben siehst du nun den Punkt Le Chat. Klicke hierauf und es öffnet sich ein Bereich, den du so ähnlich vermutlich bereits von ChatGPT kennst.

Rechts findest du ein Eingabefeld, in das du deine Frage bzw. Anweisung eintragen kannst. Darunter befindet sich ein Dropdown-Menü, in dem du das Sprachmodell einstellst. Wähle hier Codestral aus.

Anschließend kann es gleich mit einem Test weitergehen:

Schreibe einen Sketch für den Arduino, der im Setup "Hello world" im Seriellen Monitor ausgibt.

Und hier das das Ergebnis in Le Chat:

void setup() {
  // Öffne die serielle Verbindung mit einem Baudrate von 9600
  Serial.begin(9600);

  // Schreibe "Hello world" in den Seriellen Monitor
  Serial.println("Hello world");
}

void loop() {
  // Hier ist nichts, da wir nur im Setup eine Nachricht ausgeben wollen
}

Diese einfache Aufgabe hat Codestral also gemeistert. Den Prompt habe ich auf Deutsch geschrieben. In der Dokumentation zum Sprachmodell ist Englisch als Eingabesprache vermerkt – möglicherweise erhältst du auf Englisch bessere Ergebnisse bei komplizierteren Anweisungen, da dein deutschsprachiger Prompt nicht erst übersetzt werden muss.

So weit, so gut. Falls du möchtest, teste hier doch ein paar härtere Nüsse. Beeindruckend ist jedenfalls die Geschwindigkeit, mit der Antworten generiert werden – die scheint mir tatsächlich sogar etwas höher als jene des momentan aktuellen OpenAI-Modells GPT-4o zu sein.

Codestral in Visual Studio Code verwenden

Nun zu einer weiteren Anwendung von Codestral. Du kannst das Modell ähnlich wie den Copilot in Visual Studio Code integrieren, damit es dir dort beim Programmieren zur Seite steht. Das bedeutet, dass du einerseits einen Chat zur Verfügung hast, ähnlich wie jenen in Le Chat auf der Webseite von Mistral AI. Andererseits kannst du direkt mit deinem Sketch oder Script interagieren, indem du Codestral ums Debugging oder eine Ergänzung deines Codes bittest.

Um Codestral in VS Code verwenden zu können, benötigst du zunächst eine Extension bzw. Plugin sowie einen API-Schlüssel von Mistral AI. Wie eingangs erwähnt, ist letzterer aktuell (Juni ’24) innerhalb der Testphase kostenlos. Und die Extension ist natürlich auch kostenlos.

Continue installieren

Öffne zunächst die Bibliothek für die Extensions uns suche nach Continue und installiere die Erweiterung mit einem Klick auf Install.

Continue.dev in VS Code installieren

Öffne nun das Plugin und wähle im ersten Screen Use your API key. Wie vorhin erwähnt, könntest du Codestral auch lokal auf deinem Rechner ausführen, sofern er leistungsstark genug ist. Auf der nächsten Seite kannst du nun im ersten Dropdown-Menü die Mistral API, und im zweiten dann Codestral auswählen.

Anschließend benötigst du den API-Key von Mistral, den du vermutlich noch nicht hast. Mit einem Klick auf Get API Key gelangst du auf die entsprechende Webseite von Mistral:

Codestral Zugang anfordern

Wähle im Menü links Codestral aus und klicke dann rechts auf den Button Zugang anfordern. Anschließend benötigst du eine Handynummer, auf die du einen Code zur Verfizierung zugesendet bekommst. Anschließend kannst du nun den API-Key erstellen, mit einem Klick auf den Button API-Schlüssel erstellen.

Kopiere anschließend den Key und trage ihn in Visual Studio Code in das entsprechende Feld ein. Mit einem Klick auf Done gelangst du auf den letzten Screen der Einrichtung. Wähle dort Free Trial (Codestral) aus und melde dich mit deinem GitHub-Konto an. Falls du noch keines hast, kannst du es dir kostenlos einrichten.

Codestral in Visual STudio Code verwenden

Das wäre nun also geschafft. Zeit für ein paar erste Tests. Für eine bessere Bedienbarkeit von Continue ziehe das Logo in VS Code vom Menü links in die rechte Sidebar. So hast du Zugriff auf den Chat, ohne dass du deinen Code im Hauptbereich verlassen musst.

Probiere es gleich aus, zum Beispiel mit dem Prompt, der auch schon in Le Chat zum Einsatz kam:

Das funktioniert schon mal. Aber das ist natürlich nicht alles: Du solltest einen Tab namens continue_tutorial.py sehen, das dir eine Einführung in das Plugin gibt.

Darin siehst du verschiedene Code-Abschnitte und Anweisungen, die dich mit wichtigen Tastenkombinationen und den Möglichkeiten von Continue und Codestral vertraut machen.

So kannst du zum Beispiel Code markieren (im Tutorial die abgebildete Funktion) und mit der Kombination Cmd + L (Mac) wieder den Bereich rechts öffnen und eine Frage dazu stellen – also zum Beispiel was mit ihr angestellt wird. Die Kombination Cmd + I ermöglicht es dir, Code nach deinen Wünschen ändern zu lassen.

Noch praktischer ist das Debugging. Das Tutorial fordert dich im dritten Teil dazu auf, es auszuführen, was zu einem Fehler führt. Mit Cmd + Shift + R startest du die Fehlersuche, die du wieder im rechten Teil sehen kannst. Die verbesserte Funktion kannst du dann mit einem Klick in das Script einfügen – Problem gelöst.

Claude 3.5 Sonnet in VS Code einbinden

Neben Codestral eignet sich auch das LLM Claude 3.5 Sonnet von Anthropic hervorragend, um dir in Visual Studio Code zur Seite zu stehen. Um dieses Modell zu verwenden, kannst du ebenfalls Continue einsetzen – du musst lediglich deinen API Key von Anthropic und das gewünschte Modell hinterlegen.

Apropos API Key: Falls du noch keines hast, erstelle zunächst einen Account bei Anthropic. Anschließend kannst du einen Key hier erstellen. Hierfür benötigst du jedoch etwas Guthaben, denn deine Kommunikation mit Claude 3.5 wird (wie bei der API von OpenAI) nach den verwendeten Tokens abgerechnet. Das Guthaben von mindestens 5$ kannst du in deinem Konto einzahlen. Auf der Webseite von Anthropic findest du die aktuelle Preisliste für die API.

Um Claude 3.5 in Continue (und damit in VS Code) einzubinden, klicke unten links auf das Plus neben dem aktuell gewählten Modell:

Sprachmodelle in Continue auswählen

Anschließend siehst du eine Auswahl von KI-Anbietern. Wähle dort Anthropic aus. Anschließend siehst du die folgende Eingabemaske:

Trage in das erste Feld deinen API Key von Anthropic ein und wähle darunter irgendein Modell. Aktuell (Juni 24) gibt es dort nur die Modelle der Version 3 zur Auswahl, das wird sich natürlich später noch ändern. Solltest du keine Auswahl für das Modell Claude 3.5 Sonnet sehen, ist das kein Problem – in der config.json wirst du gleich das richtige Modell manuell hinterlegen.

Um diese zu öffnen, klicke auf den Button unten. Dort siehst du nun das neu hinzugefügte Claude-Modell, dass du wie folgt anpassen musst:

Hier noch einmal das momentan aktuelle Modell zum Herauskopieren:

claude-3-5-sonnet-20240620

Neben “title” kannst du den korrekten Namen des Modells eintragen. Und das war es auch schon – wähle im Auswahl-Dropdown von Continue das neue Modell aus und probiere Claude 3.5 Sonnet aus.

Fazit

Codestral und Claude 3.5 Sonnet bieten eine wirkliche Alternative zum GitHub Copilot – sowohl in Sachen Funktionalität, Zuverlässigkeit als auch im Preis. In der Testphase von Codestral sowieso, aber auch danach und für Claude 3.5 sollten die Gebühren beim hobbymäßigen Gebrauch unterhalb der monatlichen 10$ von GitHub liegen. Nähere Informationen zu den Kosten erhältst du in der Preisliste von Mistral und jener von Anthropic.

]]>
Musik mit künstlicher Intelligenz komponieren https://polluxlabs.net/python-tutorials-und-projekte/musik-mit-kuenstlicher-intelligenz-komponieren/ Wed, 17 Apr 2024 08:27:56 +0000 https://polluxlabs.net/?p=16360 Musik mit künstlicher Intelligenz komponieren Weiterlesen »

]]>
Mit KI kannst du mittlerweile eine Vielzahl von Medien erzeugen: natürlich Texte, mit denen alles anfing, aber auch Bilder und Videos. Eine faszinierende Idee war aber auch immer die Komposition von Musik mit künstlicher Intelligenz – eine Kunstform, die uns täglich begleitet und gleichzeitig zutiefst an menschliches Kreativität gebunden zu sein scheint.

Ich finde, das ist sie nach wie vor, auch wenn KI massive Fortschritte in der Erzeugung (Imitation?) von Musik gemacht hat. Wie auch immer man dazu stehen möchte – spannend ist das Thema ohne Frage. In diesem Artikel stelle ich einige Möglichkeiten und interessante Projekte vor.

Musik mit Udio komponieren

Am Anfang vieler KI-Anwendungen steht ein Prompt – so auch beim Tool Udio. Die Webseite dieses Anbieters erinnert auf den ersten Blick etwas an Spotify. Du findest dort zahlreiche, nach Genres sortierte Songs von anderen Nutzern, die du dir vorab schon mal anhören kannst, um herauszufinden, was Udio so leistet, um Musik mit künstlicher Intelligenz zu produzieren.

Musik mit künstlicher Intelligenz auf udio.com komponieren

Wenn du selbst eine Song erstellen (lassen) möchtest, musst du dich zunächst registrieren. Aktuell ist das nur mit einem Google-, Discord- oder X-Konto möglich. Anschließend kannst du im Feld ganz oben deinen Prompt eintragen und mit Klick auf Create die Musikproduktion starten.

Ich habe mit folgendem Prompt versucht, einen “autofahrttauglichen” Softrock-Song zu erstellen:

A softrock song that you would have heard in the 90s while taking a long drive on the highway. Male voice, 70s Walker Brothers influence.

Das Ergebnis kannst du dir hier anhören. Bevor du allerdings einen Song wie diesen mit gut 2 Minuten Länge erstellt hast, gibt es noch etwas mehr zu tun. Udio erstellt zunächst eine Art Preview von etwas mehr als 30 Sekunden. Diesen Schnipsel kannst du dann anschließend erweitern, indem du ein weitere Teile wie ein passendes Intro oder Outro erstellen und “drankleben” lässt. Klicke hierfür neben dem Song auf den Button Extend und wähle die gewünschte Erweiterung.

Das klappt erstaunlich gut, denn einen unnatürlichen Übergang hörst du zwischen den Teilen nicht. Allerdings habe ich es nicht geschafft, dem Song eine richtige Struktur aus Intro, Strophe und Refrain zu geben. Vielmehr führen die Erweiterungen (Sections) das Lied immer weiter in eine Richtung, die kein wirkliches Ziel zu haben scheint. Ein menschlicher Künstler würde hier sicherlich anders vorgehen. Du kannst allerdings auch den sogenannten Manual Mode aktivieren, der dir mehr Möglichkeiten gibt, mit dem zugrundeliegenden Sprachmodell zu interagieren.

In den Songs wird natürlich auch gesungen – auf Stimme und Text kannst du hierbei Einfluss nehmen. Erstere kannst du direkt im Prompt versuchen, näher zu bestimmen. Den gewünschten Gesangstext kannst du (auch hinter dem Button Extend) hinterlegen. Deinem Shoegaze-Track mit vertonten Angeboten von Hornbach steht also nichts mehr im Wege.

Wenn du mit deinem Ergebnis zufrieden bist, kannst du deinen Song auch auf Udio veröffentlichen oder einen Link zum Anhören erstellen und teilen.

Musik mit künstlicher INtelligenz – und einem Plattenspieler

Ein spannendes Projekt zum Thema stammt von Arvind Sanjeev: Hier werden über Druckknöpfe gewünschte Attribute wie Lo-Fi oder Happy und Musikstile wie Dance oder Metal eingestellt. Außerdem kann die Geschwindigkeit und die Länge des Musikstücks vorgegeben werden. Anschließend erstellt das Gerät mit Hilfe von Metas MusicGen einen passenden Track, der dann direkt abgespielt wird. Der Plattenspieler auf der linken Seite kann dann genutzt werden, um den Song vor- oder zurückzuspulen, die Geschwindigkeit zu verändern – oder um darauf zu scratchen.

SPIN Synthesizer mit künstlicher Intelligenz von MusicGen

In der Kiste stecken neben dem Plattenspieler ein Arduino Mega, ein Raspberry Pi – und jede Menge Arbeit. Das Ergebnis ist ein Gerät, das die abstrakte künstliche Intelligenz mit einem haptischen Interface verbindet und sie so nachvollziehbar macht. Ob es praxistauglich für die Musikproduktion ist? Vermutlich nicht. Es ist vielmehr der künstlerische Versuch, neue Technologie in unsere erlernte Lebenswelt “hineinzuholen” und erfahrbar zu machen. Einen ähnlichen Ansatz hat das Wählscheiben-Telefon mit integriertem ChatGPT, das du hier auf Pollux Labs findest.

Weitere Informationen zur Plattenspielerkiste mit MusicGen und seiner Entstehung findest du bei CreativeApplications.Net

]]>
Wie knapp verfehlt uns heute ein Asteroid? https://polluxlabs.net/python-tutorials-und-projekte/wie-knapp-verfehlt-uns-heute-ein-asteroid/ Wed, 21 Feb 2024 10:11:38 +0000 https://polluxlabs.net/?p=16025 Wie knapp verfehlt uns heute ein Asteroid? Weiterlesen »

]]>
Es ist erstaunlich, wie viele Asteroiden täglich an der Erde vorbeifliegen. Wobei “an der Erde vorbei” in der Regel mehrere Millionen Kilometer bedeutet und diese Asteroiden also keine Gefahr für uns bedeuten. Die NASA stellt eine API zur Verfügung, mit deren Hilfe du die nächsten Vorbeiflüge von Asteroiden für ein bestimmtes Datum einsehen kannst.

Hieraus lässt sich ein kleines Projekt bauen: Mit einem Python-Script ermittelst du den Passanten, der heute am knappsten an uns vorbeisaust und gibst seinen Namen sowie die Entfernung in der Konsole aus – oder lässt dich z.B. per E-Mail informieren.

Am 21. Februar 2024 sah es folgendermaßen aus:

Heute fliegt der Asteroid (2024 CL5) mit 1826990 Kilometern Entfernung am knappsten an der Erde vorbei.

Gute 1,8 Millionen Kilometer – klingt viel, ist es aber nach kosmischen Maßstäben eigentlich nicht. Aber immerhin war der Asteroid bei seinem Vorbeiflug immer noch ungefährt 5 Mal so weit von uns entfernt wie unser eigener Mond.

Das Python-Script

Du benötigst nicht viel Code für dieses Projekt. Zentral sind die API, bei der du die aktuellen Daten beziehst sowie das aktuelle Datum, das du in dieser API-Abfrage verwendest.

___STEADY_PAYWALL___

Die NASA betreibt eine Übersicht über ihre APIs – dort findest du unter Asteroids – NeoWs alle Informationen, die du benötigst. Wenn du dieses Projekt regelmäßig einsetzen möchtest, registriere deinen eigenen API-Key bei der NASA. Das kannst du auf der eben verlinkten Webseite machen. Falls du die API nur einmal ausprobieren möchtest, reicht auch der DEMO_KEY.

Hier zunächst das vollständige Python-Script:

import requests
from datetime import datetime

def find_asteroids(json_data):
    nearest_asteroid = None
    nearest_miss_distance = float('inf')
    
    for date in json_data["near_earth_objects"]:
        for asteroid in json_data["near_earth_objects"][date]:
            miss_distance = float(asteroid["close_approach_data"][0]["miss_distance"]["kilometers"])
            if miss_distance < nearest_miss_distance:
                nearest_asteroid = asteroid
                nearest_miss_distance = miss_distance
    
    return nearest_asteroid

# Aktuelles Datum erhalten und im passenden Format formatieren
current_date = datetime.now().strftime('%Y-%m-%d')

# API-URL für die NASA NEO-Daten
api_url = f"https://api.nasa.gov/neo/rest/v1/feed?start_date={current_date}&end_date={current_date}&detailed=false&api_key=DEMO_KEY"


# Anfrage an die API senden und JSON-Daten abrufen
response = requests.get(api_url)
json_data = response.json()

# Finde den Asteroiden mit dem knappsten Vorbeiflug
nearest_asteroid = find_asteroids(json_data)

print("Heute fliegt der Asteroid", nearest_asteroid["name"], "mit", int(float(nearest_asteroid["close_approach_data"][0]["miss_distance"]["kilometers"])), "Kilometern Entfernung am knappsten an der Erde vorbei.")

Hier findest du die URL der API, an die du deine Abfrage sendest:

api_url = f"https://api.nasa.gov/neo/rest/v1/feed?start_date={current_date}&end_date={current_date}&detailed=false&api_key=DEMO_KEY"

Dort eingebaut siehst du das aktuelle Datum als {current_date} – dieses Datum ermittelst und formatierst du wie folgt:

current_date = datetime.now().strftime('%Y-%m-%d')

Mit Hilfe der Bibliothek datetime ermittelst du das heutige Datum und bringst es mit dem Befehl strftime in das Format, das die API der NASA erwartet.

Die Antwort erhältst du im JSON-Format. Für den 21.2.24 sieht diese z.B. so aus. In diesen Daten suchst du nun mit der Funktion find_asteroids(json_data) nach dem Asteroiden, der der Erde am nächsten kommt. Sobald dieser gefunden ist, gibst du seinen Namen und die Entfernung des Vorbeiflugs über einen Print-Befehl aus.

print("Heute fliegt der Asteroid", nearest_asteroid["name"], "mit", int(float(nearest_asteroid["close_approach_data"][0]["miss_distance"]["kilometers"])), "Kilometern Entfernung am knappsten an der Erde vorbei.")

Mehr Informationen über die Asteroiden

In den Daten stecken noch viel mehr Informationen, als jene, die du bisher verwendest hast. Z.B. der geschätzte Durchmesser im Key estimated_diameter sowie seine Geschwindigkeit. Oder auch, ob der besagte Asteroid als gefährlich eingestuft wird – im Key is_potentially_hazardous_asteroid. Was diese Einstufung bedeutet, erfährst du in dieser Erklärung.

Falls du dich also für dieses Thema interessierst, sind deinem Tatendrang wenige Grenzen gesetzt. So könntest du z.B. grafisch darstellen, wie nah ein Asteroid uns in Bezug zu anderen Himmelskörpern kommt. Viel Spaß beim Experimentieren!

]]>
KI-Videos mit Stable Video Diffusion erstellen https://polluxlabs.net/python-tutorials-und-projekte/ki-videos-mit-stable-video-diffusion/ Mon, 27 Nov 2023 10:47:30 +0000 https://polluxlabs.net/?p=15413 KI-Videos mit Stable Video Diffusion erstellen Weiterlesen »

]]>
Auf Pollux Labs konntest du bereits viel über Bildgenerierung mit ChatGPT und deepAI erfahren – aber wie sieht es mit Videos aus? Stable Diffusion hat im November 2023 eine frühe Version einer Software veröffentlicht, die auf Basis eines Ausgangsbilds ein kleines KI-Video erstellen kann. In diesem Tutorial erfährst du, wie das geht.

Ein kurzer Hinweis: Dieses Tutorial behandelt eine frühe Version und ist auf dem Stand Ende November ’23. Wie du weißt, entwickelt sich die KI-Welt rasant – also möglicherweise hat sie sich schon weitergedreht, wenn du diese Zeilen hier liest.

Das kann Stable Video Diffusion

Gegenwärtig kannst du mit Stable Video Diffusion eine kurze Video-Sequenz erstellen, die entweder 14 oder 25 Frames lang ist. Als Ausgangspunkt dient ein einzelnes Bild, das zwingend im Format 576×1024 Pixel vorliegen muss. Künftig ist auch eine Version geplant, die auf Basis eines Textprompts Videos erstellen kann, für die du dich bereits in eine Warteliste eintragen kannst.

Testweise habe ich eine kleine Animation einer Gummiente auf einem Fluss erstellt. Hier das Ergebnis:

Das Ausgangsbild hierfür habe ich mit ChatGPT erstellt (Hier ein Tutorial, wie du per API Bilder mit ChatGPT erzeugen kannst).

So erstellst du ein KI-Video auf Basis eines Bilds

Du findest auf Github das Repository von Stable Video Diffusion. Wenn du Erfahrung mit dem Klonen und Einrichten von Repositorys hast, kannst du lokal auf deinem Computer installieren. In diesem Video auf Youtube erhältst du weitere Information zum Download des benötigten KI-Modells und zu ComfyUI – einer Oberfläche, mit der du Stable Diffusion verwenden kannst.

Für einen ersten Test gibt es jedoch eine einfachere Möglichkeit, die dir viel Zeit spart.

Auf der Webseite von Replicate findest du eine Online-Version von Stable Video Diffusion, mit der du ohne großen Aufwand experimentieren kannst. Du musst lediglich ein Ausgangsbild im erwähnten Format von 576×1024 Pixeln hochladen und für einen ersten Test auf Run klicken. Das Video wird dann direkt in deinem Browser erstellt:

Stable Video Diffusion replicate Ente

Auf der rechten Seite erscheint dann das fertige Video (oder eher eine kurze Animation), die auf Basis des Bilds links erzeugt wurde. Hinweis: Ein von ChatGPT erzeugtes Bild hat im Landscape-Format nicht ganz die richtige Größe für die Video-Generierung. Passe die Auflösung deshalb vor dem Upload manuell an.

Wie du im Video oben siehst, versucht Stable Video Diffusion zu erkennen, was sich auf dem statischen Bild für eine Animation eignen könnte. In unserem Fall ist das natürlich das Wasser des Flusses und die Ente, die darauf schwimmt. Selbst kannst du noch keine Vorgaben machen, was im Video passieren soll – also ob z.B. ein Stück Treibholz ins Bild schwimmt.

Voreingestellt sind 14 Frames, die mit den voreingestellten Frames pro Sekunde ein KI-Video von circa 2 Sekunden Länge ergeben. Du kannst aber die Videolänge auch auf 25 Frames erhöhen. Außerdem kannst du noch die Frames per Second definieren und auch mit weiteren Werten, wie der “Menge” an Bewegung, die im fertigen Video zu sehen sein soll, experimentieren.

Hier das Ergebnis eines Baums im Sturm mit 25 Frames, 15 Frames pro Sekunde und einer motion_bucket_id von 255:

Wie du hier siehst, geht es zwar rund mit den Wolken – der Baum scheint vom Sturm allerdings eher unbeeindruckt zu sein, abgesehen von ein paar herumwehenden Blättern. Hier fehlt einfach noch die Möglichkeit, konkret etwas vorzugeben, das Stable Diffusion dann auch verstehen und umsetzen kann.

Wenn du dein Ergebnis speichern möchtest, kannst du das Video als MP4-Datei herunterladen.

Dass künstliche Intelligenz auch Videos auf Basis konkreter Vorgaben erstellen kann, war eine Frage der Zeit – und Stable Video Diffusion ist sicherlich auch nicht die erste Anwendung dieser Art. Und doch ist das Ergebnis bereits beeindruckend. Die (nahe) Zukunft dürfte noch einige Verbesserungen bereithalten: Längere Videos mit besserer Steuerung, was in ihnen geschehen soll.

]]>
Kochen mit ChatGPT und REWE-Angeboten https://polluxlabs.net/python-tutorials-und-projekte/kochen-mit-chatgpt-und-rewe-angeboten/ Fri, 03 Nov 2023 00:06:20 +0000 https://polluxlabs.net/?p=15215 Kochen mit ChatGPT und REWE-Angeboten Weiterlesen »

]]>
Dass ChatGPT mittlerweile mit einem Bild deines Kühlschrankinhalts kochen kann, ist bekannt. Aber wie wäre es einmal mit einem Gericht, dessen Zutatenliste nur aus Sonderangeboten deines nächstgelegenen REWE-Markts besteht? In diesem Projekt probierst du genau das aus: Du fragst die aktuellen REWE-Angebote per API ab und lässt ChatGPT daraus Rezeptideen erstellen – Kochen mit ChatGPT.

Zum Einsatz kommen hierbei zwei Python-Scripts – das erste, um die ID deines Wunsch-Supermarkts herauszufinden und die zweite für die Abfrage der Angebote und die Erstellung der Rezepte. Wenn du möchtest, kannst du letzteres auch automatisieren: Auf deinem Raspberry Pi könnte ein Cronjob jeden Montag die aktuellen Angebote abrufen und ChatGPT dir daraus sieben Rezepte für die ganze Woche erstellen.

Noch ein Hinweis vorab: Bei diesem Projekt handelt es sich natürlich um eine Spielerei – ob die von ChatGPT vorgeschlagenen Gerichte wirklich schmecken, ist leider nicht so ganz sicher. Aber bei den ersten Tests kam schon ansprechende Speisen heraus, z.B. Süßkartoffel-Kürbis-Auflauf, Mediterrane Hähnchenschenkel mit frischen Kräutern und Zitronen-Butter oder Rouladen nach Landhaus-Art. Sowohl die Zutatenliste auch die Anweisungen zur Zubereitungen klangen nicht abwegig. Ein Versuch ist es allemal Wert – und dieser Versuch erweitert auf jeden Fall deine Fähigkeiten.

Finde die ID deines REWE-Markts heraus

Bevor du die Angebote des REWE-Markts deiner Wahl abrufen kannst, benötigst du den marketCode dieses Markts. Den kannst du ganz leicht mit einem kleinen Python-Script herausfinden:

import requests
import json

# Trage hier deinen Standort ein
search_term = 'Karlsruhe'
url = f'https://www.rewe.de/api/marketsearch?searchTerm={search_term}'

# Stelle die Anfrage an die API.
response = requests.get(url)

# Überprüfe, ob die Anfrage erfolgreich war (HTTP Status Code 200).
if response.status_code == 200:
    # Parse die Antwort als JSON.
    data = response.json()

    # Schön formatierte Ausgabe des JSON.
    print(json.dumps(data, indent=4))
else:
    print('Fehler bei der Anfrage:', response.status_code)

Um die Märkte an deinem Standort zu finden, trage diesen in die Variable search_term ein – in meinem Fall ist das Karlsruhe. Wenn du das Script nun ausführst, erhältst du die Antwort als JSON. Hier die ersten beiden Einträge einer möglichen Antwort der API:

{
        "wwIdent": "831008",
        "isReweDortmund": false,
        "companyName": "REWE Ponzer GmbH & Co. oHG",
        "contactStreet": "Hans - Sachs - Str. 8",
        "contactZipCode": "76133",
        "contactCity": "Karlsruhe",
        "marketHeadline": "REWE Markt",
        "openingInfo": {
            "willOpen": {
                "onDay": 5,
                "at": "07:00"
            }
        }
    },
    {
        "wwIdent": "840913",
        "isReweDortmund": false,
        "companyName": "REWE Christopher Lannert oHG",
        "contactStreet": "Josef-Schofer-Str. 14",
        "contactZipCode": "76187",
        "contactCity": "Karlsruhe",
        "marketHeadline": "REWE Markt",
        "openingInfo": {
            "willOpen": {
                "onDay": 5,
                "at": "07:00"
            }
        }
    },

Gleich der jeweils erste Key wwIdent ist die ID bzw. marketCode, den du später benötigst. Suche dir also den gewünschten Markt aus der Liste heraus und notiere dir die ID.

Aktuelle Angebote finden

Bevor es mit dem nächsten Python-Script losgehen kann, musst du noch die Bibliothek cloudscraper installieren. Diese benötigst du, das die API von REWE eigentlich keine automatisierten Abfragen zulässt. Mit dieser Bibliothek kannst du diese Sperre allerdings umgehen. Achte deshalb bitte darauf, keinen “Unfug” anzustellen und z.B. zahllose Anfragen an die API zu stellen.

Um die Bibliothek zu installieren, gib im Terminal bzw. in der Konsole folgenden Befehl ein:

pip install cloudscraper

Außerdem benötigst du noch die Bibliothek openai, mit der du die API von ChatGPT ansteuern kannst. Diese installierst du wie folgt:

pip install openai

Nun kann es mit dem Script losgehen. Zunächst bindest du die beiden genannten Bibliotheken ein und hinterlegst deine gefundene ID sowie die URL für die Abfrage:

import cloudscraper
from openai import OpenAI

# Deine ID, hier ein Beispiel aus Karlsruhe
market_id = '831008'
# Die Basis-URL der API
url = f'https://mobile-api.rewe.de/api/v3/all-offers?marketCode={market_id}'

Anschließend bereitest du cloudscraper vor, erstellst einen leeren String, in den die gefundenen Sonderangebote geschrieben werden – und erstellst eine Liste der Angebotskategorien, die überhaupt für Rezepte in Frage kommen. Es gibt natürlich auch Angebote in den Kategorien Haushalt, Tierfutter, Spirituosen etc., mit denen wir aber hier nichts anfangen können.

# Erstellen ein Cloudscraper-Objekt
scraper = cloudscraper.create_scraper()

# Stelle die GET-Anfrage
response = scraper.get(url)

# Initialisiere einen leeren String für die Titel der Angebote
titles_string = ''

# Eine Liste der gewünschten Kategorietitel
desired_categories = {
    'Frische & Kühlung',
    'Süßes & Salziges',
    'Obst & Gemüse',
    'Nahrungsmittel',
    'Tiefkühl'
}

Nun fehlt nur noch die eigentliche Abfrage. Hier stellst du sicher, dass in der Variablen titles (für die Namen der angebotenen Artikel) nur jene aus den vorgegebenen Kategorien gespeichert werden.

# Überprüfe  den Statuscode der Antwort
if response.status_code == 200:
    # Wenn der Statuscode 200 ist, war die Anfrage erfolgreich
    # Konvertiere die Antwort in JSON
    data = response.json()
    
    # Extrahiere die Angebote, die den gewünschten Kategorietiteln entsprechen
    titles = [
        offer['title']
        for category in data['categories']
        for offer in category['offers']
        if 'rawValues' in offer and 'categoryTitle' in offer['rawValues']
        and offer['rawValues']['categoryTitle'] in desired_categories
    ]
    
    # Erstelle einen String mit den gefilterten Titeln, getrennt durch Kommas
    titles_string = ', '.join(titles)
    
    # Ausgabe des Strings
    print("Gefilterte Titel:", titles_string)
else:
    # Wenn der Statuscode nicht 200 ist, gab es ein Problem mit der Anfrage
    print(f'Fehler: {response.status_code}')

Rezepte erstellen lassen mit ChatGPT

Nun folgt der zweite Teil des Scripts. Hier fragst du ChatGPT über die API nach Rezeptideen, die auf den gefundenen Sonderangeboten basieren. Hierfür benötigst du einen API-Key von OpenAI. In diesem Tutorial erfährst du, wie du dir den benötigten Key erstellst.

Du hinterlegst im Script also deinen Key und erstellst gleich danach die Abfrage:

client = OpenAI(
  api_key="DEIN API-KEY",
)

print("Ich erstelle Gerichte...")
completion = client.chat.completions.create(
#model="gpt-3.5-turbo", 
model="gpt-4",
messages=[
{"role": "system", "content": "Du bist ein KI-Koch, der aus vorgegebenen Zutaten Rezepte für Gerichte entwirft."},
{"role": "user", "content": "Es folgt eine Liste von Zutaten. Kreiere hieraus 3 Rezepte für leckere Gerichte. Gehe davon aus, dass die Küchen-Basics wie Salz, Pfeffer, Öl, Butter etc. bereits vorhanden sind. Hier die Liste: {}".format(titles_string)}]
)

print(completion.choices[0].message.content)

Du findest im obigen Code zwei Zeilen, mit denen du auswählen kannst, ob du das Modell 3.5 oder die neuere Version 4 verwenden möchtest. Kommentiere einfach die nicht gewünschte Version aus.

Als Anweisung (system) an ChatGPT legst du fest, dass die KI als Ideengeber für Rezepte fungieren soll. Mit dem eigentlichen Prompt (user) legst du dann fest, was du möchtest. Im obigen Beispiel sind es drei Rezepte, für die übliche Zutaten wie Salz und Pfeffer enthalten sein dürfen, auch wenn sie nicht in den Angeboten zu finden sind. An diesen Prompt hängst du dann einfach die Liste der Angebote an.

Hier hast du natürlich einiges an Spielraum. So könntest du z.B. nur vegetarische Gerichte entwerfen lassen und ChatGPT Unverträglichkeiten mitteilen.

Die Antwort der künstlichen Intelligenz sieht dann beispielsweise folgendermaßen aus:

Rezept 1: Rinderrouladen mit Apfel-Rotkohl und Maronen

Zutaten:
- Rinder-Rouladen
- Petersilie
- Rote Tafeläpfel
- REWE Beste Wahl Apfelrotkohl
- REWE Bio Gekochte Maronen

1. Die Rinderrouladen flach ausbreiten, mit Salz und Pfeffer würzen und mit gehackter Petersilie bestreuen. Die Rouladen aufrollen und mit Küchengarn befestigen.
2. Die Rouladen in einem großen Topf mit Öl scharf anbraten und anschließend beiseite stellen.
3. Die Äpfel schälen, vierteln, entkernen und klein schneiden. Zusammen mit dem Apfelrotkohl in den Topf geben und ca. 5 Minuten dünsten.
4. Die Rinderrouladen zurück in den Topf geben und bei niedriger Hitze 60 Minuten köcheln lassen.
5. 10 Minuten vor Ende der Kochzeit die gekochten Maronen hinzufügen.
6. Abschmecken und servieren.

Klingt doch halbwegs plausibel, oder? Eine Beilage wäre vielleicht noch gut und dass der Rotkohl in den gleichen Topf wie die Rouladen soll, ist auch nicht ganz einleuchtend. Auch wenn du die Rezepte nicht 1:1 übernehmen solltest, erhältst du mit diesem Projekt recht brauchbare Ideen für Gerichte, die deinen Geldbeutel schonen. Ich wünsche dir jedenfalls schon einmal guten Appetit!

Hier nun das vollständige Python-Script:

import cloudscraper
from openai import OpenAI

# # Deine ID, hier ein Beispiel aus Karlsruhe
market_id = '831008'
# Die Basis-URL der API
url = f'https://mobile-api.rewe.de/api/v3/all-offers?marketCode={market_id}'

# Erstellen ein Cloudscraper-Objekt
scraper = cloudscraper.create_scraper()

# Stelle die GET-Anfrage
response = scraper.get(url)

# Initialisiere einen leeren String für die Titel der Angebote
titles_string = ''

# Eine Liste der gewünschten Kategorietitel
desired_categories = {
    'Frische & Kühlung',
    'Süßes & Salziges',
    'Obst & Gemüse',
    'Nahrungsmittel',
    'Tiefkühl'
}

# Überprüfe  den Statuscode der Antwort
if response.status_code == 200:
    # Wenn der Statuscode 200 ist, war die Anfrage erfolgreich
    # Konvertiere die Antwort in JSON
    data = response.json()
    
    # Extrahiere die Angebote, die den gewünschten Kategorietiteln entsprechen
    titles = [
        offer['title']
        for category in data['categories']
        for offer in category['offers']
        if 'rawValues' in offer and 'categoryTitle' in offer['rawValues']
        and offer['rawValues']['categoryTitle'] in desired_categories
    ]
    
    # Erstelle einen String mit den gefilterten Titeln, getrennt durch Kommas
    titles_string = ', '.join(titles)
    
    # Ausgabe des Strings
    print("Gefilterte Titel:", titles_string)
else:
    # Wenn der Statuscode nicht 200 ist, gab es ein Problem mit der Anfrage
    print(f'Fehler: {response.status_code}')


# Mit ChatGPT Rezepte erstellen
client = OpenAI(
  api_key="DEIN API-KEY",
)

print("Ich erstelle Gerichte...")
completion = client.chat.completions.create(
#model="gpt-3.5-turbo", 
model="gpt-4",
messages=[
{"role": "system", "content": "Du bist ein KI-Koch, der aus vorgegebenen Zutaten Rezepte für Gerichte entwirft."},
{"role": "user", "content": "Es folgt eine Liste von Zutaten. Kreiere hieraus 3 Rezepte für leckere Gerichte. Gehe davon aus, dass die Küchen-Basics wie Salz, Pfeffer, Öl, Butter etc. bereits vorhanden sind. Hier die Liste: {}".format(titles_string)}]
)

print(completion.choices[0].message.content)
  
]]>
Bilder mit der ChatGPT API erstellen https://polluxlabs.net/python-tutorials-und-projekte/bilder-mit-der-chatgpt-api-erstellen/ Sat, 30 Sep 2023 09:32:09 +0000 https://polluxlabs.net/?p=14601 Bilder mit der ChatGPT API erstellen Weiterlesen »

]]>
Die Welt der künstlichen Intelligenz hat in den letzten Jahren erstaunliche Fortschritte gemacht und ist heute in der Lage, erstaunliche kreative Werke zu schaffen. Eine faszinierende Anwendung ist die Generierung von Bildern mithilfe der ChatGPT API von OpenAI. In diesem Tutorial erfährst du, wie du die API mit Python verwenden kannst, um Bilder zu erstellen.

Bevor es losgeht

Um die ChatGPT API nutzen zu können, benötigst du ein Konto bei OpenAI. Ebenso musst du die benötigte Python-Bibliothek installieren. In diesem Tutorial erfährst du, wie beides funktioniert. Sobald du mit den Vorbereitungen fertig bist, kann es losgehen.

Ein Bild erzeugen

Über die API kannst du mit nur wenigen Zeilen Code ein Bild erzeugen:

from openai import OpenAI

client = OpenAI(
  api_key="DEIN OPENAI API-KEY",
)

response = client.images.generate(
  model="dall-e-3",
  prompt="Eine weiße Siamkatze",
  n=1,
  size="1024x1024",
  quality="standard"
)

image_url = response.data[0].url
print(image_url)

Nachdem du die Bibltiothek eingebunden hast, erstellst du mit der Funktion openai.Image.create() ein Bild. Hierbei sind folgende Parameter im Einsatz:

  • model: Das Modell, das du verwenden möchtest (dall-e-2 oder dall-e-3)
  • prompt: Deine Anweisung, was auf dem Bild zu sehen sein soll (und optional welcher Stil verwendet werden soll)
  • n: Die Anzahl der Bilder
  • size: Die Größe des generierten Bildes (1024×1024, 1024×1792 oder 1792×1024 Pixel)
  • quality: Die Qualität des Bilds (standard oder hd)

In der Variablen image_url wird eine URL gespeichert, hinter der du das fertige Bild findest. Kopiere die URL und öffne sie in einem Browser deiner Wahl – dort siehst du dann das Bild und kannst es herunterladen. Hier das Bild, das mit dem Prompt oben (“Eine weiße Siamkatze”) erstellt wurde:

Eine weiße Siamkatze, Bild erstellt mit der ChatGPT API

Tipps zur Verfeinerung deiner Bilder

Manchmal erhältst du möglicherweise nicht sofort das gewünschte Bild. Hier sind einige Tipps, wie du die Qualität der generierten Bilder verbessern kannst:

  1. Präzise Beschreibungen: Je genauer und detaillierter deine Beschreibung ist, desto besser wird das Ergebnis sein. Gib der künstlichen Intelligenz ganz klare Anweisungen.
  2. Experimentieren mit Parametern: Ändere die Bildgröße, den Stil oder die Anzahl der generierten Bilder, um unterschiedliche Ergebnisse zu erzielen.
  3. Mehrere Versuche: Wenn du mit dem ersten Ergebnis nicht zufrieden bist, probiere es erneut. Die API kann in verschiedenen Anfragen unterschiedliche Bilder erzeugen.

Das kostet ein Bild

Die Nutzung der ChatGPT API ist nicht kostenlos. Auf der Webseite von OpenAI findest du die aktuelle Preisliste. Die Preise für die Erstellung von Bilder findest du unter Image models.

]]>
Die ChatGPT API mit Python verwenden https://polluxlabs.net/python-tutorials-und-projekte/die-chatgpt-api-mit-python-verwenden/ Tue, 12 Sep 2023 20:51:06 +0000 https://polluxlabs.net/?p=14453 Die ChatGPT API mit Python verwenden Weiterlesen »

]]>
ChatGPT im Browser oder als App zu verwenden, hat sich mittlerweile bei einer Vielzahl von Menschen etabliert. Aber selbstverständlich stellt OpenAI auch eine ChatGPT API zur Verfügung, die du ansteuern kannst, um zum Beispiel Texte erstellen oder dir Fragen beantworten zu lassen.

In diesem Tutorial lernst du, wie du

  • dir einen OpenAI Account und den benötigten API Key erstellst
  • mit Python Prompts erstellst und die Antwort von ChatGPT erhältst
  • zwischen den Modellen 3.5 und 4 wechselst
  • ChatGPT präzise Anweisungen gibst, die du nicht in jedem Prompt wiederholen musst

Einen OpenAI Account erstellen

Um die ChatGPT API nutzen zu können, benötigst du einen Account bei OpenAI. Wenn du allerdings bereits den Chatbot nutzt, musst du natürlich kein Extra-Konto erstellen. Besuche diese Webseite, um einen Account zu erstellen oder dich einzuloggen.

Anschließend landest du auf der Startseite. Dort warten eine Vielzahl von Tutorials auf dich, die du aber zunächst links liegen lässt.

ChatGPT Startseite

Einen API Key erstellen

Klicke stattdessen oben rechts auf Personal und wähle den Menüpunkt View API keys. Auf der folgenden Seite findest du den Button Create new secret key. Nach einem Klick hierauf kannst du deinem neuen Key einen (am besten sprechenden) Namen geben:

Ein weiterer Klick auf Create secret key erstellt deinen neuen Key, den du dir direkt herauskopieren und ablegen solltest. Später kannst du den Key nicht mehr aufrufen – allerdings kannst du in diesem Fall einfach einen neuen erstellen.

Zahlungdaten hinterlegen

Die ChatGPT API ist nicht kostenlos – deshalb musst du dein Konto mit einem Betrag deiner Wahl (mindestens jedoch 5 $) aufladen musst. Hierfür stehen dir verschiedene Zahlungsmethoden wie PayPal oder Kreditkarte zur Verfügung.

Bei OpenAI findest du die aktuellen Preise für die Nutzung der API. Sobald dein Konto mit ein paar Dollar aufgeladen ist, kann es direkt mit dem Python Script weitergehen.

Stelle eine Frage mit Python

Wie du bestimmt schon weißt, funktioniert ChatGPT wie eine Art Chatbot – du stellst eine Frage oder gibst eine Anweisung und erhältst darauf eine Antwort. Diese Frage wird auch Prompt genannt. Das folgende Python Script stellt die Verbindung zur ChatGPT API her, übermittelt deinen Prompt und gibt die Antwort aus.

from openai import OpenAI
client = OpenAI(
  api_key="DEIN API KEY",
)

completion = client.chat.completions.create(
  model="gpt-3.5-turbo",
  messages=[
    {"role": "user", "content": "Wie lautet die Antwort auf alle Fragen?"}
  ]
)

print(completion.choices[0].message.content)

In der ersten Zeile bindest du die Bibliothek openai ein. Diese musst du natürlich vorher noch installieren. Führe hierfür zum Beispiel im Terminal folgende Zeile aus:

pip install openai

Ein kleiner Hinweis: Der Code oben funktioniert nur mit Versionen der Bibliothek ab dem 8.11.23 – sollte deine Version älter sein, führe zunächst ein Update mit pip install –upgrade openai durch. Zurück zum Script: Nachdem du die Bibliothek eingebunden hast, hinterlegst du in der Variablen api_key deinen API Key, den du vorhin erstellst hast.

Und noch ein Hinweis: In der offiziellen Dokumentation von openAI werden zwei andere Verfahren vorgeschlagen, um den API-KEY zu hinterlegen. Diese haben bei mir allerdings nicht zuverlässig funktioniert. Falls du sie ausprobieren möchtest, kannst du hier mehr erfahren.

Anschließend folgt die Abfrage mit der Funktion client.chat.ompletions.create(). Hier legst du zunächst das Modell fest, im obigen Beispiel ist das GPT-3.5-turbo. Du kannst seit Juli 2023 auch das bessere Modell GPT-4 verwenden. Aber Achtung: ChatGPT 4 ist aktuell (September 2023) 20 Mal teuerer als ChatGPT 3.5 – du kannst die Preise über den Link oben vergleichen. Die dort aufgelisteten Preise beziehen sich jeweils auf 1.000 Tokens. Laut OpenAI entspricht das ungefähr 750 Wörtern (im Englischen).

Letztlich musst du selbst entscheiden, wie gut die Antworten von ChatGPT innerhalb deines Projekts ausfallen sollen. Wenn du dich für das Modell 4 entscheidest ersetze die entsprechende Zeile im Python Script durch:

model="gpt-4",

Update (Feb. 2024): Mittlerweile gibt es auch ein GPT-4 Turbo, das auf Trainingsdaten bis Dezember 2023 basiert. Dieses Modell kannst du mit “gpt-4-0125-preview” einbinden und verwenden. Weitere Informationen (auch zu kommenden Modellen) findest du hier.

Falls du in deinem Script immer das neueste GPT-4-Modell verwenden möchtest, bietet die ChatGPT API nun hierfür eine Möglichkeit: Verwende einfach das Modell gpt-4-turbo-preview, das stets auf die aktuellste Version verweist. Weitere Informationen hierüber findest du hier.

Der Prompt

Kommen wir zur Frage, die du stellst und dafür an die ChatGPT API sendest. Diese findest du im Script hier:

messages=[
    {"role": "user", "content": "Wie lautet die Antwort auf alle Fragen?"}]
)

Hier definierst du zunächst die Rolle (role), hier also user. Diese Rolle hat die Person, die eine Frage stellt – also genauso wie du es vielleicht vom Browser oder der App gewohnt bist. Dahinter folgt der content, also die eigentliche Frage oder Anweisung.

Nun muss nur noch die Antwort ausgegeben werden:

print(completion.choices[0].message.content)

In deinem Terminal oder Konsole sollte nun die Antwort erscheinen, die du sicherlich auch schon vorher wusstest. 😉

Weitere Rollen für DIE ChatGPT API

Oben hast du die Rolle user verwendet. Du kannst ChatGPT aber auch vor deiner eigentlichen Frage genauere Anweisungen mitgeben und damit versuchen, das System etwas zu “lenken”. Hierfür fügst du vorab etwas mit der Rolle system ein:

messages=[
    {"role": "system", "content": "Du beantwortest Fragen kurz und präzise."},
    {"role": "user", "content": "Wie lautet die Antwort auf alle Fragen?"}]
)

Das ist besonders nützlich, wenn ChatGPT zum Beispiel Antworten in einem bestimmten Format geben soll. Du musst diese Anweisungen also nicht in deinem eigentlichen Prompt unterbringen, sondern kannst sie separat erstellen und verwenden.

Und das war es schon. Du hast nun das grundlegende Python Script, um per API mit ChatGPT zu kommunizieren. Wirf einen Blick in die Raspberry Pi Projekte, um Anwendungsmöglichkeiten zu entdecken. Wenn du dich besonders für den Bereich künstlicher Intelligenz interessierst, wirf doch mal einen Blick in unsere KI-Projekte.

]]>
So erzeugst du KI Bilder mit Python und deepAI https://polluxlabs.net/python-tutorials-und-projekte/so-erzeugst-du-ki-bilder-mit-python-und-deepai/ Fri, 27 Jan 2023 07:21:20 +0000 https://polluxlabs.net/?p=13559 So erzeugst du KI Bilder mit Python und deepAI Weiterlesen »

]]>
Bilder, die von einer künstlichen Intelligenz wie DALL-E oder DeepAI “gemalt” werden, sind in aller Munde. In diesem Tutorial erfährst du, wie du KI Bilder mithilfe eines Python Scripts erzeugst.

Du lädst dir hierfür die aktuelle Schlagzeile der BBC-Nachrichten von einer API und schickst diese an die künstliche Intelligenz von deepai.org – von dort erhältst du eine Illustration der Schlagzeile zurück auf deinen Computer, gemalt in einem Stil deiner Wahl.

Diese APIs benötigst du

In diesem Projekt kommen zwei Services zum Einsatz, die du über deren APIs ansteuerst: NewsAPI und DeepAI. Von ersterer fragst die aktuelle Schlagzeile der BBC ab. Hierfür benötigst du einen API Key, den du nach deiner kostenlosen Registrierung erhältst. Wie das geht, und wo du deinen API Key findest, haben wir in diesem Projekt beschrieben.

Mit DeepAI erzeugst du dann KI Bilder, indem du die Schlagzeile an deren API weiterleitest und als sogenannten Prompt verwendest. Das ist so etwas wie die “Malanweisung”, die du der künstlichen Intelligenz gibst. Hierfür kommt ein Diffusionsmodell zum Einsatz, das der Deutschlandfunk Kultur in diesem Beitrag anschaulich erklärt. Erstaunlich hierbei ist, dass die KI eigentlich kein Bild auf Basis deiner Anweisung erzeugt, sondern vielmehr aus einem großen Rauschen “freilegt”.

Aber zurück zur API von DeepAI. Auch um diese nutzen zu können, benötigst du einen kostenlosen Account dort. Du erhältst anschließend einige Gratis-Credits, die du bei Bedarf auch günstig aufstocken kannst. Nachdem du dein kostenloses Kontingent verbraucht hast, kostet dich ein Bild 5 Cent – ein Betrag, der den Spaß Wert ist, wie wir finden.

Deinen API Key von DeepAI findest du übrigens oben in deinem Profil. Auch diesen wirst du demnächst in deinem Python Script benötigen.

Bibliotheken installieren

Für dein Script benötigst du einige Bibliotheken, die du vielleicht noch nicht installiert hast: requests, newsapi und PIL. Du kannst sie mit diesen Befehlen installieren:

pip install requests
pip install newsapi-python
pip install Pillow

Du benötigst diese drei Bibliotheken für die API-Abfrage bei DeepAI und NewsAPI und um das Bild, das du zurück erhältst zu bearbeiten. Insgesamt importierst du zu Beginn des Scripts folgende Bibliotheken:

import requests
import webbrowser
import json
from newsapi import NewsApiClient
from PIL import Image
import os
import sys
import shutil
import random

Schlagzeilen von newsapi abrufen

Als nächstes besorgst du dir die neuesten Nachrichten von der BBC. Hier kommt die NewsAPI-Bibliothek zum Einsatz, die du gerade importiert hast. (Natürlich kannst du den Request auch anders gestalten.)

# NewsAPI
newsapi = NewsApiClient(api_key='DEIN API-Key von NewsAPI')

# Top-Schlagzeilen der BBC abrufen
headlines = newsapi.get_everything(sources='bbc-news',
                                   language='en',
                                   sort_by='publishedAt')

x = headlines.get('articles')
y = x[0]

# Die längere 'description' der Schlagzeile der Variable prompt zuweisen
print('Ich empfange die neueste BBC-Schlagzeile...')
prompt = y.get('description')

KI Bilder erzeugen

Danach kommt die künstliche Intelligenz ins Spiel. Um etwas Abwechslung ins Spiel zu bringen, bindest du vier verschiedene Stilrichtungen ein (galleries): “Old Style”, Pop Art, Renaissance, Abstrakt. Welcher Stil bei deiner Anfrage zum Einsatz kommt, bestimmst du mit einer Zufallszahl.

Je nachdem, welche Zahl gewürfelt wurde, steuerst du eine andere URL der API an:

# Zufällig eine von vier Stilrichtungen festlegen
randomGallery = random.randint(0,3)

if randomGallery == 0:
    galleryURL = 'https://api.deepai.org/api/old-style-generator'
elif randomGallery == 1:
    galleryURL = 'https://api.deepai.org/api/pop-art-generator'
elif randomGallery == 2:
    galleryURL = 'https://api.deepai.org/api/renaissance-painting-generator'
else:
    galleryURL = 'https://api.deepai.org/api/abstract-painting-generator'

print('Ich verwende den Stil von: ' + galleryURL)

r = requests.post(
    galleryURL,
    data={
        'text': prompt,
    },
    headers={'api-key': 'DEIN API-Key von DeepAI'}
)

url = r.json()
print(url['output_url'])

Wie du im Code oben siehst, dient die Description der BBC-Schlagzeile als prompt, den du in deinem Request an die API übermittelst. Ein mögliches Ergebnis im sogenannten “Old Style” sieht dann so aus:

Prompt: Former Detroit Lions linebacker Jessie Lemonier dies at the age of 25, the National Football League team announce.

DeepAI liefert dir über die API immer eine Collage aus vier quadratischen Bildern zurück. In diesem Python Script schneiden wir das Bild oben links aus und speichern es ab – mit dem Prompt als Dateinamen. Natürlich kannst du es auch unverändert ausschneiden, oder jedes einzelne Quadrat ausschneiden und separat speichern.

# Bild herunterladen
def download_image(url, file_name, headers):
     response = requests.get(url, headers=headers)
     if response.status_code == 200:
        with open(file_name, "wb") as f:
            f.write(response.content)
     else:
        print(response.status_code)

headers = {
    "User-Agent": "Chrome/51.0.2704.103",
}

url = url['output_url']

# Dateinamen = Prompt festlegen
file_name = "{}.jpg".format(prompt)

download_image(url, file_name, headers)

# Bild zuschneiden
print('Ich schneide das Bild zu...')
img = Image.open('{}'.format(file_name))
box = (0, 0, 512, 512)
img = img.crop(box)
img.save('{}'.format(file_name))

Zuletzt bleibt nur noch eins: Das neue Bild zu öffnen und zu präsentieren:

img.show()

Das vollständige Python Script

Hier nun das vollständige Script. Vergiss nicht, deine API Keys von NewsAPI und DeepAi einzutragen, bevor du loslegst.

# Copyright 2023, Pollux Labs
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
# documentation files (the "Software"), to deal in the Software without restriction, including without
# limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
# Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in all copies or substantial portions
# of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
# TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
# 
# https://polluxlabs.net/python/so-erzeugst-du-ki-bilder-mit-python-und-deepai/

import requests
import webbrowser
import json
from newsapi import NewsApiClient
from PIL import Image
import os
import sys
import shutil
import random

# NewsAPI
newsapi = NewsApiClient(api_key='DEIN API-Key von NewsAPI')

# Top-Schlagzeilen der BBC abrufen
headlines = newsapi.get_everything(sources='bbc-news',
                                   language='en',
                                   sort_by='publishedAt')

x = headlines.get('articles')
y = x[0]

# Die längere 'description' der Schlagzeile der Variable prompt zuweisen
print('Ich empfange die neueste BBC-Schlagzeile...')
prompt = y.get('description')


# Bild von DeepAI empfangen

# Zufällig eine von vier Stilrichtungen festlegen
randomGallery = random.randint(0,3)

if randomGallery == 0:
    galleryURL = 'https://api.deepai.org/api/old-style-generator'
elif randomGallery == 1:
    galleryURL = 'https://api.deepai.org/api/pop-art-generator'
elif randomGallery == 2:
    galleryURL = 'https://api.deepai.org/api/renaissance-painting-generator'
else:
    galleryURL = 'https://api.deepai.org/api/abstract-painting-generator'

print('Ich verwende den Stil von: ' + galleryURL)

r = requests.post(
    galleryURL,
    data={
        'text': prompt,
    },
    headers={'api-key': 'DEIN API-Key von DeepAI'}
)

url = r.json()
print(url['output_url'])


print('Ich male dein Bild...')

# Bild herunterladen
def download_image(url, file_name, headers):
     response = requests.get(url, headers=headers)
     if response.status_code == 200:
        with open(file_name, "wb") as f:
            f.write(response.content)
     else:
        print(response.status_code)

headers = {
    "User-Agent": "Chrome/51.0.2704.103",
}

url = url['output_url']

# Dateinamen = Prompt festlegen
file_name = "{}.jpg".format(prompt)

download_image(url, file_name, headers)

# Bild zuschneiden
print('Ich schneide das Bild zu...')
img = Image.open('{}'.format(file_name))
box = (0, 0, 512, 512)
img = img.crop(box)
img.save('{}'.format(file_name))

# Bild anzeigen
img.show()

Bringe das Projekt in dein Wohnzimmer

Zum Schluss noch eine Idee für ein Raspberry Pi Projekt: Verbinde ein quadratisches Display, z.B. das HyperPixel 4.0 Square, mit deinem Raspberry Pi. Beides kannst du in einen Bilderrahmen stecken und das Python Script automatisch bei jedem Boot laufen lassen.

Damit jedoch nicht immer das gleiche Bild im Bilderrahmen steckt, könntest du noch dafür sorgen, dass es z.B. jede Stunde ausgetauscht wird.

Zusammengebaut könnte das Ganze dann so ausschauen:

]]>