Aller au contenu principal

Prompts visuels avancés : composition, éclairage, perspective

Prompts visuels avancés : composition, éclairage, perspective

Un prompt bien structuré est la clé d’un résultat visuel de qualité professionnelle. Cette leçon vous enseigne les techniques avancées de rédaction de prompts visuels, en empruntant le vocabulaire de la photographie, du cinéma et des arts visuels.

Anatomie d’un prompt visuel professionnel

Un prompt avancé se décompose en couches :

from openai import OpenAI
import base64

client = OpenAI()

def prompt_multicouche(
    sujet: str,
    composition: str,
    eclairage: str,
    perspective: str,
    style: str,
    details_techniques: str,
    output: str
):
    """Construit un prompt multicouche pour un contrôle maximal."""
    prompt = (
        f"Sujet : {sujet}. "
        f"Composition : {composition}. "
        f"Éclairage : {eclairage}. "
        f"Perspective : {perspective}. "
        f"Style : {style}. "
        f"Détails techniques : {details_techniques}."
    )

    response = client.images.generate(
        model="gpt-image-1",
        prompt=prompt,
        size="1536x1024",
        quality="high",
        response_format="b64_json"
    )

    data = base64.b64decode(response.data[0].b64_json)
    with open(output, "wb") as f:
        f.write(data)
    print(f"Image avancée : {output}")
    return prompt


prompt_utilise = prompt_multicouche(
    sujet="Architecte travaillant sur des plans dans un atelier lumineux",
    composition="Règle des tiers, sujet au tiers gauche, profondeur avec plans multiples",
    eclairage="Lumière naturelle latérale depuis de grandes fenêtres, ombres douces",
    perspective="Angle légèrement bas (contre-plongée subtile), focale 35mm",
    style="Photographie documentaire éditoriale, tons désaturés chauds",
    details_techniques="Profondeur de champ moyenne, premier plan net, arrière-plan en bokeh léger",
    output="architecte_atelier.png"
)

Maîtriser la composition

La composition détermine comment le regard parcourt l’image.

Règles de composition classiques

from openai import OpenAI
import base64

client = OpenAI()

compositions = {
    "regle_des_tiers": (
        "Composition règle des tiers, sujet positionné à l'intersection "
        "des lignes de force (tiers droit, tiers bas)"
    ),
    "symetrie": (
        "Composition parfaitement symétrique, axe central vertical, "
        "reflets dans l'eau, style Wes Anderson"
    ),
    "diagonale": (
        "Composition en diagonale dynamique, ligne de force du coin "
        "inférieur gauche au coin supérieur droit"
    ),
    "cadre_dans_cadre": (
        "Cadre dans le cadre : sujet vu à travers une arche, "
        "une fenêtre ou un encadrement naturel"
    ),
    "minimaliste": (
        "Composition minimaliste, énorme espace négatif, "
        "sujet petit et isolé dans un vaste environnement"
    ),
}

sujet_base = "Un phare isolé sur une falaise bretonne face à la mer"

for nom, composition in compositions.items():
    prompt = f"{sujet_base}, {composition}, photographie paysage"

    response = client.images.generate(
        model="gpt-image-1",
        prompt=prompt,
        size="1536x1024",
        quality="high",
        response_format="b64_json"
    )

    path = f"composition_{nom}.png"
    data = base64.b64decode(response.data[0].b64_json)
    with open(path, "wb") as f:
        f.write(data)
    print(f"Composition {nom}{path}")

Plans et profondeur

from openai import OpenAI
import base64

client = OpenAI()

prompt_profondeur = (
    "Scène de marché provençal avec trois plans distincts : "
    "premier plan net — étalage de lavande et savons artisanaux, "
    "plan moyen — vendeur et client en conversation, flou léger, "
    "arrière-plan — façades en pierre dorée et platanes, bokeh prononcé. "
    "Photographie avec objectif 50mm f/1.8, profondeur de champ réduite."
)

response = client.images.generate(
    model="gpt-image-1",
    prompt=prompt_profondeur,
    size="1536x1024",
    quality="high",
    response_format="b64_json"
)

data = base64.b64decode(response.data[0].b64_json)
with open("marche_profondeur.png", "wb") as f:
    f.write(data)

Maîtriser l’éclairage

L’éclairage est l’outil le plus puissant pour créer une ambiance.

from openai import OpenAI
import base64

client = OpenAI()

