Retour aux projets
Projet SNT - Photographie numérique

Retoucher une photo avec Python

Manipule les pixels d'une image pour créer des effets : négatif, niveaux de gris, filtres de couleur, détection de contours.

2 heures
Intermédiaire
Thème : Photographie numérique

Objectifs pédagogiques

  • Comprendre la représentation des images numériques (pixels, RGB)
  • Manipuler les pixels d'une image avec la bibliothèque PIL
  • Créer des filtres simples (niveaux de gris, négatif, sépia)
  • Modifier la luminosité et le contraste
  • Appliquer des effets de flou et de détection de contours

Prérequis

  • Python avec la bibliothèque Pillow (pip install Pillow)
  • Une image à manipuler (photo personnelle ou image libre de droits)
  • Connaissances de base en Python (boucles, fonctions)

Concepts clés

Modèle RGB

Chaque pixel est défini par 3 valeurs (0-255) : Rouge, Vert, Bleu. (255, 0, 0) = rouge pur, (0, 255, 0) = vert pur.

Niveaux de gris

On calcule la moyenne des 3 composantes : gris = (R + G + B) / 3. On obtient une valeur entre 0 (noir) et 255 (blanc).

Luminosité

On ajoute ou soustrait une valeur à chaque composante RGB pour éclaircir ou assombrir l'image.

Négatif

On inverse chaque composante : nouveau = 255 - ancien. Le noir devient blanc, le rouge devient cyan, etc.

Les étapes du projet

1

Charger et afficher une image

On utilise la bibliothèque PIL (Pillow) pour manipuler les images.

from PIL import Image

# Charger l'image
image = Image.open("photo.jpg")

# Afficher les informations
print(f"Taille : {image.size[0]} x {image.size[1]} pixels")
print(f"Mode : {image.mode}")  # RGB, RGBA, L (gris)...

# Afficher l'image
image.show()

# Accéder aux pixels
pixels = image.load()
largeur, hauteur = image.size

# Lire un pixel (x=100, y=50)
r, g, b = pixels[100, 50]
print(f"Pixel (100, 50) : R={r}, G={g}, B={b}")

Astuce : Tu peux utiliser n'importe quelle image JPG ou PNG. Pour ce projet, une photo de paysage ou un portrait fonctionne bien.

2

Convertir en niveaux de gris

Pour chaque pixel, on calcule la moyenne des composantes RGB.

def niveaux_de_gris(image):
    """Convertit une image en niveaux de gris"""
    # Créer une copie pour ne pas modifier l'originale
    gris = image.copy()
    pixels = gris.load()
    largeur, hauteur = gris.size

    for x in range(largeur):
        for y in range(hauteur):
            r, g, b = pixels[x, y]

            # Moyenne des composantes
            moyenne = (r + g + b) // 3

            # Appliquer le gris
            pixels[x, y] = (moyenne, moyenne, moyenne)

    return gris

# Appliquer le filtre
image_gris = niveaux_de_gris(image)
image_gris.save("photo_gris.jpg")
image_gris.show()

Variante : Pour un gris plus naturel, utilise la formule de luminance :0.299*R + 0.587*G + 0.114*B

3

Créer le négatif

On inverse chaque composante de couleur (255 - valeur).

def negatif(image):
    """Crée le négatif d'une image"""
    neg = image.copy()
    pixels = neg.load()
    largeur, hauteur = neg.size

    for x in range(largeur):
        for y in range(hauteur):
            r, g, b = pixels[x, y]

            # Inverser chaque composante
            pixels[x, y] = (255 - r, 255 - g, 255 - b)

    return neg

# Appliquer le filtre
image_neg = negatif(image)
image_neg.save("photo_negatif.jpg")
image_neg.show()
4

Appliquer un filtre sépia

Le sépia donne un effet "photo ancienne" avec des tons bruns chauds.

def sepia(image):
    """Applique un filtre sépia à une image"""
    sep = image.copy()
    pixels = sep.load()
    largeur, hauteur = sep.size

    for x in range(largeur):
        for y in range(hauteur):
            r, g, b = pixels[x, y]

            # Formules du filtre sépia
            new_r = int(0.393 * r + 0.769 * g + 0.189 * b)
            new_g = int(0.349 * r + 0.686 * g + 0.168 * b)
            new_b = int(0.272 * r + 0.534 * g + 0.131 * b)

            # Limiter à 255
            new_r = min(255, new_r)
            new_g = min(255, new_g)
            new_b = min(255, new_b)

            pixels[x, y] = (new_r, new_g, new_b)

    return sep

