
Immagina di inviare meme o cartoni animati personalizzati invece di quelli da Internet. Quindi, trasforma i tuoi selfie o foto in adesivi divertenti e stilizzati utilizzando il nuovo modello GPT-Image-1 di OpenAI. In questo tutorial, creeremo un generatore di adesivi WhatsApp in Python che applica vari stili artistici, tra cui caricature e filtri in stile Pixar, alle tue immagini.
Imparerai come configurare l’API di modifica delle immagini OpenAI, acquisire o caricare immagini in Colab, definire categorie di testo divertenti e umoristiche o utilizzare il tuo testo ed elaborare tre adesivi in parallelo utilizzando più chiavi API per la velocità. Alla fine, avrai un produttore di adesivi funzionante basato su GPT-Image-1 e istruzioni di testo personalizzate.
Perché GPT-Immagine-1?
Abbiamo valutato diversi modelli di generazione di immagini all’avanguardia, tra cui Gemini 2.0 Flash, Flux e Phoenix, sul Leonardo.ai piattaforma. In particolare, tutti questi modelli hanno avuto difficoltà a rendere correttamente il testo e le espressioni. Ad esempio:
- Quello di Google Gemelli 2.0 L’API image spesso produce parole errate o confuse anche quando vengono fornite istruzioni esatte. Ad esempio, con Gemelli, il testo esatto assomiglia a “Grandi saldi oggi!” e otteniamo risultati come “Big Sale Todai” o parole senza senso casuali.
- Flux offre un’elevata qualità dell’immagine in generale, ma gli utenti segnalano che “ha introdotto rapidamente piccoli errori” in qualsiasi testo renderizzato. Flux commette anche piccoli errori di ortografia o lettere confuse, soprattutto all’aumentare della lunghezza del testo. Per impostazione predefinita, Flux prevede anche generazioni di volti molto simili, ovvero “tutti i volti sembrano uguali” a meno che non sia fortemente vincolato.
- Phoenix è ottimizzato per la fedeltà e l’aderenza immediata, ma come la maggior parte dei modelli di diffusione, visualizza comunque il testo visivamente e può introdurre errori. Abbiamo scoperto che Phoenix poteva generare un adesivo con la dicitura corretta solo sporadicamente e tendeva a ripetere la stessa faccia predefinita per un determinato prompt.
Insieme, queste limitazioni ci hanno portato a svilupparci GPT-Immagine-1. A differenza dei modelli precedenti, GPT-Image-1 incorpora una pipeline di prompt specializzata che applica esplicitamente le modifiche corrette al testo e alle espressioni.
Per saperne di più: Come eseguire il modello Flux?
Come GPT-Image-1 potenzia l’editing delle immagini
GPT-Image-1 è il modello multimodale di punta di OpenAI. Crea e modifica immagini da messaggi di testo e immagini per generare output di immagini di alta qualità. In sostanza, possiamo istruire GPT-Image-1 ad applicare una modifica a un’immagine sorgente in base a un messaggio di testo. Nel nostro caso, utilizziamo le immagini. Modifica l’endpoint API con GPT-Image-1 per applicare filtri divertenti e divertenti e sovrapponi il testo all’input di una foto per creare adesivi.
Il prompt è costruito con cura per applicare un output adatto agli adesivi (PNG 1024×1024). Quindi GPT-Image-1 diventa essenzialmente il creatore di adesivi basato sull’intelligenza artificiale, dove cambierà l’aspetto del soggetto nella foto e aggiungerà testo esilarante.
# Set up OpenAI clients for each API key (to run parallel requests)
clients = (OpenAI(api_key=key) for key in API_KEYS)
Quindi, per questo, creiamo un client OpenAI per chiave API. Con tre chiavi possiamo effettuare tre chiamate API simultanee. Questo approccio multi-chiave e multi-thread utilizza ThreadPoolExecutor. Ci consente di generare 3 adesivi in parallelo per ogni corsa. Quando il codice viene stampato, utilizza “3 chiavi API per la generazione SIMULTANEA”, accelerando notevolmente la creazione dell’adesivo.
Guida passo passo
L’idea di creare il tuo generatore di adesivi AI può sembrare complessa, ma questa guida ti aiuterà a semplificare l’intero processo. Inizierai con la preparazione dell’ambiente in Google Colab, quindi esamineremo l’API, comprenderemo le categorie di frasi, convalideremo il testo, genereremo diversi stili artistici e infine genereremo adesivi in parallelo. Ogni parte è accompagnata da frammenti di codice e spiegazioni in modo da poter seguire facilmente. Ora procediamo con il codice:
Installazione ed esecuzione su Colab
Per generare adesivi, dobbiamo avere la giusta configurazione! Questo progetto utilizzerà le librerie Python PIL E rembg per l’elaborazione di base delle immagini e geni di google verrà utilizzato per l’utilizzo nell’istanza Colab. Il primo passaggio è installare le dipendenze direttamente nel tuo notebook Colab.
!pip install --upgrade google-genai pillow rembg
!pip install --upgrade onnxruntime
!pip install python-dotenv
Integrazione OpenAI e chiavi API
Dopo l’installazione, importa i moduli e configura le chiavi API. Lo script crea un client OpenAI per chiave API. Ciò consente al codice di distribuire le richieste di modifica dell’immagine su più chiavi in parallelo. L’elenco dei clienti viene quindi utilizzato dalle funzioni di generazione degli adesivi.
API_KEYS = ( # 3 API keys
"API KEY 1",
"API KEY 2",
"API KEY 3"
)
"""# Stickerverse
"""
import os
import random
import base64
import threading
from concurrent.futures import ThreadPoolExecutor, as_completed
from openai import OpenAI
from PIL import Image
from io import BytesIO
from rembg import remove
from google.colab import files
from IPython.display import display, Javascript
from google.colab.output import eval_js
import time
clients = (OpenAI(api_key=key) for key in API_KEYS)
Caricamento di immagini e acquisizione della fotocamera (logica)
Ora il passaggio successivo è accedere alla fotocamera per scattare una foto o caricare un file immagine. IL capture_photo()
utilizza JavaScript iniettato in Colab per aprire la webcam e restituire un’immagine catturata image.upload_image()
utilizza il widget di caricamento file di Colab e verifica il file caricato con PIL.
# Camera capture via JS
def capture_photo(filename="photo.jpg", quality=0.9):
js_code = """
async function takePhoto(quality) {
const div = document.createElement('div');
const video = document.createElement('video');
const btn = document.createElement('button');
btn.textContent="📸 Capture";
div.appendChild(video);
div.appendChild(btn);
document.body.appendChild(div);
const stream = await navigator.mediaDevices.getUserMedia({video: true});
video.srcObject = stream;
await video.play();
await new Promise(resolve => btn.onclick = resolve);
const canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0);
stream.getTracks().forEach(track => track.stop());
div.remove();
return canvas.toDataURL('image/jpeg', quality);
}
"""
display(Javascript(js_code))
data = eval_js("takePhoto(%f)" % quality)
binary = base64.b64decode(data.split(',')(1))
with open(filename, 'wb') as f:
f.write(binary)
print(f"Saved: {filename}")
return filename
# Image upload function
def upload_image():
print("Please upload your image file...")
uploaded = files.upload()
if not uploaded:
print("No file uploaded!")
return None
filename = list(uploaded.keys())(0)
print(f"Uploaded: {filename}")
# Validate if it's an image
try:
img = Image.open(filename)
img.verify()
print(f"📸 Image verified: {img.format} {img.size}")
return filename
except Exception as e:
print(f"Invalid image file: {str(e)}")
return None
# Interactive image source selection
def select_image_source():
print("Choose image source:")
print("1. Capture from camera")
print("2. Upload image file")
while True:
try:
choice = input("Select option (1-2): ").strip()
if choice == "1":
return "camera"
elif choice == "2":
return "upload"
else:
print("Invalid choice! Please enter 1 or 2.")
except KeyboardInterrupt:
print("\nGoodbye!")
return None
Produzione:

