Commit c0777b10 authored by Matthieu PERREIRA DA SILVA's avatar Matthieu PERREIRA DA SILVA
Browse files

Corrections minimes après tests sous cocalc

parent fc945472
Pipeline #21212 passed with stage
in 1 minute and 1 second
%% Cell type:markdown id: tags:
# TP1 : quantification, histogramme et égalisation, interpolation, couleur
Dans ce TP, quelques images sont fournies, mais vous êtes fortement encouragés à récupérer et expérimenter sur d'autres images récupérées sur le web.
Les TP de traitement d'images sont réalisés en Python3, à l'aide de la librairie [scikit-image](http://scikit-image.org/docs/stable/). Les tableaux utilisés (`ndarray`) par cette librairie pour manipuler les images proviennent de la librairie [numpy](https://docs.scipy.org/doc/). L'affichage des images et autres figures est réalisé grace à [matplotlib](https://matplotlib.org/contents.html). La documentation de ces trois librairies vous sera donc bien utile.
Dans ce TP, les questions seront indiquées dans un bloc **question**, et les réponses seront à donner dans le bloc **réponse** situé en dessous du bloc de question. Vos réponses sont à rédiger en [markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). Vous pourrez ainsi répondre non seulement avec du texte, mais aussi avec des tableaux et des images.
Ce TP est à réaliser en deux séances d'1h30.
**Remarque importante:** Les questions posées dans ce TP requièrent généralement des <u>réponses courtes mais justifées</u>. Un simple oui ou non ne nous est d'aucune utilité pour juger de votre compréhension de la question et de sa réponse...
**Autre remarque:** Il y a parfois plusieurs sous-questions dans une même question. <u>Pensez a répondre à toutes les sous-questions</u>.
## Manipulation d'image
- Nous allons commencer par charger et afficher une image à l'aide du code ci-dessous.
%% Cell type:code id: tags:
``` python
%matplotlib widget
# la ligne précédente permet d'afficher les figures directement dans votre notebook et de pouvoir interagir avec
from skimage import io # on charge le module permettant d'ouvrir des images
import matplotlib.pyplot as plt # gestion des figures
im = io.imread('talvi.jpg')
plt.imshow(im)
```
%% Output
<matplotlib.image.AxesImage at 0x11e245048>
<matplotlib.image.AxesImage at 0x7f9d848724c0>
%% Cell type:markdown id: tags:
- Les images sont manipulées sous forme de tableau à 2 (niveaux de gris) ou 3 dimensions (couleur). Le type python utilisé pour représenter ces tableaux est `ndarray` de la librairie numpy.
%% Cell type:code id: tags:
``` python
print("type de données utilisé:", type(im))
print("nombre de dimensions de l'image:",im.ndim)
print("dimensions:", im.shape)
```
%% Output
type de données utilisé: <class 'numpy.ndarray'>\nnombre de dimensions de l'image: 3\ndimensions: (400, 300, 3)\n
type de données utilisé: <class 'numpy.ndarray'>
nombre de dimensions de l'image: 3
dimensions: (400, 300, 3)
%% Cell type:markdown id: tags:
**Question 1:** Expliquez les dimensions affichée pour l'image d'exemple.
%% Cell type:markdown id: tags:
**Réponse 1:** VOTRE REPONSE ICI
%% Cell type:markdown id: tags:
**Question 2:** Le code suivant transforme l'image d'origine en niveau de gris. Modifiez le afin d'afficher les dimensions de la nouvelle image. Cela correspond-t-il à ce que vous attendez ? Y a-t-il une différence entre les deux méthodes utilisées ? (si oui) pourquoi ?
%% Cell type:markdown id: tags:
**Réponse 2:** VOTRE REPONSE ICI
%% Cell type:code id: tags:
``` python
from skimage import color # fonctions de conversion de couleur
# Traitement des images
im_gris1=im.mean(2)
im_gris2=(color.rgb2grey(im)*255).astype('uint8') #rgb2grey renvoie une image avec 0<= valeurs <=1
im_gris2=(color.rgb2gray(im)*255).astype('uint8') #rgb2grey renvoie une image avec 0<= valeurs <=1
diff=abs(im_gris1-im_gris2)
# Affichage sous forme de différentes figures (attention les numéros de figure sont valables dans tout le notebook)
plt.figure(2)
plt.imshow(im_gris1, cmap=plt.cm.gray) # cmap=plt.cm.gray permet d'afficher les image en niveaux de gris avec la bonne palette
plt.title("moyenne")
plt.figure(3)
plt.imshow(im_gris2, cmap=plt.cm.gray)
plt.title("rgb2grey")
plt.figure(4)
print(diff.mean())
plt.imshow(diff, cmap=plt.cm.gray)
plt.title("différence")
```
%% Output
4.314236111111111
4.314527777777777\n
Text(0.5, 1.0, 'différence')
Text(0.5, 1, 'différence')
%% Cell type:markdown id: tags:
## Quantification
### Comment ça marche ?
Fixer par exemple la variable `Q=8` pour le taux de quantification, puis lancer le script ci-dessous. Essayer pour diverse images (talvi, dégradés, etc.) et déterminer si, à Q identique la visibilité des dégradation dépend des images ou zones d'images.
%% Cell type:code id: tags:
``` python
import numpy as np # manipulation des ndarray
# Init
Q=32
im = io.imread('talvi.jpg')
# Traitements
im_gris=(color.rgb2grey(im)*255).astype('uint8')
im_gris=(color.rgb2gray(im)*255).astype('uint8')
im_requantifiee = Q * np.round(im_gris/Q)
# Affichage sous forme de différentes sous figures
plt.figure() #les numéros de figure ne sont pas obligatoires
plt.subplot(121) # 121 = 1 ligne, 2 colonnes, 1ère sous figure
plt.imshow(im_gris, cmap=plt.cm.gray)
plt.title("image de départ")
plt.subplot(122) # 122 = 1 ligne, 2 colonnes, 2ème sous figure
plt.imshow(im_requantifiee, cmap=plt.cm.gray)
plt.title("requantifié Q=" + str(Q))
```
%% Output
Text(0.5, 1.0, 'requantifié Q=32')
Text(0.5, 1.0, 'requantifié Q=32')
%% Cell type:markdown id: tags:
**Question 3:** Visualiser l'effet de cette opération pour Q=2, puis Q=38 et Q=71.
%% Cell type:markdown id: tags:
**Réponse 3:** VOTRE REPONSE ICI
%% Cell type:markdown id: tags:
**Question 4:** Montrer que cet algorithme réalise de la compression d'images avec perte.
%% Cell type:markdown id: tags:
**Réponse 4:** VOTRE REPONSE ICI
%% Cell type:markdown id: tags:
### Comment mesurer la dégradation ?
**Question 5:** Cette dégration visuelle (évaluation subjective de votre part) est-t-elle perceptible pour des quantifications (`Q`) faibles ?
On pourrait qualifier objectivement et numériquement la dégradation par différentes mesures d'erreur (cf. code ci-dessous).
%% Cell type:markdown id: tags:
**Réponse 5:** VOTRE REPONSE ICI
%% Cell type:code id: tags:
``` python
from skimage import measure # fonctions de mesure d'erreur
from skimage import metrics # fonctions de mesure d'erreur
err_quad=measure.compare_mse(im_gris, im_requantifiee)
err_quad=metrics.mean_squared_error(im_gris, im_requantifiee)
print("erreur quadratique moyenne (mse):", err_quad)
psnr=measure.compare_psnr(im_gris/255, im_requantifiee/255) # compare_psnr a besoin d'images avec des 0 <= valeur <=1
psnr=metrics.peak_signal_noise_ratio(im_gris/255, im_requantifiee/255) # peak_signal_noise_ratio a besoin d'images avec des 0 <= valeur <=1
print("rapport signal bruit (psnr):", psnr)
ssim=measure.compare_ssim(im_gris, im_requantifiee)
ssim=metrics.structural_similarity(im_gris/255, im_requantifiee/255) # idem ici
print("similarité structurelle (ssim):", ssim)
```
%% Output
erreur quadratique moyenne (mse): 85.842175\nrapport signal bruit (psnr): 28.793796479662667\nsimilarité structurelle (ssim): 0.8808622932284417\n
erreur quadratique moyenne (mse): 85.84075
rapport signal bruit (psnr): 28.79386857415159
similarité structurelle (ssim): 0.913582970122122
%% Cell type:markdown id: tags:
**Question 6:** Chercher la signification de chacune de ces mesures. De quelle manière doit on les interpréter ? Correspondent elle à votre évaluation subjective ? Est-ce que cette fidélité depend des images / zones d'images ?
%% Cell type:markdown id: tags:
**Réponse 6:** VOTRE REPONSE ICI
%% Cell type:markdown id: tags:
## Histogramme, seuillage
Le script ci-dessous calcule et affiche l'histogramme des niveaux de gris d'une image, après quantification uniforme en N boites.
** Question 7:** Essayez les trois cas `N=256`, `N=50` et `N=10`. Pour plusieurs images de votre choix, faire le lien entre les régions de l'histogramme et les régions de l'image.
%% Cell type:markdown id: tags:
**Réponse 7:** VOTRE REPONSE ICI
%% Cell type:code id: tags:
``` python
from skimage import exposure
N = 256 # Expérimenter avec d'autres valeurs
im = io.imread('talvi.jpg') # Expérimenter avec d'autres images
im_gris=(color.rgb2grey(im)*255).astype('uint8') # transcodage de l'image en uint8 pour avec un histogramme discret
im_gris=(color.rgb2gray(im)*255).astype('uint8') # transcodage de l'image en uint8 pour avec un histogramme discret
(histo, bin_centers)=exposure.histogram(im_gris,N)
plt.figure()
plt.bar(np.arange(N), histo)
```
%% Output
<BarContainer object of 256 artists>
<BarContainer object of 256 artists>
%% Cell type:markdown id: tags:
** Question 8: ** Que fait le petit script ci-dessous ? Quel est le rôle de la variable `SEUIL` (testez différentes valeurs) ?
%% Cell type:markdown id: tags:
**Réponse 8:** VOTRE REPONSE ICI
%% Cell type:markdown id: tags:
** Question 9: ** Quel est le lien ente cette opération de seuillage et l'histogramme de l'image ? A quoi ressemble l'histogramme de l'image seuillée ? (vous pouvez ajouter du code pour l'afficher)
%% Cell type:markdown id: tags:
**Réponse 9:** VOTRE REPONSE ICI
%% Cell type:code id: tags:
``` python
SEUIL = 75
# une double boucle (lente) pour effectuer notre traitement sur chaque pixel
im_thresholded = np.zeros( im_gris.shape )
largeur = im_gris.shape[1]
hauteur = im_gris.shape[0]
for y in range(0, hauteur):
for x in range(0, largeur):
if im_gris[y][x] > SEUIL:
im_thresholded[y][x] = 255
else:
im_thresholded[y][x] = 0
# On peut aussi remplacer la double boucle précédente par ceci
#im_thresholded = (im_gris > SEUIL)*255
plt.figure()
plt.imshow(im_thresholded, cmap=plt.cm.gray)
```
%% Output
<matplotlib.image.AxesImage at 0x1201c75f8>
<matplotlib.image.AxesImage at 0x7f9d7bd10610>
%% Cell type:markdown id: tags:
** Question 10: ** Dans une nouvelle cellule de script, adaptez le programme précédent pour réaliser un effet "inverse vidéo" sur l'image originale (un pixel de sortie doit être d'autant plus foncé qu'il n'était clair en entrée).
%% Cell type:code id: tags:
``` python
# VOTRE CODE ICI
```
%% Cell type:markdown id: tags:
## Restauration par transformation de l'intensité : égalisation d'histogramme
L'objectif de cette opération est "d'améliorer" une image en transformant son contraste, c'est à dire d'exploiter "au mieux" la dynamique de luminance disponible.
**Question 11:** Exécuter le script ci-dessous et interprétez les résultats pour l'image `essai.jpg`.
%% Cell type:markdown id: tags:
**Réponse 11:** VOTRE REPONSE ICI
%% Cell type:code id: tags:
``` python
plt.rcParams['figure.subplot.hspace'] = 0.8 # espace un peu les sous-figures verticalement
from skimage import exposure
nb_bins=256
# Chargement de l'image
im = io.imread('low.png') # Expérimenter avec d'autres images
im_gris=(color.rgb2grey(im)*255.0).astype('uint8') # transcodage de l'image en uint8 pour avec un histogramme discret
im_gris = io.imread('low.png') # Expérimenter avec d'autres images
im_gris=color.rgb2gray(im).astype('uint8') # transcodage de l'image en uint8 pour avec un histogramme discret
# Histogramme normale et cumulé de l'image de départ
im_gris_histo, im_bins = exposure.histogram( im_gris, nb_bins )
im_gris_cumul, im_cumul_bins = exposure.cumulative_distribution( im_gris, nb_bins )
# Egalisation + histogramme
im_eq = exposure.equalize_hist(im_gris,nb_bins)