-
Notifications
You must be signed in to change notification settings - Fork 0
/
TE1.py
286 lines (246 loc) · 13.2 KB
/
TE1.py
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
import numpy as np
import cv2
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Transformée de Fourier et interprétation
# voir tutoriaux python-OpenCV
plt.close('all')
# %%création d'une image composée d'une sinusoïde
fx, fy = 0.03, 0.08; # fréquences définissant la sinusoïde données en cycles par
# pixel. Il faut les multiplier par le nombre de pixels par ligne et par colonne
# pour les avoir en cycles par image.
Z = np.fromfunction(lambda m, n: np.sin(2 * np.pi * (fx * n + fy * m)), (512, 512))
plt.figure()
plt.imshow(Z, cmap='gray'), plt.title('Mire sinusoïdale'), plt.xlabel('x'), plt.ylabel('y'),
plt.show()
# En comptant les cycles (<=> périodes) sur chaque axe,
# on trouve nb_cycles_x=16 env et nb_cycles_y=41 env, ce qui correspond à
# fx=0.031 env et fy=0.08 (vous devez bien comprendre la signification des
# fréquences spatiales!)
# %% calcul de la TFD-2D avec numpy
tfd_w = np.fft.fft2(Z);
# la transformée de Fourier est calculée pour des fréquences u et v normalisées
# entre 0 et 1 -
# (fréquence horizontale (verticale) <=> variation de niveaux de gris selon x
# (y) respectivement)
# calcul du spectre d'amplitude:
# le spectre d'amplitude défini pour des fréquences u et v
# normalisées et tq 0<u<1 et 0<v<1 est donc donné par:
magnitude_spectrum = np.abs(tfd_w);
# visualisation du spectre
plt.figure()
plt.subplot(121), plt.imshow(Z, cmap='gray')
plt.title('Mire sinusoïdale'), plt.xlabel('n - axe x'), plt.ylabel('m - axe y')
plt.subplot(122), plt.imshow(np.log2(1 + magnitude_spectrum), origin=('upper'), extent=(0, 1, 1, 0), cmap='jet')
# sans extent(0,1,1,0), les axes sont référencés en nombre de points et non pas
# en fréquences normalisées entre 0 et 1 pour chaque axe. Bien renseigner ce
# champ extent est essentiel pour bien interpréter le spectre
# Bien noter que la syntaxe pour extent est (left, right, bottom, top). Comme
# l'axe y va vers le bas il faut saisir extent(0,1,1,0) et non pas extent(0,1,0,1)
plt.title('Spectre d''amplitude avec numpy'), plt.xlabel('u'), plt.ylabel('v')
plt.show()
# calcul de la TFD-2D et de son module (spectre d'amplitude) avec OpenCV
tfd_w = cv2.dft(np.float32(Z), flags=cv2.DFT_COMPLEX_OUTPUT)
# de même la TFD2D est ici calculée pour des fréquences entre 0 et 1
magnitude_spectrum = cv2.magnitude(tfd_w[:, :, 0], tfd_w[:, :, 1])
plt.figure()
plt.subplot(121), plt.imshow(Z, cmap='gray')
plt.title('Mire sinusoïdale'), plt.xlabel('n - axe x'), plt.ylabel('m - axe y')
plt.subplot(122), plt.imshow(np.log2(1 + magnitude_spectrum), origin=('upper'), extent=(0, 1, 1, 0), cmap='jet')
plt.title('Spectre d''amplitude avec OpenCV'), # plt.colorbar()
plt.xlabel('u'), plt.ylabel('v');
plt.show()
# %%
# visualisation du spectre centré pour une meilleure interprétation
# décalage du spectre d'amplitude (spectre dit centré):
# le spectre d'amplitude est défini pour des fréquences u et v
# normalisées et tq -1/2<u<1/2 et -1/2<v<1/2
tfd_w = np.fft.fft2(Z);
magnitude_spectrum = np.abs(np.fft.fftshift(tfd_w))
plt.figure()
plt.subplot(121), plt.imshow(Z, cmap='gray')
plt.title('Mire sinusoïdale'), plt.xlabel('n - axe x'), plt.ylabel('m - axe y')
plt.subplot(122), plt.imshow(np.log2(1 + magnitude_spectrum), origin=('upper'), extent=(-0.5, 0.5, 0.5, -0.5),
cmap='jet')
# attention à bien renseigner le paramètre extent.
# Bien saisir extent=(-0.5,0.5,0.5,-0.5) et non pas l'inverse !!!
plt.title('Spectre d''amplitude'), plt.xlabel('u'), plt.ylabel('v')
plt.show()
# Remarque 1 : Ce graphe permet une meilleure visualisation et donc une meilleure
# interpretation car les basses fréquences se trouvent désormais au centre
# et les hautes fréquences autour.
# Remarque 2 : on observe bien deux pics fréquentiels, l'un en u=0.031 et v=0.078
# et l'autre en u=-0.031 et v=-0.078. Les deux pics sont en fait des sinc du fait
# de la troncature rectangulaire implicite
# %% Zéro-padding : permet de mieux visualiser le spectre en rajoutant des points
# (fréquences)
# de calcul dans le calcul de la FFT. Cette opération ne modifie pas le spectre,
# c'est le même sauf qu'en rajoutant des points de calcul, on affiche la TF pour
# des fréquences intermédiaires, du coup on a une meilleure précision.
tfd_w512 = np.fft.fft2(Z);
magnitude_spectrum512 = np.abs(tfd_w512);
tfd_w1024 = np.fft.fft2(Z, (1024, 1024));
magnitude_spectrum1024 = np.abs(tfd_w1024);
magnitude_spectrum_shifted_512 = np.fft.fftshift(magnitude_spectrum512);
magnitude_spectrum_shifted_1024 = np.fft.fftshift(magnitude_spectrum1024);
plt.figure()
plt.subplot(121), plt.imshow(np.log2(1 + magnitude_spectrum_shifted_512), extent=(-0.5, 0.5, 0.5, -0.5), cmap='jet')
plt.title('Spectre d\'amplitude shifté'), # plt.colorbar()
plt.xlabel('u'), plt.ylabel('v');
plt.show()
plt.subplot(122), plt.imshow(np.log2(1 + magnitude_spectrum_shifted_1024), extent=(-0.5, 0.5, 0.5, -0.5), cmap='jet')
plt.title('Spectre d\'amplitude shifté avec zero-padding'), # plt.colorbar()
plt.xlabel('u'), plt.ylabel('v');
plt.show()
# %%Extension à des images réelles présentant des périodicités
im1 = cv2.imread('Data/D1.tif', 0);
im2 = cv2.imread('Data/D4.tif', 0);
# im1=cv2.imread('../DATA/crayons.jpg',0);
# im2=cv2.imread('../DATA/bibliotheque.jpg',0);
# im3=cv2.imread('pollen.jpg',0);
# im2=cv2.imread('../DATA/neige.JPG',0);
TF1 = np.fft.fft2(im1);
spectre1s = np.abs(np.fft.fftshift(TF1))
TF2 = np.fft.fft2(im2);
spectre2s = np.abs(np.fft.fftshift(TF2))
plt.figure()
plt.subplot(221), plt.imshow(im1, cmap='gray')
plt.title('Input image')
plt.subplot(222), plt.imshow(np.log2(1 + spectre1s), extent=(-0.5, 0.5, 0.5, -0.5), cmap='jet')
plt.title('Spectre d\'amplitude'), plt.colorbar()
plt.subplot(223), plt.imshow(im2, cmap='gray')
plt.title('Input image')
plt.subplot(224), plt.imshow(np.log2(1 + spectre2s), extent=(-0.5, 0.5, 0.5, -0.5), cmap='jet')
plt.title('Spectre d''amplitude'), plt.colorbar()
plt.show()
# - le spectre d'amplitude de l'image crayons présente 3 particularités.
# Tout d'abord une très forte concentration de l'énergie pour des couples de
# fréquences (u,v) multiples de (0.13,-0.09) ce qui laisse supposer une périodicité
# dans l'image de périodes spatiales (1/0.13, 1/0.09) pixels dans la direction "45°"
# soit 7.7 pixels selon x et 11.1 pixels selon y dans la direction "45°" ce qui
# correspond vraisemblablement aux crayons de couleur. Deuxièmement, on décèle deux
# traits lumineux, l'un en u=0 et l'autre en v=0. Or d'après le cours, on en déuit
# que l'on a deux "lames lumineuses" dans l'image. Celles-ci sont dues aux bords de
# l'image qui présentent de fortes variations si on considère les 1ère et dernière
# lignes et 1ères et dernières colonnes. Enfin, on remarque des sortes de croix composées
# de petites lames "parallèles" d'énergie qui se répètent, croix centrées autour des
# fréquences multiples de (0.13,-0.09). On peut les relier aux pointes des crayons.
# - le spectre de l'image bibliothèque présente également un spectre de raies
# d'espacement v=0.03 environ ce qui laisse supposer une périodicité spatiale de
# période 1/0.03 pixels soit 33 pixels verticalement et effectivement les étagères
# sont espacées d'a peu près 30 pixels ! on devine également une bande diagonale d'énergie,
# que l'on peut assoscier aux livres qui sont penchés. On remarque ensuite deux pics
# d'énergie en u=0.18 cycles par pixel et v=0 ce qui correspond à une périodicité
# selon x de 5 pixels environ, que l'on peut associer aux livres verticaux dont la
# taille est environ de 5 pixels.
# Transformée de Fourier et interprétation
# voir tutoriaux python-OpenCV
plt.close('all')
# %%création d'une image composée d'une sinusoïde
fx, fy = 0.03, 0.08; # fréquences définissant la sinusoïde données en cycles par
# pixel. Il faut les multiplier par le nombre de pixels par ligne et par colonne
# pour les avoir en cycles par image.
Z = np.fromfunction(lambda m, n: np.sin(2 * np.pi * (fx * n + fy * m)), (512, 512))
plt.figure()
plt.imshow(Z, cmap='gray'), plt.title('Mire sinusoïdale'), plt.xlabel('x'), plt.ylabel('y'),
plt.show()
# En comptant les cycles (<=> périodes) sur chaque axe,
# on trouve nb_cycles_x=16 env et nb_cycles_y=41 env, ce qui correspond à
# fx=0.031 env et fy=0.08 (vous devez bien comprendre la signification des
# fréquences spatiales!)
# %% calcul de la TFD-2D avec numpy
tfd_w = np.fft.fft2(Z);
# la transformée de Fourier est calculée pour des fréquences u et v normalisées
# entre 0 et 1 -
# (fréquence horizontale (verticale) <=> variation de niveaux de gris selon x
# (y) respectivement)
# calcul du spectre d'amplitude:
# le spectre d'amplitude défini pour des fréquences u et v
# normalisées et tq 0<u<1 et 0<v<1 est donc donné par:
magnitude_spectrum = np.abs(tfd_w);
# visualisation du spectre
plt.figure()
plt.subplot(121), plt.imshow(Z, cmap='gray')
plt.title('Mire sinusoïdale'), plt.xlabel('n - axe x'), plt.ylabel('m - axe y')
plt.subplot(122), plt.imshow(np.log2(1 + magnitude_spectrum), origin=('upper'), extent=(0, 1, 1, 0), cmap='jet')
# sans extent(0,1,1,0), les axes sont référencés en nombre de points et non pas
# en fréquences normalisées entre 0 et 1 pour chaque axe. Bien renseigner ce
# champ extent est essentiel pour bien interpréter le spectre
# Bien noter que la syntaxe pour extent est (left, right, bottom, top). Comme
# l'axe y va vers le bas il faut saisir extent(0,1,1,0) et non pas extent(0,1,0,1)
plt.title('Spectre d''amplitude avec numpy'), plt.xlabel('u'), plt.ylabel('v')
plt.show()
# calcul de la TFD-2D et de son module (spectre d'amplitude) avec OpenCV
tfd_w = cv2.dft(np.float32(Z), flags=cv2.DFT_COMPLEX_OUTPUT)
# de même la TFD2D est ici calculée pour des fréquences entre 0 et 1
magnitude_spectrum = cv2.magnitude(tfd_w[:, :, 0], tfd_w[:, :, 1])
plt.figure()
plt.subplot(121), plt.imshow(Z, cmap='gray')
plt.title('Mire sinusoïdale'), plt.xlabel('n - axe x'), plt.ylabel('m - axe y')
plt.subplot(122), plt.imshow(np.log2(1 + magnitude_spectrum), origin=('upper'), extent=(0, 1, 1, 0), cmap='jet')
plt.title('Spectre d''amplitude avec OpenCV'), # plt.colorbar()
plt.xlabel('u'), plt.ylabel('v');
plt.show()
# %%
# visualisation du spectre centré pour une meilleure interprétation
# décalage du spectre d'amplitude (spectre dit centré):
# le spectre d'amplitude est défini pour des fréquences u et v
# normalisées et tq -1/2<u<1/2 et -1/2<v<1/2
tfd_w = np.fft.fft2(Z);
magnitude_spectrum = np.abs(np.fft.fftshift(tfd_w))
plt.figure()
plt.subplot(121), plt.imshow(Z, cmap='gray')
plt.title('Mire sinusoïdale'), plt.xlabel('n - axe x'), plt.ylabel('m - axe y')
plt.subplot(122), plt.imshow(np.log2(1 + magnitude_spectrum), origin=('upper'), extent=(-0.5, 0.5, 0.5, -0.5),
cmap='jet')
# attention à bien renseigner le paramètre extent.
# Bien saisir extent=(-0.5,0.5,0.5,-0.5) et non pas l'inverse !!!
plt.title('Spectre d''amplitude'), plt.xlabel('u'), plt.ylabel('v')
plt.show()
# Remarque 1 : Ce graphe permet une meilleure visualisation et donc une meilleure
# interpretation car les basses fréquences se trouvent désormais au centre
# et les hautes fréquences autour.
# Remarque 2 : on observe bien deux pics fréquentiels, l'un en u=0.031 et v=0.078
# et l'autre en u=-0.031 et v=-0.078. Les deux pics sont en fait des sinc du fait
# de la troncature rectangulaire implicite
# %% Zéro-padding : permet de mieux visualiser le spectre en rajoutant des points
# (fréquences)
# de calcul dans le calcul de la FFT. Cette opération ne modifie pas le spectre,
# c'est le même sauf qu'en rajoutant des points de calcul, on affiche la TF pour
# des fréquences intermédiaires, du coup on a une meilleure précision.
tfd_w512 = np.fft.fft2(Z);
magnitude_spectrum512 = np.abs(tfd_w512);
tfd_w1024 = np.fft.fft2(Z, (1024, 1024));
magnitude_spectrum1024 = np.abs(tfd_w1024);
magnitude_spectrum_shifted_512 = np.fft.fftshift(magnitude_spectrum512);
magnitude_spectrum_shifted_1024 = np.fft.fftshift(magnitude_spectrum1024);
plt.figure()
plt.subplot(121), plt.imshow(np.log2(1 + magnitude_spectrum_shifted_512), extent=(-0.5, 0.5, 0.5, -0.5), cmap='jet')
plt.title('Spectre d\'amplitude shifté'), # plt.colorbar()
plt.xlabel('u'), plt.ylabel('v');
plt.show()
plt.subplot(122), plt.imshow(np.log2(1 + magnitude_spectrum_shifted_1024), extent=(-0.5, 0.5, 0.5, -0.5), cmap='jet')
plt.title('Spectre d\'amplitude shifté avec zero-padding'), # plt.colorbar()
plt.xlabel('u'), plt.ylabel('v');
plt.show()
# %%Extension à des images réelles présentant des périodicités
im1 = cv2.imread('Data/D1.tif', 0);
im2 = cv2.imread('Data/D4.tif', 0);
# im1=cv2.imread('../DATA/crayons.jpg',0);
# im2=cv2.imread('../DATA/bibliotheque.jpg',0);
# im3=cv2.imread('pollen.jpg',0);
# im2=cv2.imread('../DATA/neige.JPG',0);
TF1 = np.fft.fft2(im1);
spectre1s = np.abs(np.fft.fftshift(TF1))
TF2 = np.fft.fft2(im2);
spectre2s = np.abs(np.fft.fftshift(TF2))
plt.figure()
plt.subplot(221), plt.imshow(im1, cmap='gray')
plt.title('Input image')
plt.subplot(222), plt.imshow(np.log2(1 + spectre1s), extent=(-0.5, 0.5, 0.5, -0.5), cmap='jet')
plt.title('Spectre d\'amplitude'), plt.colorbar()
plt.subplot(223), plt.imshow(im2, cmap='gray')
plt.title('Input image')
plt.subplot(224), plt.imshow(np.log2(1 + spectre2s), extent=(-0.5, 0.5, 0.5, -0.5), cmap='jet')
plt.title('Spectre d''amplitude'), plt.colorbar()
plt.show()