Esempi di categorie e frasi
Ora creeremo le nostre diverse categorie di frasi da applicare sui nostri adesivi. Pertanto, utilizzeremo un dizionario PHRASE_CATEGORIES che contiene molte categorie, come aziendale, Bollywood, Hollywood, Tollywood, sport, meme e altre. Quando viene scelta una categoria, il codice seleziona casualmente tre frasi uniche per i tre stili di adesivi.
PHRASE_CATEGORIES = {
"corporate": (
"Another meeting? May the force be with you!",
"Monday blues activated!",
"This could have been an email, boss!"
),
"bollywood": (
"Mogambo khush hua!",
"Kitne aadmi the?",
"Picture abhi baaki hai mere dost!"
),
"memes": (
"Bhagwan bharose!",
"Main thak gaya hoon!",
"Beta tumse na ho payega!"
)
}
Categorie di frasi e testo personalizzato
Il generatore utilizza un dizionario di categorie di frasi. L’utente può selezionare una categoria per la selezione casuale della frase o inserire la propria frase personalizzata. Sono inoltre presenti funzioni di supporto per la selezione interattiva, nonché una semplice funzione per convalidare la lunghezza di una frase personalizzata.
def select_category_or_custom():
print("\nChoose your sticker text option:")
print("1. Pick from phrase category (random selection)")
print("2. Enter my own custom phrase")
while True:
try:
choice = input("Choose option (1 or 2): ").strip()
if choice == "1":
return "category"
elif choice == "2":
return "custom"
else:
print("Invalid choice! Please enter 1 or 2.")
except KeyboardInterrupt:
print("\nGoodbye!")
return None
# NEW: Function to get custom phrase from user
def get_custom_phrase():
while True:
phrase = input("\nEnter your custom sticker text (2-50 characters): ").strip()
if len(phrase) < 2:
print("Too short! Please enter at least 2 characters.")
continue
elif len(phrase) > 50:
print("Too long! Please keep it under 50 characters.")
continue
else:
print(f"Custom phrase accepted: '{phrase}'")
return phrase
Per le frasi personalizzate, la lunghezza immessa viene controllata (2–50 caratteri) prima dell’accettazione.
Convalida delle frasi e barriere ortografiche
def validate_and_correct_spelling(text):
spelling_prompt = f"""
Please check the spelling and grammar of the following text and return ONLY the corrected version.
Do not add explanations, comments, or change the meaning.
Text to check: "{text}"
"""
response = clients(0).chat.completions.create(
model="gpt-4o-mini",
messages=({"role": "user", "content": spelling_prompt}),
max_tokens=100,
temperature=0.1
)
corrected_text = response.choices(0).message.content.strip()
return corrected_text
Ora creeremo un campione build_prompt
funzione per impostare alcune istruzioni di livello base per l’agente. Nota anche build_prompt()
chiama il validatore ortografico e quindi incorpora il testo corretto nel prompt dell’adesivo rigoroso:
# Concise Prompt Builder with Spelling Validation
def build_prompt(text, style_variant):
corrected_text = validate_and_correct_spelling(text)
base_prompt = f"""
Create a HIGH-QUALITY WhatsApp sticker in {style_variant} style.
OUTPUT:
- 1024x1024 transparent PNG with 8px white border
- Subject centered, balanced composition, sharp details
- Preserve original facial identity and proportions
- Match expression to sentiment of text: '{corrected_text}'
TEXT:
- Use EXACT text: '{corrected_text}' (no changes, no emojis)
- Bold comic font with black outline, high-contrast colors
- Place text in empty space (top/bottom), never covering the face
RULES:
- No hallucinated elements or decorative glyphs
- No cropping of head/face or text
- Maintain realistic but expressive look
- Ensure consistency across stickers
"""
return base_prompt.strip()
Varianti di stile: caricatura contro Pixar
I tre modelli di stile risiedono in STYLE_VARIANTS. Le prime due sono trasformazioni caricaturali e l’ultima è un look 3D in stile Pixar. Queste stringhe verranno inviate direttamente al generatore di prompt e determineranno lo stile visivo.
STYLE_VARIANTS = ("Transform into detailed caricature with slightly exaggerated facial features...",
"Transform into expressive caricature with enhanced personality features...",
"Transform into high-quality Pixar-style 3D animated character..."
)
Generazione di adesivi in parallelo
Il vero punto di forza del progetto è la generazione parallela degli adesivi. La generazione degli adesivi viene eseguita parallelamente al threading di tutti e tre contemporaneamente, utilizzando chiavi API separate, quindi i tempi di attesa sono drasticamente ridotti.
# Generate single sticker using OpenAI GPT-image-1 with specific client (WITH TIMING)
def generate_single_sticker(input_path, output_path, text, style_variant, client_idx):
try:
start_time = time.time()
thread_id = threading.current_thread().name
print(f"(START) Thread-{thread_id}: API-{client_idx+1} generating {style_variant(:30)}... at {time.strftime('%H:%M:%S', time.localtime(start_time))}")
prompt = build_prompt(text, style_variant)
result = clients(client_idx).images.edit(
model="gpt-image-1",
image=(open(input_path, "rb")),
prompt=prompt,
# input_fidelity="high"
quality = 'medium'
)
image_base64 = result.data(0).b64_json
image_bytes = base64.b64decode(image_base64)
with open(output_path, "wb") as f:
f.write(image_bytes)
end_time = time.time()
duration = end_time - start_time
style_type = "Caricature" if "caricature" in style_variant.lower() else "Pixar"
print(f"(DONE) Thread-{thread_id}: {style_type} saved as {output_path} | Duration: {duration:.2f}s | Text: '{text(:30)}...'")
return True
except Exception as e:
print(f"(ERROR) API-{client_idx+1} failed: {str(e)}")
return False
# NEW: Create stickers with custom phrase (all 3 styles use the same custom text)
def create_custom_stickers_parallel(photo_file, custom_text):
print(f"\nCreating 3 stickers with your custom phrase: '{custom_text}'")
print(" • Style 1: Caricature #1")
print(" • Style 2: Caricature #2")
print(" • Style 3: Pixar Animation")
# Map futures to their info
tasks_info = {}
with ThreadPoolExecutor(max_workers=3, thread_name_prefix="CustomSticker") as executor:
start_time = time.time()
print(f"\n(PARALLEL START) Submitting 3 API calls SIMULTANEOUSLY at {time.strftime('%H:%M:%S', time.localtime(start_time))}")
# Submit ALL tasks at once (non-blocking) - all using the same custom text
for idx, style_variant in enumerate(STYLE_VARIANTS):
output_name = f"custom_sticker_{idx+1}.png"
future = executor.submit(generate_single_sticker, photo_file, output_name, custom_text, style_variant, idx)
tasks_info(future) = {
'output_name': output_name,
'text': custom_text,
'style_variant': style_variant,
'client_idx': idx,
'submit_time': time.time()
}
print("All 3 API requests submitted! Processing as they complete...")
completed = 0
completion_times = ()
# Process results as they complete
for future in as_completed(tasks_info.keys(), timeout=180):
try:
success = future.result()
task_info = tasks_info(future)
if success:
completed += 1
completion_time = time.time()
completion_times.append(completion_time)
duration = completion_time - task_info('submit_time')
style_type = "Caricature" if "caricature" in task_info('style_variant').lower() else "Pixar"
print(f"({completed}/3) {style_type} completed: {task_info('output_name')} "
f"(API-{task_info('client_idx')+1}, {duration:.1f}s)")
else:
print(f"Failed: {task_info('output_name')}")
except Exception as e:
task_info = tasks_info(future)
print(f"Error with {task_info('output_name')} (API-{task_info('client_idx')+1}): {str(e)}")
total_time = time.time() - start_time
print(f"\n (FINAL RESULT) {completed}/3 custom stickers completed in {total_time:.1f} seconds!")
# UPDATED: Create 3 stickers in PARALLEL (using as_completed)
def create_category_stickers_parallel(photo_file, category):
if category not in PHRASE_CATEGORIES:
print(f" Category '{category}' not found! Available: {list(PHRASE_CATEGORIES.keys())}")
return
# Choose 3 unique phrases for 3 stickers
chosen_phrases = random.sample(PHRASE_CATEGORIES(category), 3)
print(f" Selected phrases for {category.title()} category:")
for i, phrase in enumerate(chosen_phrases, 1):
style_type = "Caricature" if i <= 2 else "Pixar Animation"
print(f" {i}. ({style_type}) '{phrase}' → API Key {i}")
# Map futures to their info
tasks_info = {}
with ThreadPoolExecutor(max_workers=3, thread_name_prefix="StickerGen") as executor:
start_time = time.time()
print(f"\n (PARALLEL START) Submitting 3 API calls SIMULTANEOUSLY at {time.strftime('%H:%M:%S', time.localtime(start_time))}")
# Submit ALL tasks at once (non-blocking)
for idx, (style_variant, text) in enumerate(zip(STYLE_VARIANTS, chosen_phrases)):
output_name = f"{category}_sticker_{idx+1}.png"
future = executor.submit(generate_single_sticker, photo_file, output_name, text, style_variant, idx)
tasks_info(future) = {
'output_name': output_name,
'text': text,
'style_variant': style_variant,
'client_idx': idx,
'submit_time': time.time()
}
print("All 3 API requests submitted! Processing as they complete...")
print(" • API Key 1 → Caricature #1")
print(" • API Key 2 → Caricature #2")
print(" • API Key 3 → Pixar Animation")
completed = 0
completion_times = ()
# Process results as they complete (NOT in submission order)
for future in as_completed(tasks_info.keys(), timeout=180): # 3 minute total timeout
try:
success = future.result() # This only waits until ANY future completes
task_info = tasks_info(future)
if success:
completed += 1
completion_time = time.time()
completion_times.append(completion_time)
duration = completion_time - task_info('submit_time')
style_type = "Caricature" if "caricature" in task_info('style_variant').lower() else "Pixar"
print(f"({completed}/3) {style_type} completed: {task_info('output_name')} "
f"(API-{task_info('client_idx')+1}, {duration:.1f}s) - '{task_info('text')(:30)}...'")
else:
print(f"Failed: {task_info('output_name')}")
except Exception as e:
task_info = tasks_info(future)
print(f"Error with {task_info('output_name')} (API-{task_info('client_idx')+1}): {str(e)}")
total_time = time.time() - start_time
print(f"\n(FINAL RESULT) {completed}/3 stickers completed in {total_time:.1f} seconds!")
if len(completion_times) > 1:
fastest_completion = min(completion_times) - start_time
print(f"Parallel efficiency: Fastest completion in {fastest_completion:.1f}s")
Qui, generate_single_sticker()
crea il prompt e chiama le immagini. modifica l’endpoint utilizzando il client_idx specificato. Le funzioni parallele creano un ThreadPoolExecutor con max_workers=3, inviano le tre attività ed elaborano i risultati con as_completed. Ciò consente allo script di registrare rapidamente ogni adesivo finito. Inoltre, possiamo anche visualizzare i log per vedere cosa sta succedendo per ogni thread (ora, cosa era caricatura o stile Pixar).
Blocco di esecuzione principale
In fondo alla sceneggiatura, il __main__
la guardia per impostazione predefinita corre sticker_from_camera()
. Tuttavia, puoi accettare/rimuovere il commento come desideri per eseguire interactive_menu()
, create_all_category_stickers()
o altre funzioni.
# Main execution
if __name__ == "__main__":
sticker_from_camera()
Produzione:
Immagine di uscita:

