Skip to article frontmatterSkip to article content

merci à Wikipedia et à stackoverflow

le but de ce TP n’est pas d’apprendre le traitement d’image
on se sert d’images pour égayer des exercices avec numpy
(et parce que quand on se trompe ça se voit)

import numpy as np
from matplotlib import pyplot as plt

Création d’un patchwork

  1. Le fichier data/rgb-codes.txt contient une table de couleurs:
AliceBlue 240 248 255
AntiqueWhite 250 235 215
Aqua 0 255 255
.../...
YellowGreen 154 205 50

Le nom de la couleur est suivi des 3 valeurs de ses codes R, G et B
Lisez cette table en Python et rangez-la dans la structure qui vous semble adéquate.

# votre code
  1. Affichez, à partir de votre structure, les valeurs rgb entières des couleurs suivantes
    'Red', 'Lime', 'Blue'
# votre code
  1. Faites une fonction patchwork qui prend deux paramètres obligatoires:

    • une liste de couleurs
    • et la structure donnant le code des couleurs RGB qu’on a obtenue à l’étape 1
      et retourne un tableau numpy avec un patchwork de ces couleurs

    Testez votre fonction en affichant le résultat obtenu sur un jeu de couleurs fourni

# votre code
def rectangle_size(n):
    """
    return a tuple lines, cols for
    the smallest rectangle that contains n cells
    """
    ...
# votre code 
def patchwork(colors, colormap, side=10):
    """
    """
    ...
  1. Tirez aléatoirement une liste de couleurs et appliquez votre fonction à ces couleurs.
# votre code
  1. Sélectionnez toutes les couleurs à base de blanc et affichez leur patchwork
    même chose pour des jaunes
# votre code
  1. Appliquez la fonction à toutes les couleurs du fichier
    et sauver ce patchwork dans le fichier patchwork.png avec plt.imsave
# votre code
  1. Relisez et affichez votre fichier
    attention si votre image vous semble floue c’est juste que l’affichage grossit vos pixels

vous devriez obtenir quelque chose comme ceci

# votre code

Somme dans une image & overflow

  1. Lisez l’image data/les-mines.jpg
# votre code
  1. Créez un nouveau tableau numpy.ndarray en sommant avec l’opérateur + les valeurs RGB des pixels de votre image
# votre code
  1. Regardez le type de cette image-somme, et son maximum; que remarquez-vous?
    Affichez cette image-somme; comme elle ne contient qu’un canal il est habile de l’afficher en “niveaux de gris” (normalement le résultat n’est pas terrible ...)

# votre code
  1. Créez un nouveau tableau numpy.ndarray en sommant mais cette fois avec la fonction d’agrégation np.sum les valeurs RGB des pixels de votre image
# votre code
  1. Comme dans le 2., regardez son maximum et son type, et affichez la
# votre code
  1. Les deux images sont de qualité très différente, pourquoi cette différence ? Utilisez le help np.sum?
# votre code / explication
  1. Passez l’image en niveaux de gris de type entiers non-signés 8 bits
    (de la manière que vous préférez)
# votre code
  1. Remplacez dans l’image en niveaux de gris,
    les valeurs >= à 127 par 255 et celles inférieures par 0
    Affichez l’image avec une carte des couleurs des niveaux de gris
    vous pouvez utilisez la fonction numpy.where
# votre code
  1. avec la fonction numpy.unique
    regardez les valeurs différentes que vous avez dans votre image en noir et blanc
# votre code

Image en sépia

Pour passer en sépia les valeurs R, G et B d’un pixel
(encodées ici sur un entier non-signé 8 bits)

  1. on transforme les valeurs R, G et B par la transformation
    0.393 * R + 0.769 * G + 0.189 * B
    0.349 * R + 0.686 * G + 0.168 * B
    0.272 * R + 0.534 * G + 0.131 * B
    (attention les calculs doivent se faire en flottants pas en uint8
    pour ne pas avoir, par exemple, 256 devenant 0)
  2. puis on seuille les valeurs qui sont plus grandes que 255 à 255
  3. naturellement l’image doit être ensuite remise dans un format correct
    (uint8 ou float entre 0 et 1)
# exemple de produit de matrices avec `numpy.dot`
# le help(np.dot) dit: dot(A, B)[i,j,k,m] = sum(A[i,j,:] * B[k,:,m])

i, j, k, m, n = 2, 3, 4, 5, 6
A = np.arange(i*j*k).reshape(i, j, k)
B = np.arange(m*k*n).reshape(m, k, n)

C = A.dot(B)
# or C = np.dot(A, B)

print(f"en partant des dimensions {A.shape} et {B.shape}")
print(f"on obtient un résultat de dimension {C.shape}")
print(f"et le nombre de termes dans chaque `sum()` est {A.shape[-1]} == {B.shape[-2]}")
en partant des dimensions (2, 3, 4) et (5, 4, 6)
on obtient un résultat de dimension (2, 3, 5, 6)
et le nombre de termes dans chaque `sum()` est 4 == 4

Exercice

  1. Faites une fonction qui prend en argument une image RGB et rend une image RGB sépia
    la fonction numpy.dot peut être utilisée si besoin, voir l’exemple ci-dessus
# votre code
  1. Passez votre patchwork de couleurs en sépia
    Lisez le fichier patchwork-all.jpg si vous n’avez pas de fichier perso
# votre code
  1. Passez l’image data/les-mines.jpg en sépia
# votre code

Exemple de qualité de compression

  1. Importez la librairie Imagede PIL (pillow)
    (vous devez peut être installer PIL dans votre environnement)
# votre code
  1. Quelle est la taille du fichier data/les-mines.jpg sur disque ?
file = "data/les-mines.jpg"
# votre code
  1. Lisez le fichier ‘data/les-mines.jpg’ avec Image.open et avec plt.imread
# votre code
  1. Vérifiez que les valeurs contenues dans les deux objets sont proches
# votre code
  1. Sauvez (toujours avec de nouveaux noms de fichiers)
    l’image lue par imread avec plt.imsave
    l’image lue par Image.open avec save et une quality=100
    (save s’applique à l’objet créé par Image.open)
# votre code
  1. Quelles sont les tailles de ces deux fichiers sur votre disque ?
    Que constatez-vous ?
# votre code
  1. Relisez les deux fichiers créés et affichez avec plt.imshow leur différence
# votre code