eclairages_avances = {
    "rembrandt": (
        "Éclairage Rembrandt : source unique à 45 degrés, triangle lumineux "
        "sur la joue opposée, ombres profondes et dramatiques"
    ),
    "rim_light": (
        "Contre-jour (rim light) : silhouette soulignée par un halo lumineux, "
        "source directement derrière le sujet, détails dans les ombres"
    ),
    "split": (
        "Éclairage split : moitié du visage éclairée, moitié dans l'ombre, "
        "séparation nette, ambiance mystérieuse et cinématographique"
    ),
    "golden_hour": (
        "Golden hour : lumière dorée rasante, ombres allongées et chaudes, "
        "lens flare subtil, atmosphère douce et nostalgique"
    ),
    "neon": (
        "Éclairage néon urbain : sources multiples rose et cyan, "
        "reflets sur surfaces mouillées, ambiance cyberpunk nocturne"
    ),
    "studio_high_key": (
        "High key studio : éclairage uniformément lumineux, ombres minimales, "
        "fond blanc, atmosphère propre et commerciale"
    ),
}

sujet = "Portrait d'une violoniste concentrée"

for nom, eclairage in eclairages_avances.items():
    prompt = f"{sujet}, {eclairage}"

    response = client.images.generate(
        model="gpt-image-1",
        prompt=prompt,
        size="1024x1536",
        quality="high",
        response_format="b64_json"
    )

    path = f"eclairage_{nom}.png"
    data = base64.b64decode(response.data[0].b64_json)
    with open(path, "wb") as f:
        f.write(data)
    print(f"Éclairage {nom}{path}")

Maîtriser la perspective

La perspective influence la perception du sujet par le spectateur.

from openai import OpenAI
import base64

client = OpenAI()

perspectives = {
    "plongee": (
        "Vue en plongée (angle haut), caméra surplombant la scène, "
        "effet de domination, sujet vu de dessus à 45 degrés"
    ),
    "contre_plongee": (
        "Contre-plongée (angle bas), caméra au niveau du sol regardant vers le haut, "
        "effet de grandeur et de puissance"
    ),
    "aerienne": (
        "Vue aérienne drone, parfaitement verticale (90 degrés), "
        "composition graphique, textures et motifs visibles d'en haut"
    ),
    "worm_eye": (
        "Vue worm's eye, caméra posée au sol, perspective extrême "
        "avec lignes de fuite convergeant vers le ciel"
    ),
    "eye_level": (
        "Vue à hauteur des yeux, naturelle et immersive, "
        "focale 50mm, comme le regard humain"
    ),
}

sujet = "Gratte-ciels modernes en verre et acier"

for nom, perspective in perspectives.items():
    prompt = f"{sujet}, {perspective}, photographie architecturale"

    response = client.images.generate(
        model="gpt-image-1",
        prompt=prompt,
        size="1024x1536" if nom in ["contre_plongee", "worm_eye"] else "1536x1024",
        quality="high",
        response_format="b64_json"
    )

    path = f"perspective_{nom}.png"
    data = base64.b64decode(response.data[0].b64_json)
    with open(path, "wb") as f:
        f.write(data)
    print(f"Perspective {nom}{path}")

Constructeur de prompt avancé

Voici une classe utilitaire pour construire des prompts structurés :

class PromptBuilder:
    """Constructeur de prompts visuels structurés."""

    def __init__(self, sujet: str):
        self.sujet = sujet
        self.layers = {}

    def composition(self, desc: str):
        self.layers["composition"] = desc
        return self

    def eclairage(self, desc: str):
        self.layers["éclairage"] = desc
        return self

    def perspective(self, desc: str):
        self.layers["perspective"] = desc
        return self

    def style(self, desc: str):
        self.layers["style"] = desc
        return self

    def couleurs(self, desc: str):
        self.layers["palette de couleurs"] = desc
        return self

    def atmosphere(self, desc: str):
        self.layers["atmosphère"] = desc
        return self

    def technique(self, desc: str):
        self.layers["technique"] = desc
        return self

    def build(self) -> str:
        parts = [self.sujet]
        for key, value in self.layers.items():
            parts.append(f"{key} : {value}")
        return ". ".join(parts)


# Utilisation
prompt = (
    PromptBuilder("Café artisanal en bord de mer, terrasse avec parasols")
    .composition("Règle des tiers, terrasse au premier plan, mer à l'horizon")
    .eclairage("Fin d'après-midi, lumière dorée rasante, ombres allongées")
    .perspective("Légère plongée, focale 28mm grand angle")
    .style("Photographie lifestyle, tons chauds, film analogue")
    .couleurs("Terracotta, bleu méditerranée, blanc cassé, vert olive")
    .atmosphere("Détendu et méditerranéen, brise marine")
    .technique("Profondeur de champ large, tout net du premier plan à l'infini")
    .build()
)

print(prompt)
# Utilisez ce prompt avec client.images.generate()

Exercice pratique

Utilisez le PromptBuilder pour créer 5 images d’un même lieu (une bibliothèque ancienne) avec des variations systématiques de composition, éclairage et perspective. Comparez les résultats dans un catalogue HTML.