Aller au contenu

Exercices sur les images

Ces exercices doivent être utilisés pour vous entraîner à programmer. Ils sont généralement accompagnés d'aide et de leur solution pour vous permettre de progresser.

Avant de vous précipiter sur ces solutions dès la première difficulté, n'oubliez pas les conseils suivants :

  • Avez-vous bien fait un schéma au brouillon pour visualiser le problème posé ?
  • Avez-vous essayé de rédiger un algorithme en français, avec vos propres mots, avant de vous lancer dans la programmation sur machine ?
  • Avez-vous utilisé des affichages intermédiaires, des print(), pour visualiser au fur et à mesure le contenu des variables ?
  • Avez-vous testé le programme avec les propositions de tests donnés dans l'exercice ?
  • Avez-vous testé le programme avec de nouveaux tests, différents de ceux proposés ?
Rappels
  • Chaque programme Python doit être sauvegardé sous forme de fichier texte avec l'extension .py.
    Enregistrez ce fichier dans le dossier [B03-Images] avec le nom donné à l'exercice : ProgB03.51.py, ProgB03.52.py, etc...
  • Pour exécuter ce programme, il suffit de le sauvegarder puis d'appuyer sur la touche [F5].

ProgB03.51 - Une seule composante

Feux On considère l'image feux.png ci-contre.

  1. A l'aide d'un clic droit sur cette image, enregistrez-là dans le répertoire [B03-Images].

  2. Copiez/collez et complétez la définition de la fonction composantes() qui crée et sauvegarde une image constituée uniquement des composantes rouge, vert ou bleu de l'image d'origine selon la valeur du paramètre indice.
    Les autres composantes sont mises à zéro.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    from PIL import Image
    
    
    def composantes(source, indice, nom_result):
        """
        source - Image
        indice - int, entier compris entre 0 et 2 (0 -> R, 1 -> G, 2 -> B)
        nom_result - str, nom du fichier image qui sera renvoyé
        Sortie: Image - Nouvelle image de mêmes caractéristiques que la source.
                Seule la composante de numéro indice est conservée,
                les autres sont mises à zéro.
        """
        # TODO
    
    
    if __name__ == '__main__':
    
        # importation de l'image:
        source = Image.open('feux.png')
    
        composantes(source, 0, 'feux_rouge.png')
        composantes(source, 1, 'feux_vert.png')
        composantes(source, 2, 'feux_bleu.png')
    

    Exemples

    L'instruction composantes(source, 0, 'feux_rouge.png') renvoie l'image : Feux rouges

    L'instruction composantes(source, 1, 'feux_vert.png') renvoie l'image : Feux rouges

    L'instruction composantes(source, 2, 'feux_bleu.png') renvoie l'image : Feux rouges

    Une solution
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    from PIL import Image
    
    def composantes(source, indice, nom_result):
        """
        source - Image
        indice - int, entier compris entre 0 et 2 (0 -> R, 1 -> G, 2 -> B)
        nom_result - str, nom du fichier image qui sera renvoyé
        Sortie: Image - Nouvelle image de mêmes caractéristiques que la source.
                Seule la composante de numéro indice est conservée,
                les autres sont mises à zéro.
        """
        # récupération des dimensions de l'image :
        largeur, hauteur = source.size
    
        resultat = Image.new(source.mode, source.size)
    
        for ligne in range(hauteur):
            for colonne in range(largeur):
                r, g, b = source.getpixel( (colonne, ligne) )
                if indice == 0:
                    resultat.putpixel( (colonne, ligne), (r, 0, 0) )
                elif indice == 1:
                    resultat.putpixel( (colonne, ligne), (0, g, 0) )
                else:
                    resultat.putpixel( (colonne, ligne), (0, 0, b) )
        resultat.save(nom_result)
    
    
    if __name__ == '__main__':
    
        # importation de l'image:
        source = Image.open('feux.png')
    
        composantes(source, 0, 'feux_rouge.png')
        composantes(source, 1, 'feux_vert.png')
        composantes(source, 2, 'feux_bleu.png')
    

ProgB03.52 - Rechercher des informations