Per la versione completa di questo codice generatore di adesivi WhatsApp, visita questo GitHub deposito.
Conclusione
In questo tutorial, abbiamo illustrato l’impostazione delle chiamate GPT-Image-1, la creazione di un prompt esteso per gli adesivi, l’acquisizione o il caricamento di immagini, la selezione di frasi divertenti o testo personalizzato e l’esecuzione simultanea di 3 varianti di stile. In poche centinaia di righe di codice, questo progetto converte le tue immagini in adesivi in stile fumetto.
Combinando semplicemente il modello di visione di OpenAI con un po’ di ingegneria creativa e multi-threading, puoi generare adesivi divertenti e personalizzati in pochi secondi. E il risultato sarà un generatore di adesivi WhatsApp basato sull’intelligenza artificiale in grado di produrre adesivi immediatamente condivisibili con un solo clic con qualsiasi amico e gruppo. Ora provalo per la tua foto e la tua battuta preferita!
Domande frequenti
R. Trasforma le tue foto caricate o catturate in divertenti adesivi WhatsApp stilizzati con testo utilizzando il modello GPT-Image-1 di OpenAI.
R. GPT-Image-1 gestisce l’accuratezza del testo e le espressioni facciali meglio rispetto a modelli come Gemini, Flux o Phoenix, garantendo che gli adesivi abbiano parole corrette e immagini espressive.
R. Utilizza tre chiavi API OpenAI e un ThreadPoolExecutor per generare tre adesivi in parallelo, riducendo i tempi di elaborazione.
Accedi per continuare a leggere e goderti i contenuti curati dagli esperti.
Fonte: www.analyticsvidhya.com