# Appliquer le filtre
image_sepia = sepia(image)
image_sepia.save("photo_sepia.jpg")
image_sepia.show()
5

Modifier la luminosité

On ajoute ou soustrait une valeur à chaque composante.

def luminosite(image, valeur):
    """
    Modifie la luminosité d'une image
    valeur > 0 : éclaircit
    valeur < 0 : assombrit
    """
    lum = image.copy()
    pixels = lum.load()
    largeur, hauteur = lum.size

    for x in range(largeur):
        for y in range(hauteur):
            r, g, b = pixels[x, y]

            # Ajouter la valeur et limiter entre 0 et 255
            new_r = max(0, min(255, r + valeur))
            new_g = max(0, min(255, g + valeur))
            new_b = max(0, min(255, b + valeur))

            pixels[x, y] = (new_r, new_g, new_b)

    return lum

# Éclaircir de 50
image_claire = luminosite(image, 50)
image_claire.save("photo_claire.jpg")

# Assombrir de 50
image_sombre = luminosite(image, -50)
image_sombre.save("photo_sombre.jpg")
6

Filtre de couleur unique

Garde uniquement une composante de couleur pour un effet artistique.

def filtre_couleur(image, couleur):
    """
    Garde uniquement une couleur
    couleur : 'rouge', 'vert' ou 'bleu'
    """
    filtre = image.copy()
    pixels = filtre.load()
    largeur, hauteur = filtre.size

    for x in range(largeur):
        for y in range(hauteur):
            r, g, b = pixels[x, y]

            if couleur == 'rouge':
                pixels[x, y] = (r, 0, 0)
            elif couleur == 'vert':
                pixels[x, y] = (0, g, 0)
            elif couleur == 'bleu':
                pixels[x, y] = (0, 0, b)

    return filtre

# Créer les 3 versions
image_rouge = filtre_couleur(image, 'rouge')
image_vert = filtre_couleur(image, 'vert')
image_bleu = filtre_couleur(image, 'bleu')

image_rouge.save("photo_rouge.jpg")
image_vert.save("photo_vert.jpg")
image_bleu.save("photo_bleu.jpg")
7

Créer une mosaïque de tous les effets

Combinons tous nos filtres dans une seule image.

def creer_mosaique(image):
    """Crée une mosaïque avec tous les effets"""
    # Redimensionner pour que ça tienne
    petite = image.resize((image.size[0] // 3, image.size[1] // 3))

    # Appliquer les filtres
    originale = petite.copy()
    gris = niveaux_de_gris(petite)
    neg = negatif(petite)
    sep = sepia(petite)
    claire = luminosite(petite, 50)
    sombre = luminosite(petite, -50)
    rouge = filtre_couleur(petite, 'rouge')
    vert = filtre_couleur(petite, 'vert')
    bleu = filtre_couleur(petite, 'bleu')

    # Créer la mosaïque 3x3
    largeur, hauteur = petite.size
    mosaique = Image.new('RGB', (largeur * 3, hauteur * 3))

    # Placer les images
    images = [originale, gris, neg, sep, claire, sombre, rouge, vert, bleu]
    for i, img in enumerate(images):
        x = (i % 3) * largeur
        y = (i // 3) * hauteur
        mosaique.paste(img, (x, y))

    return mosaique

# Créer et sauvegarder la mosaïque
mosaique = creer_mosaique(image)
mosaique.save("photo_mosaique.jpg")
mosaique.show()

Critères d'évaluation

CritèrePoints
Chargement et sauvegarde d'images2 pts
Filtre niveaux de gris fonctionnel3 pts
Filtre négatif fonctionnel3 pts
Au moins 2 filtres supplémentaires4 pts
Code structuré en fonctions4 pts
Présentation des résultats (mosaïque ou comparaison)4 pts
Total20 pts

Pour aller plus loin

Variante 1 : Détection de contours

Utilise le filtre de Sobel pour détecter les bords dans l'image.

Variante 2 : Flou gaussien

Implémente un effet de flou en moyennant les pixels voisins.

Variante 3 : Pixelisation

Crée un effet "pixel art" en réduisant la résolution.

Variante 4 : Incrustation

Remplace une couleur par une autre image (fond vert).

Pixel