Feuille de TP numéro 1

publicité
Analyse de Fourier et hilbertienne
ENS de Cachan
Département de Mathématiques
Vendredi 21 octobre 2016
Feuille de TP numéro 1
1
Consignes pour le rapport de TP
Cette feuille de TP comporte 16 questions. Les réponses, les résultat d’expérience (images,
figures), ansi que les codes devront être rassemblés dans un rapport individuel à rendre au
plus tard le vendredi 4 novembre 2016. Une pénalité de deux points par jour de retard sera
appliquée.
1.1
Format du rapport
Les rapports de TP seront rédigés avec LATEX et rendus au format PDF. Pour vous aider dans
la rédaction de ce rapport, un modèle de fichier LATEX (extension .tex) est téléchargeable à
l’adresse : http://dev.ipol.im/~coco/afh/modele_latex.zip
1.2
Remise du rapport
Le rapport (PDF) du TP doit être rendu au plus tard le vendredi 4 novembre 2016. Il sera
envoyé à l’adresse email [email protected]. L’objet de l’email doit être
Rapport du TP1 de Nom Prénom et le fichier .pdf joint doit être intitulé nom_prenom_tp1.pdf.
2
Mise en route
Ouvrez un terminal (fenêtre permettant d’entrer des lignes de commandes). Tapez les commandes suivantes pour créer un dossier tp_fourier et placez vous dans ce dossier :
mkdir tp_fourier
cd tp_fourier
Dans le même terminal, tapez les commandes suivantes pour télécharger les fichiers nécessaires
dans votre dossier tp_fourier.
wget dev.ipol.im/~coco/afh/tp1.zip
unzip tp1.zip
Toujours dans le même terminal, lancez Pyzo grâce à la commande pyzo2014. Vous pouvez également lancer python directement dès la ligne de commande, ou même écrire vos instructions dans un fichier mon_script.py puis l’exécuter avec python mon_script.py.
Avant de commencer, il est conseillé d’exécuter les commandes suivantes :
1/7
cd tp_fourier/tp1
import numpy as np
import matplotlib.pyplot as plt
import imageio
from numpy.fft import fft,ifft,fftshift,fft2,ifft2
3
Notions de base sur les images numériques
Nous travaillerons exclusivement avec des images en niveaux de gris.
3.1
Niveaux de gris
Une image numérique est un tableau de pixels (vu comme une matrice), dont les coefficients
sont typiquement des nombres flottants compris entre 0 et 1 ou des entiers entre 0 et 255. Il
est très facile de créer des images simples avec Python. Par exemple, le script suivant crée une
image de taille 500 × 500 représentant un carré noir sur fond blanc :
u = np.ones( (500,500) )
u[200:400,100:300] = 0
Pour visualiser une image u (ou n’importe quel tableau) nous utiliserons les instructions
suivantes (le problème de la visualisation d’une image est abordé en détail dans la partie suivante) :
plt.imshow(u, cmap="gray")
I Question 1 : Créez une image de taille 256 × 256 qui soit constante sur chaque colonne et dont
le niveau de gris des colonnes varie progressivement de 0 à 1.
Aide Python : Si a et b sont deux nombres, alors np.linspace(a,b,n) est un vecteur de
longueur n avec valeurs entre a et b.
I Question 2 : Que représente l’image suivante ?
Par quelle suite de commandes peut-on créer et afficher l’image 9 × 9 suivante ?
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0.5
0.5
0.5
0.5
0.5
0
0
0
0
0.5
1
1
1
0.5
0
0
0
0
0.5
1
1
1
0.5
0
0
0
0
0.5
1
1
1
0.5
0
0
0
0
0.5
0.5
0.5
0.5
0.5
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
2/7
3.2
3.2.1
Visualisation des images
Plage de valeurs
La manipulation mathématique des images amène à considérer des images dont les niveaux
de gris sont des nombres réels (ou du moins la représentation informatique des nombres réels,
c’est-à-dire des nombres flottants). En effet, toutes les images ne peuvent pas être limitées à des
valeurs entre 0 et 1.
La méthode de visualisation effectue un changement de variable affine qui ramène l’intervalle [min(u), max(u)] sur l’intervalle intensité d’image : min(u) correspond au noir et max(u)
au blanc.
3.2.2
Lecture et écriture des fichiers d’images
La fonction imread permet de lire des fichiers images en format PNG :
u = imageio.imread(’tile.png’)[:,:,0]
Ainsi obtenu, u est un Array des nombres entiers compris entre 0 et 1. On peut le vérifier par
les commandes suivantes :
u.shape
u.dtype
Pour le convertir à flottants, vous pouvez faire par exemple u=np.double(u)/255 ou simplement u=u/255.0.
Pour enregistrer une image u dans un fichier d’image PNG il faut utiliser la fonction imsave :
imageio.imsave(’nouvelle_image.png’, u)
Il est conseillé de convertir les images à uint8, avec des valeurs entre 0 et 255 avant de les
sauvegarder. ATTENTION : imsave écrase les fichiers existants sans prévenir !
3.2.3
Visualisation des images avec Python
imshow : La fonction qu’on utilisera pour visualiser des images avec Python est plt.imshow(im,
cmap="gray"). Le paramètre im est le nom d’une variable contenant un tableau à valeurs
réelles ou entières. Optionnellement, on peut indiquer la plage de valeurs à montrer avec la
commnande suivante :
plt.imshow(im, cmap="gray", vmin=-10, vmax=10)
Dans l’exemple, la plage de valeurs va de -10 à 10 ; la valeur -10 correspondra au noir, la
valeur 10 au blanc et les valeurs intermédiaires à differents niveaux de gris, toutes les valeurs
plus petites que -10 ou plus grandes que 10 seront saturées et donc montrées comme noires ou
blanches respectivement. Si les paramètres vmin et vmax ne sont pas spécifiés, la gamme sera
automatiquement fixée à vmin=im.min() et vmax=im.max().
I Question 3 : Chargez l’image water.png dans la variable im, et testez les commandes
suivantes :
3/7
plt.imshow(im,
plt.imshow(im,
plt.imshow(im,
plt.imshow(im,
cmap="gray")
cmap="gray", vmin=0, vmax=1)
cmap="gray", vmin=0, vmax=0.4)
vmin=0, vmax=1)
Comment expliquez-vous les différences observées entre les visualisations ?
Pour fixer la palette grise par défaut, faire plt.rcParams[’image.cmap’] = ’gray’
4
4.1
Transformée de Fourier discrète (TFD)
En dimension 1
I Question 4 : Trouvez et lisez l’aide de numpyp.fft. La définition de la TFD dans Python
diffère de celle du cours. Précisez.
En réalité, ce ne sont que des différrences de conventions. Les propriétés de la TFD restent
inchangées. Par soucis de simplicité, nous utiliserons pour ces TPs la définition de Python.
Créez un signal discret u de longueur paire N = 512 représentant un créneau :
N = 512
u = np.zeros(N)
u[ N/4 : 3*N/4 ] = 1
plt.plot(u)
I Question 5 : Calculez le module de Fourier modu du signal u (utilisez modu=abs(u))
et visualisez-le avec la commande plt.plot(modu). Le graphique obtenu est-il conforme
à vos attentes ? Où se trouve la fréquence nulle ? Recommencez en utilisant la commande
fftshift.
4.2
4.2.1
En dimension 2
TFD et TFD inverse
La TFD en dimension 2 est donnée par la fonction fft2, la transformation inverse est donnée
par ifft2. Lisez la section “Higher dimensions” de l’aide en ligne de numpy.fft. Remarquez que la propriété de séparabilité de la transformation est mise en œuvre.
Remarque : En pratique, il est possible que la TFD inverse de la TFD d’une image réelle ne
soit pas réelle. À cause des erreurs d’arrondi, la partie imaginaire peut ne pas être strictement
nulle. Dans ce cas, on pourra extraire la partie réelle avec la commande real.
4.2.2
Visualisation du module
Pour visualiser le module d’une image nous utiliserons la fonction vis_mod_img définie dans
afh.py, fournie dans l’archive tp1.zip. Vous pouvez lire la description de cette fonction
dans le fichier afh.py.
I Question 6 : Lisez le fichier afh.py. Visualisez le module de l’image room.png avec
les trois jeux de paramètres (d,opt) = (0,0), (1,0), (1,1). Expliquez l’intérêt du
seuillage. Quelle propriété de symétrie du module peut-on observer ?
4/7
On ne visualisera pas la phase d’une image car son interprétation est assez difficile. Néanmoins, comme le montrent les expériences qui suivent, la phase d’une image est au moins aussi
importante que son module du point de vue de l’information qu’elle contient.
4.2.3
Échange du module et de la phase de deux images
Calculez et visualisez les deux images obtenues en échangeant le module et la phase des images
building.png et tile.png. Recommencez cette expérience avec les couples d’images
(sand.png, water.png) et (tile.png, sand.png).
(Aide Python : Le module et la phase d’un nombre complexe c sont donnés par abs(c) et
angle(c)).
I Question 7 : Quelles conclusions générales peut-on en tirer sur les contenus visuels du module et de la phase d’une image ? (On distingue deux types de “contenu visuel” : les contours
géométriques et les textures.)
5
5.1
Effet de Gibbs et zooms avant
Polynôme trigonométrique associé à un signal discret
Soit uk , k = 0, . . . , N − 1 un signal discret et ũn , n = − N2 , . . . , N2 − 1 sa TFD. On suppose que
N est un entier pair. On rappelle que le polynôme trigonométrique associé à u est le polynôme
Pu défini par
N
−1
2
X
2iπnx
ũn e N .
Pu (x) =
n=− N
2
Le polynôme Pu vérifie Pu (k) = uk pour tout k = 0, . . . , N − 1. Alors Pu est un polynôme
trigonométrique qui interpole les valeurs du signal u. En revanche, Pu n’est pas nécessairement
à valeur réelle ce qui n’est pas satisfaisant en pratique.
I Question 8 : Montrez que Pu est à valeur réelle si et seulement si ũ− N = 0. Notez également
2
que pour tout signal u, la partie réelle de Pu est un polynôme trigonométrique qui interpole les
valeurs de u.
En pratique, on utilise la partie réelle de Pu pour interpoler le signal u. Il en est de même en
dimension 2.
5.2
Effet de Gibbs sur les images
L’effet de Gibbs est le phénomène suivant : les projections basses fréquences d’un signal présentant des discontinuités ont des comportements oscillants autour des discontinuités. Nous allons
mettre en évidence ce phénomène à partir d’une image discrète (voir le polycopié pour le cas
des signaux unidimensionnels).
Créez une image rectangle de taille 512×512 repésentant un rectangle gris clair (niveau
de gris 0.8) sur un fond gris foncé (niveau de gris 0.2), voir la section 3.1. Calculez la TFD de
l’image rectangle. Annulez toutes les fréquences qui ne sont pas dans le carré central de
5/7
taille n×n avec n = 64 et calculez l’image rectbf correspondant à ce spectre ne comportant
que des basses fréquences.
I Question 9 : Commentez les résultats observés.
5.3
Zooms avant
Le fichier d’instructions zooms_avant.py vous permet de comparer trois méthodes d’interpolation pour zoomer une image.
• La première est la méthode “pixel le plus proche”.
• La deuxième repose sur l’interpolation bilinéaire.
• La troisième est le zoom par zéro-padding (extension du spectre avec des hautes fréquences nulles).
I Question 10 : Testez les zooms sur plusieurs images. Décrivez brièvement les défauts de
chacune des méthodes. Expliquez le lien entre les défauts du zoom par zéro-padding et l’effet
de Gibbs.
6
6.1
Translation non entière et rotation
Translation non entière
Soit (uk,l ) une image carrée de taille N × N et (ũm,n ) sa TFD. On pose
N
Pu (x, y) =
N
−1
−1
2
2
X
X
ũm,n e
2iπmx
N
e
2iπny
N
m=− N
n=− N
2
2
le polynôme trigonométrique représenté par u.
I Question 11 : Soit a et b deux réels. Exprimez la TFD de (k, l) 7→ Pu (k − a, l − b) en fonction des ũm,n . Codez une fonction v = translation_fourier(u,a,b) qui calculera
la translation de l’image u par le vecteur (a, b). Cette fonction retournera la partie réelle de la
translation de Pu , en accord avec les remarques de la section 5.1.
Testez votre fonction en faisant une translation sous-pixelienne de (3.3 ; 50.7) pixels d’une
image.
6.2
Rotation d’une image (devoir à la maison)
La rotation d’une image par la méthode de Yaroslavsky se base sur la décomposition suivante :
cos θ sin θ
R−θ :=
− sin θ cos θ
1
0
cos θ sin θ
1 tan 2θ
1 tan 2θ
=
− sin θ cos θ
− sin θ 1
0
1
0
1
{z
}
|
{z
}|
:=T (θ)
:=S(θ)
6/7
R−θ := Tθ Sθ Tθ
Remarquez que le changement de
donné par T (θ) revient à translater chaque co variable
θ
lonne : u(k, l) devient u k + tan 2 l, l . De même, le changement de variable donné par S(θ)
revient à translater chaque ligne : u(k, l) devient u (k, l − sin(θ)k).
Les consignes qui suivent ont pour but de vous aider à coder l’algorithme de rotation de
Yaroslavsky.
I Question 12 : Codez une fonction v = translation_colonnes(u,t) qui translate
chaque colonne k de u par le vecteur t(k) en utilisant la TFD unidimensionnelle.
(Aide Python : si A est une matrice, alors fft(A,axis=0) renvoie la matrice des TFD des
colonnes de A). Testez cette fonction avec des vecteurs de translation non entiers.
I Question 13 : Codez une fonction v = translation_lignes(u,t) qui translate chaque
ligne k de u par le vecteur t(k). On va utiliser la fonction translation_colonnes et les
transpositions de matrice. (Aide Python : la transposée de A est np.transpose(A)).
I Question 14 : Codez la fonction v = rotation_fourier(u,theta) en effectuant trois
appels successifs aux fonctions translation_colonnes et translation_lignes.
Commencez par copier l’image u au centre d’une image nulle deux fois plus grande pour éviter
les problèmes de bords. Imposez à chacune des translations de ne pas déplacer la colonne (ou
la ligne) du centre de l’image. Illustrez la méthode en visualisant chacune des images intermédiaires.
Testez votre fonction en faisant (a) une rotation de 13o d’une image, (b) dix rotations de
36o , (c) 360 rotations de 1o .
7
Zoom arrière et aliasing (devoir à la maison)
Le fichier d’instructions aliasing.py illustre le phénomène d’aliasing (ou repliement de
spectre). Suivez les instructions dans le fichier et répondez aux questions suivantes.
I Question 15 : Dans la partie 1) qu’observe-t-on ? Comment cela se traduit-il au niveau du
spectre ?
I Question 16 : Dans la partie 2) expliquez précisément le comportement des deux ondes
sous-échantillonnées. Quelle est la fréquence de l’onde de l’image sous-échantillonnée par 4 ?
Qu’observe-t-on ? Comment cela se traduit-il au niveau du spectre ?
7/7
Téléchargement