Dans cet exercice, on utilise à nouveau l'image de l'exercice précédent.

  1. Copiez/collez et complétez le corps de la fonction sommetHaut() en respectant ses spécifications.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    from PIL import Image
    
    def sommetHaut(source):
        """
        source - Image
        Sortie: tuple - couple de coordonnées du premier pixel rencontré de couleur
                distincte de (255, 255, 255).
                L'image est parcourue de haut en bas et de gauche à droite.
                →→→→
                →→→→
                →→→→
        """
    
    
    if __name__ == '__main__':
        # importation de l'image:
        source = Image.open('feux.png')
    
        print(f"Coordonnées du sommet haut du triangle : {sommetHaut(source)}\n")
    

    Une piste

    N'oubliez pas de récupérer les dimensions de l'image dans le code de la fonction sommetHaut()

    Un algorithme
    Parcourir les pixels ligne par ligne de gauche à droite
    S'arrêter dès que l'on a obtenu un pixel dont la couleur n'est pas blanche
    Renvoyer les coordonnées de ce pixel
    
    Une autre piste

    La condition « tant que le pixel est blanc » pourra se traduire par :

    while source.getpixel((colonne,ligne)) == (255,255,255):
    
    colonne et ligne sont deux variables à faire évoluer, colonne entre 0 et largeur-1, ligne entre 0 et hauteur-1 (largeur est la largeur de l'image et hauteur sa hauteur).

    Une solution avec une double boucle for

    On obtient le pixel de coordonnées (249, 20).

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    from PIL import Image
    
    def sommetHaut(source):
        """
        source - Image
        Sortie: tuple - couple de coordonnées du premier pixel rencontré de couleur
                distincte de (255, 255, 255).
                L'image est parcourue de haut en bas et de gauche à droite.
                →→→→
                →→→→
                →→→→
        """
        # récupération des dimensions de l'image :
        largeur, hauteur = source.size
    
        for ligne in range(hauteur):
            for colonne in range(largeur):
                if source.getpixel((colonne,ligne)) != (255,255,255):
                    return (colonne, ligne)
    
    
    if __name__ == '__main__':
        # importation de l'image:
        source = Image.open('feux.png')
    
        print(f"Coordonnées du sommet haut du triangle : {sommetHaut(source)}\n")
    

    Une solution avec une boucle while

    On obtient aussi le pixel de coordonnées (249, 20).

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    from PIL import Image
    
    def sommetHaut(source):
        """
        source - Image
        Sortie: tuple - couple de coordonnées du premier pixel rencontré de couleur
                distincte de (255, 255, 255).
                L'image est parcourue de haut en bas et de gauche à droite.
                →→→→
                →→→→
                →→→→
        """
        # récupération des dimensions de l'image :
        largeur, hauteur = source.size
    
        ligne = 0
        colonne = 0
    
        while source.getpixel((colonne,ligne)) == (255,255,255):
            if colonne < largeur-1:
                colonne += 1
            else:
                colonne = 0
                ligne += 1
    
        return (colonne, ligne)
    
    
    if __name__ == '__main__':
        # importation de l'image:
        source = Image.open('feux.png')
    
        print(f"Coordonnées du sommet haut du triangle : {sommetHaut(source)}\n")
    

  2. À la fin du « main » du programme précédent, ajoutez les instructions suivantes :

    34
    35
    36
    for i in range(largeur):
        if source.getpixel((i, 20)) != (255, 255, 255):
            print(i)
    
    Exécutez le programme puis interprétez le résultat obtenu.

    Une solution

    On obtient :

    249
    250
    
    Cela signifie que le sommet de notre triangle est en fait constitué de deux pixels, le pixel de coordonénes (249, 20) et celui de coordonnées (250, 20).

    Vous pouvez vous convaincre de ce résultat en ouvrant l'image avec le logiciel GIMP. Dans le menu [Affichage], sélectionnez [Zoom 16:1].
    Déplacez-vous sur les pixels du sommet, les coordonnées s'affichent dans le bas de la fenêtre du logiciel.

  3. Obtenir de même les coordonnées du sommet bas-gauche du triangle et celles du sommet bas-droite.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    from PIL import Image
    
    def sommetBasGauche(source):
        """
        source - Image
        Sortie: tuple - couple de coordonnées du premier pixel bas-gauche
                rencontré de couleur distincte de (255, 255, 255).
        """
        # TODO
    
    
    def sommetBasDroite(source):
        """
        source - Image
        Sortie: tuple - couple de coordonnées du premier pixel bas-droite
                rencontré de couleur distincte de (255, 255, 255).
        """
        # TODO
    
    
    if __name__ == '__main__':
        # importation de l'image:
        source = Image.open('feux.png')
    
        print(f"Coordonnées du sommet bas-gauche du triangle : {sommetBasGauche(source)}\n")
    
        print(f"Coordonnées du sommet bas-droite du triangle : {sommetBasDroite(source)}\n")
    

    Une piste

    Au lieu de parcourir l'image ligne par ligne, on peut la parcourir colonne par colonne :

    • De gauche à droite pour le sommet bas-gauche ;
    • De droite à gauche et de bas en haut pour le sommet bas-droit.

    A vous de traduire cela avec les modifications qui conviennent sur le code écrit pour le sommet haut.

    Une solution avec une double boucle for

    Le pixel bas-gauche a pour coordonnées (46, 364), les coordonnées du sommet bas-droite sont (453, 364).

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    from PIL import Image
    
    def sommetBasGauche(source):
        """
        source - Image
        Sortie: tuple - couple de coordonnées du premier pixel bas-gauche
                rencontré de couleur distincte de (255, 255, 255).
                L'image est parcourue de gauche à droite et de haut en bas.
                ↓↓↓↓
                ↓↓↓↓
                ↓↓↓↓
        """
        # récupération des dimensions de l'image :
        largeur, hauteur = source.size
    
        for colonne in range(largeur):
            for ligne in range(hauteur):
                if source.getpixel((colonne,ligne)) != (255,255,255):
                    return (colonne, ligne)
    
    
    def sommetBasDroite(source):
        """
        source - Image
        Sortie: tuple - couple de coordonnées du premier pixel bas-droite
                rencontré de couleur distincte de (255, 255, 255).
                L'image est parcourue de bas en haut et de droite à gauche.
                ↑↑↑↑
                ↑↑↑↑
                ↑↑↑↑
        """
        # récupération des dimensions de l'image :
        largeur, hauteur = source.size
    
        for colonne in range(largeur-1, -1, -1):
            for ligne in range(hauteur-1, -1, -1):
                if source.getpixel((colonne,ligne)) != (255,255,255):
                    return (colonne, ligne)
    
    
    if __name__ == '__main__':
    
        # importation de l'image:
        source = Image.open('feux.png')
    
        print(f"Coordonnées du sommet bas-gauche du triangle : {sommetBasGauche(source)}\n")
    
        print(f"Coordonnées du sommet bas-droite du triangle : {sommetBasDroite(source)}\n")
    

    Une solution avec une boucle while

    Le pixel bas-gauche a pour coordonnées (46, 364), les coordonnées du sommet bas-droite sont (453, 364).

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    from PIL import Image
    
    def sommetBasGauche(source):
        """
        source - Image
        Sortie: tuple - couple de coordonnées du premier pixel bas-gauche
                rencontré de couleur distincte de (255, 255, 255).
                L'image est parcourue de gauche à droite et de haut en bas.
                ↓↓↓↓
                ↓↓↓↓
                ↓↓↓↓
        """
        # récupération des dimensions de l'image :
        largeur, hauteur = source.size
    
        ligne = 0
        colonne = 0
    
        while source.getpixel((colonne,ligne)) == (255,255,255):
            if ligne < hauteur-1:
                ligne += 1
            else:
                ligne = 0
                colonne += 1
    
        return (colonne, ligne)
    
    
    def sommetBasDroite(source):
        """
        source - Image
        Sortie: tuple - couple de coordonnées du premier pixel bas-droite
                rencontré de couleur distincte de (255, 255, 255).
                L'image est parcourue de bas en haut et de droite à gauche.
                ↑↑↑↑
                ↑↑↑↑
                ↑↑↑↑
        """
        # récupération des dimensions de l'image :
        largeur, hauteur = source.size
    
        ligne = hauteur-1
        colonne = largeur-1
    
        while source.getpixel((colonne,ligne)) == (255,255,255):
            if colonne > 0:
                colonne = colonne-1
            else:
                colonne = largeur-1
                ligne = ligne - 1
    
        return (colonne, ligne)
    
    
    if __name__ == '__main__':
    
        # importation de l'image:
        source = Image.open('feux.png')
    
        print(f"Coordonnées du sommet bas-gauche du triangle : {sommetBasGauche(source)}\n")
    
        print(f"Coordonnées du sommet bas-droite du triangle : {sommetBasDroite(source)}\n")
    

ProgB03.53 - Une image à partir de rien

Degrade Rouge Concevoir un script, sans fonction, qui permet d'obtenir le rectangle ci-contre, de 100 pixels de largeur et de 256 pixels de hauteur, de couleur dégradée du noir (en haut) vers le rouge (en bas).

Une piste : fichier à compléter
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
##----- Importation des modules -----##


##----- Variables et constantes : caractéristiques de l'image -----##
largeur =
hauteur =
encodage =

##------ Nouvelle image à créer ------##
im =

for x in range(largeur):
    for ...


##----- Fermeture et affichage -----##
Une solution
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
##----- Importation des modules -----##
from PIL import Image

##----- Variables et constantes -----##
largeur = 100
hauteur = 256
encodage = 'RGB'

##------ Nouvelle image ------##
im = Image.new(encodage, (largeur, hauteur))

for x in range(largeur):
    for y in range(hauteur):
        im.putpixel((x, y), (y, 0, 0))  # Composante R en fonction de la hauteur

##----- Fermeture et affichage -----##
im.save('Degrade.jpg')
im.show()

ProgB03.54 - Carrés empilés

Degrade Rouge L'image ci-contre est constituée de sept carrés de couleur noir, rouge, vert, jaune, bleu, magenta et cyan (dans cet ordre).

  1. Rappelez les triplets RGB correspondant à chacune de ces couleurs.

    Réponse

    Couleur Composante R Composante G Composante B
    Noir 0 0 0
    Rouge 255 0 0
    Vert 0 255 0
    Jaune 255 255 0
    Bleu 0 0 255
    Magenta 255 0 255
    Cyan 0 255 255

  2. Copiez/collez et complétez la définition de la fonction carre() en respectant ses spécifications.

    1
    2
    3
    4
    5
    6
    7
    8
    def carre(source, h, couleur):
        """
        source – Image
        h - int, ordonnée (numéro de ligne
        couleur – tuple, triplet RGB
        Sortie : None – Ajoute à l'image source un carré de 100 pixels
                de couleur, à partir de l'ordonnée h.
        """
    
    Une solution
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    def carre(source, h, couleur):
        """
        source – Image
        h - int, ordonnée (numéro du carré - de 0 à 6)
        couleur – tuple, triplet RGB
        Sortie : None – Ajoute à l'image source un carré de 100 pixels
                de couleur, à partir de l'ordonnée h.
        """
        for x in range(100) :
            for y in range(h*100, (h+1)*100) :
                source.putpixel((x, y), couleur)
    
  3. Utilisez cette fonction pour obtenir l'image de carrés empilés.

    Une solution
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    ##----- Importation des Modules -----##
    from PIL import Image                               # Ne pas oublier de l'importer pour un programme indépendant
    
    ##------ Définition des Fonctions ------##
    def carre(source, h, couleur):
        """
        source – Image
        h - int, ordonnée (numéro du carré - de 0 à 6)
        couleur – tuple, triplet RGB
        Sortie : None – Ajoute à l'image source un carré de 100 pixels
                de couleur, à partir de l'ordonnée h.
        """
        for x in range(100) :
            for y in range(h*100, (h+1)*100) :
                source.putpixel((x, y), couleur)
    
    ##------ Programme principal ------##
    ##----- Informations sur l'image -----##
    largeur = 100                                       # largeur de l'image, en pixels
    hauteur = 700                                       # hauteur de l'image, en pixels
    encodage = 'RGB'
    
    ##----- Conception de la nouvelle image -----##
    im = Image.new(encodage, (largeur, hauteur) )
    
    carre(im, 0, (0, 0, 0) )
    carre(im, 1, (255, 0, 0) )
    carre(im, 2, (0, 255, 0) )
    carre(im, 3, (255, 255, 0) )
    carre(im, 4, (0, 0, 255) )
    carre(im, 5, (255, 0, 255) )
    carre(im, 6, (0, 255, 255) )
    
    im.save('Carres_Empiles.jpg')
    im.show()
    
    Une variante
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    ##----- Importation des Modules -----##
    from PIL import Image                               # Ne pas oublier de l'importer pour un programme indépendant
    
    ##------ Définition des Fonctions ------##
    def carre(source, h, couleur):
        """
        source – Image
        h - int, ordonnée (numéro du carré - de 0 à 6)
        couleur – tuple, triplet RGB
        Sortie : None – Ajoute à l'image source un carré de 100 pixels
                de couleur, à partir de l'ordonnée h.
        """
        for x in range(100) :
            for y in range(h*100, (h+1)*100) :
                source.putpixel((x, y), couleur)
    
    ##------ Programme principal ------##
    ##----- Informations sur l'image -----##
    largeur = 100                                       # largeur de l'image, en pixels
    hauteur = 700                                       # hauteur de l'image, en pixels
    encodage = 'RGB'
    
    ##----- Conception de la nouvelle image -----##
    im = Image.new(encodage, (largeur, hauteur) )
    
    h = 0
    for i in range(2):
        for j in range(2):
            for k in range(2):
                if not(i == j == k == 1):
                    carre(im, h, (255*k, 255*j, 255*i))
                    h += 1
    
    im.save('Carres_Empiles.jpg')
    im.show()