TP1.ipynb 24.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# TP1 : quantification, histogramme et égalisation, interpolation, couleur\n",
    "\n",
    "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.\n",
    "\n",
11
    "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.\n",
12
13
14
15
16
    "\n",
    "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.\n",
    "\n",
    "Ce TP est à réaliser en deux séances d'1h30.\n",
    "\n",
17
18
19
20
    "**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...\n",
    "\n",
    "**Autre remarque:** Il y a parfois plusieurs sous-questions dans une même question. <u>Pensez a répondre à toutes les sous-questions</u>.\n",
    "\n",
21
22
23
24
25
26
27
    "## Manipulation d'image\n",
    "\n",
    "- Nous allons commencer par charger et afficher une image à l'aide du code ci-dessous."
   ]
  },
  {
   "cell_type": "code",
28
   "execution_count": 3,
29
   "metadata": {
30
31
    "scrolled": false,
    "tags": []
32
33
34
   },
   "outputs": [
    {
35
     "output_type": "display_data",
36
     "data": {
37
38
39
40
41
42
      "text/plain": "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …",
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "46497d5f771f40309983921b059a24bc"
      }
43
     },
44
     "metadata": {}
45
46
    },
    {
47
     "output_type": "execute_result",
48
     "data": {
49
      "text/plain": "<matplotlib.image.AxesImage at 0x11e245048>"
50
51
     },
     "metadata": {},
52
     "execution_count": 3
53
54
55
    }
   ],
   "source": [
56
    "%matplotlib widget\n",
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    "# la ligne précédente permet d'afficher les figures directement dans votre notebook et de pouvoir interagir avec\n",
    "\n",
    "from skimage import io # on charge le module permettant d'ouvrir des images\n",
    "import matplotlib.pyplot as plt # gestion des figures\n",
    "\n",
    "im = io.imread('talvi.jpg')\n",
    "plt.imshow(im)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 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",
75
76
77
78
   "execution_count": 4,
   "metadata": {
    "tags": []
   },
79
80
81
   "outputs": [
    {
     "output_type": "stream",
82
83
     "name": "stdout",
     "text": "type de données utilisé: <class 'numpy.ndarray'>\nnombre de dimensions de l'image: 3\ndimensions: (400, 300, 3)\n"
84
85
    }
   ],
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
   "source": [
    "print(\"type de données utilisé:\", type(im))\n",
    "print(\"nombre de dimensions de l'image:\",im.ndim)\n",
    "print(\"dimensions:\", im.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 1:** Expliquez les dimensions affichée pour l'image d'exemple."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
103
    "**Réponse 1:** VOTRE REPONSE ICI"
104
105
106
107
108
109
110
111
112
113
114
115
116
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**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",
   "metadata": {},
   "source": [
117
    "**Réponse 2:** VOTRE REPONSE ICI"
118
119
120
121
   ]
  },
  {
   "cell_type": "code",
122
   "execution_count": 5,
123
   "metadata": {
124
125
    "scrolled": false,
    "tags": []
126
127
128
   },
   "outputs": [
    {
129
     "output_type": "display_data",
130
     "data": {
131
132
133
134
135
136
      "text/plain": "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …",
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "eae0881650074ad480727c722a666169"
      }
137
     },
138
     "metadata": {}
139
140
    },
    {
141
     "output_type": "display_data",
142
     "data": {
143
144
145
146
147
148
      "text/plain": "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …",
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "0e76eb910bde4f789f167120d9426806"
      }
149
     },
150
     "metadata": {}
151
152
    },
    {
153
     "output_type": "display_data",
154
     "data": {
155
156
157
158
159
160
      "text/plain": "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …",
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "a2ad1dc1ed204a948ecb629bc08dda31"
      }
161
     },
162
     "metadata": {}
163
164
165
    },
    {
     "output_type": "stream",
166
167
     "name": "stdout",
     "text": "4.314527777777777\n"
168
169
    },
    {
170
     "output_type": "execute_result",
171
     "data": {
172
      "text/plain": "Text(0.5, 1.0, 'différence')"
173
174
     },
     "metadata": {},
175
     "execution_count": 5
176
177
178
179
180
181
182
183
    }
   ],
   "source": [
    "from skimage import color # fonctions de conversion de couleur\n",
    "\n",
    "\n",
    "# Traitement des images\n",
    "im_gris1=im.mean(2)\n",
184
    "im_gris2=(color.rgb2grey(im)*255).astype('uint8') #rgb2grey renvoie une image avec 0<= valeurs <=1\n",
185
186
187
188
189
190
191
192
193
    "diff=abs(im_gris1-im_gris2)\n",
    "\n",
    "# Affichage sous forme de différentes figures (attention les numéros de figure sont valables dans tout le notebook)\n",
    "plt.figure(2)\n",
    "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\n",
    "plt.title(\"moyenne\")\n",
    "\n",
    "plt.figure(3)\n",
    "plt.imshow(im_gris2, cmap=plt.cm.gray)\n",
194
    "plt.title(\"rgb2grey\")\n",
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
    "\n",
    "plt.figure(4)\n",
    "print(diff.mean())\n",
    "plt.imshow(diff, cmap=plt.cm.gray)\n",
    "plt.title(\"différence\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Quantification\n",
    "\n",
    "### Comment ça marche ?\n",
    "\n",
    "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",
215
   "execution_count": 6,
216
217
218
219
220
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
221
     "output_type": "display_data",
222
     "data": {
223
224
225
226
227
228
      "text/plain": "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …",
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "09b301d33d354299991bda2ee1f6349d"
      }
229
     },
230
     "metadata": {}
231
232
    },
    {
233
     "output_type": "execute_result",
234
     "data": {
235
      "text/plain": "Text(0.5, 1.0, 'requantifié Q=32')"
236
237
     },
     "metadata": {},
238
     "execution_count": 6
239
240
241
242
243
244
245
246
247
248
    }
   ],
   "source": [
    "import numpy as np # manipulation des ndarray\n",
    "\n",
    "# Init \n",
    "Q=32\n",
    "im = io.imread('talvi.jpg')\n",
    "\n",
    "# Traitements \n",
249
    "im_gris=(color.rgb2grey(im)*255).astype('uint8')\n",
250
251
    "im_requantifiee = Q * np.round(im_gris/Q)\n",
    "\n",
252
    "# Affichage sous forme de différentes sous figures\n",
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
    "plt.figure()  #les numéros de figure ne sont pas obligatoires\n",
    "\n",
    "plt.subplot(121) # 121 = 1 ligne, 2 colonnes, 1ère sous figure\n",
    "plt.imshow(im_gris, cmap=plt.cm.gray)\n",
    "plt.title(\"image de départ\")\n",
    "\n",
    "plt.subplot(122) # 122 = 1 ligne, 2 colonnes, 2ème sous figure\n",
    "plt.imshow(im_requantifiee, cmap=plt.cm.gray)\n",
    "plt.title(\"requantifié Q=\" + str(Q))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 3:** Visualiser l'effet de cette opération pour Q=2, puis Q=38 et Q=71."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
275
    "**Réponse 3:** VOTRE REPONSE ICI"
276
277
278
279
280
281
282
283
284
285
286
287
288
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 4:** Montrer que cet algorithme réalise de la compression d'images avec perte."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
289
    "**Réponse 4:** VOTRE REPONSE ICI"
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comment mesurer la dégradation ?\n",
    "\n",
    "**Question 5:** Cette dégration visuelle (évaluation subjective de votre part) est-t-elle perceptible pour des quantifications (`Q`) faibles ?\n",
    "\n",
    "On pourrait qualifier objectivement et numériquement la dégradation par différentes mesures d'erreur (cf. code ci-dessous)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
307
    "**Réponse 5:** VOTRE REPONSE ICI"
308
309
310
311
   ]
  },
  {
   "cell_type": "code",
312
   "execution_count": 7,
313
   "metadata": {
314
315
    "scrolled": true,
    "tags": []
316
317
318
   },
   "outputs": [
    {
319
     "output_type": "stream",
320
321
     "name": "stdout",
     "text": "erreur quadratique moyenne (mse): 85.842175\nrapport signal bruit (psnr): 28.793796479662667\nsimilarité structurelle (ssim): 0.8808622932284417\n"
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
    }
   ],
   "source": [
    "from skimage import measure # fonctions de mesure d'erreur\n",
    "\n",
    "err_quad=measure.compare_mse(im_gris, im_requantifiee)\n",
    "print(\"erreur quadratique moyenne (mse):\", err_quad)\n",
    "psnr=measure.compare_psnr(im_gris/255, im_requantifiee/255) # compare_psnr a besoin d'images avec des 0 <= valeur <=1\n",
    "print(\"rapport signal bruit (psnr):\", psnr)\n",
    "ssim=measure.compare_ssim(im_gris, im_requantifiee)\n",
    "print(\"similarité structurelle (ssim):\", ssim)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**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",
   "metadata": {},
   "source": [
346
    "**Réponse 6:** VOTRE REPONSE ICI"
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## Histogramme, seuillage\n",
    "\n",
    "Le script ci-dessous calcule et affiche l'histogramme des niveaux de gris d'une image, après quantification uniforme en N boites.\n",
    "\n",
    "** 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",
   "metadata": {},
   "source": [
366
    "**Réponse 7:** VOTRE REPONSE ICI"
367
368
369
370
   ]
  },
  {
   "cell_type": "code",
371
   "execution_count": 8,
372
373
374
   "metadata": {},
   "outputs": [
    {
375
     "output_type": "display_data",
376
     "data": {
377
378
379
380
381
382
      "text/plain": "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …",
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "612b6c7d994f4d749b13a5c117a5e5f0"
      }
383
     },
384
     "metadata": {}
385
386
    },
    {
387
     "output_type": "execute_result",
388
     "data": {
389
      "text/plain": "<BarContainer object of 256 artists>"
390
391
     },
     "metadata": {},
392
     "execution_count": 8
393
394
395
396
397
398
399
    }
   ],
   "source": [
    "from skimage import exposure\n",
    "\n",
    "N = 256 # Expérimenter avec d'autres valeurs\n",
    "im = io.imread('talvi.jpg') # Expérimenter avec d'autres images\n",
400
    "im_gris=(color.rgb2grey(im)*255).astype('uint8') # transcodage de l'image en uint8 pour avec un histogramme discret\n",
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
    "\n",
    "(histo, bin_centers)=exposure.histogram(im_gris,N)\n",
    "plt.figure()\n",
    "plt.bar(np.arange(N), histo)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "** 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",
   "metadata": {},
   "source": [
418
    "**Réponse 8:** VOTRE REPONSE ICI"
419
420
421
422
423
424
425
426
427
428
429
430
431
432
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "** 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",
   "metadata": {},
   "source": [
433
    "**Réponse 9:** VOTRE REPONSE ICI"
434
435
436
437
   ]
  },
  {
   "cell_type": "code",
438
   "execution_count": 9,
439
   "metadata": {},
440
441
   "outputs": [
    {
442
     "output_type": "display_data",
443
     "data": {
444
445
446
447
448
449
      "text/plain": "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …",
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "868c4d8f0b4740afb674eb5b981e8aa3"
      }
450
     },
451
     "metadata": {}
452
453
    },
    {
454
     "output_type": "execute_result",
455
     "data": {
456
      "text/plain": "<matplotlib.image.AxesImage at 0x1201c75f8>"
457
458
     },
     "metadata": {},
459
     "execution_count": 9
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
    }
   ],
   "source": [
    "SEUIL = 75\n",
    "\n",
    "# une double boucle (lente)  pour effectuer notre traitement sur chaque pixel\n",
    "im_thresholded = np.zeros( im_gris.shape )\n",
    "largeur = im_gris.shape[1]\n",
    "hauteur = im_gris.shape[0]\n",
    "\n",
    "for y in range(0, hauteur):\n",
    "    for x in range(0, largeur):\n",
    "        if im_gris[y][x] > SEUIL:\n",
    "            im_thresholded[y][x] = 255\n",
    "        else:\n",
    "            im_thresholded[y][x] = 0\n",
    "\n",
    "# On peut aussi remplacer la double boucle précédente par ceci\n",
    "#im_thresholded = (im_gris > SEUIL)*255\n",
    "\n",
    "plt.figure()\n",
    "plt.imshow(im_thresholded, cmap=plt.cm.gray)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "** 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",
493
   "execution_count": 10,
494
495
496
   "metadata": {},
   "outputs": [],
   "source": [
497
    "# VOTRE CODE ICI"
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Restauration par transformation de l'intensité : égalisation d'histogramme\n",
    "\n",
    "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.\n",
    "\n",
    "**Question 11:** Exécuter le script ci-dessous et interprétez les résultats pour l'image `essai.jpg`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
515
    "**Réponse 11:** VOTRE REPONSE ICI"
516
517
518
519
   ]
  },
  {
   "cell_type": "code",
520
   "execution_count": 18,
521
522
523
524
525
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
526
     "output_type": "display_data",
527
     "data": {
528
529
530
531
532
533
      "text/plain": "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …",
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "717e35d584c84bac9aa9f286f37ebde0"
      }
534
     },
535
     "metadata": {}
536
537
    },
    {
538
     "output_type": "execute_result",
539
     "data": {
540
      "text/plain": "Text(0.5, 1.0, 'histogramme cumulé')"
541
542
     },
     "metadata": {},
543
     "execution_count": 18
544
545
    }
   ],
546
   "source": [
547
    "plt.rcParams['figure.subplot.hspace'] = 0.8 # espace un peu les sous-figures verticalement\n",
548
549
550
551
552
    "from skimage import exposure\n",
    "nb_bins=256\n",
    "\n",
    "# Chargement de l'image\n",
    "im = io.imread('low.png') # Expérimenter avec d'autres images\n",
553
    "im_gris=(color.rgb2grey(im)*255.0).astype('uint8') # transcodage de l'image en uint8 pour avec un histogramme discret\n",
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
    "\n",
    "# Histogramme normale et cumulé de l'image de départ\n",
    "im_gris_histo, im_bins = exposure.histogram( im_gris, nb_bins )\n",
    "im_gris_cumul, im_cumul_bins = exposure.cumulative_distribution( im_gris, nb_bins )\n",
    "\n",
    "# Egalisation + histogramme\n",
    "im_eq = exposure.equalize_hist(im_gris,nb_bins)\n",
    "im_eq_histo, im_bins = exposure.histogram( im_eq, nb_bins )\n",
    "im_eq_cumul, im_cumul_bins = exposure.cumulative_distribution( im_eq, nb_bins )\n",
    "\n",
    "# Affichage\n",
    "plt.figure()\n",
    "plt.subplot(321)\n",
    "plt.imshow(im_gris, cmap=plt.cm.gray)\n",
    "plt.title(\"image de départ\")\n",
    "\n",
    "plt.subplot(322)\n",
    "plt.imshow(im_eq, cmap=plt.cm.gray)\n",
    "plt.title(\"image egalisée\")\n",
    "\n",
    "plt.subplot(323)\n",
575
    "plt.bar(np.arange(im_gris_histo.size), im_gris_histo)\n",
576
577
578
    "plt.title(\"histogramme\")\n",
    "\n",
    "plt.subplot(324)\n",
579
    "plt.bar(np.arange(im_eq_histo.size), im_eq_histo)\n",
580
581
582
    "plt.title(\"histogramme\")\n",
    "\n",
    "plt.subplot(325)\n",
583
    "plt.bar(np.arange(im_gris_cumul.size), im_gris_cumul )\n",
584
585
586
    "plt.title(\"histogramme cumulé\")\n",
    "\n",
    "plt.subplot(326)\n",
587
    "plt.bar(np.arange(im_eq_cumul.size), im_eq_cumul )\n",
588
589
590
591
592
593
594
595
596
597
598
599
600
601
    "plt.title(\"histogramme cumulé\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 12**: Pourquoi l'histogramme après égalisation n'est il pas tout à fait plat ?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
602
    "**Réponse 12:** VOTRE REPONSE ICI"
603
604
605
606
607
608
609
610
611
612
613
614
615
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 13:** Est-il correct d'affirmer que cette transformation s'écrit sous la forme $I_{sortie}(x,y)=transformation(I_{entree}(x,y))$ ?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
616
    "**Réponse 13:** VOTRE REPONSE ICI"
617
618
619
620
621
622
623
624
625
626
627
628
629
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 15:** La transformation est-elle linéaire ?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
630
    "**Réponse 15:** VOTRE REPONSE ICI"
631
632
633
634
635
636
637
638
639
640
641
642
643
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 16:** S'adapte-t-elle automatiquement à l'image traitée ?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
644
    "**Réponse 16:** VOTRE REPONSE ICI"
645
646
647
648
649
650
651
652
653
654
655
656
657
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 17:** Selon vous, quels sont les contenus d'images pour lesquels l'égalisation d'histogramme est très (ou très peu) efficace ? Tentez d'en trouver sur le web et de leur appliquer l'algorithme d'égalisation."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
658
    "**Réponse 17:** VOTRE REPONSE ICI"
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Agrandissement d'image\n",
    "\n",
    "La numérisation des images procède à une discrétisation spatiale, en posant une grille discrète de pixels sur une réalité initialement continue. De nombreuses tâches ont besoin de déterminer l'intensité de l'image en des coordonnées \"non entières\". Pour estimer cette intensité, on s'appuie souvent sur une hypothèse sur la fonction \"luminance\": sa continuité, continuité de sa dérivée, etc.\n",
    "\n",
    "Le script ci-dessous agrandit une image selon deux méthodes : réplication et interpolation bilinéaire."
   ]
  },
  {
   "cell_type": "code",
674
   "execution_count": 15,
675
   "metadata": {},
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
   "outputs": [
    {
     "output_type": "display_data",
     "data": {
      "text/plain": "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …",
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "49e6dd90320a4b7dac4d36bb31e43a33"
      }
     },
     "metadata": {}
    },
    {
     "output_type": "execute_result",
     "data": {
      "text/plain": "Text(0.5, 1.0, 'Interpolation bilinéaire')"
     },
     "metadata": {},
     "execution_count": 15
    }
   ],
698
699
700
701
   "source": [
    "plt.rcParams['image.interpolation'] = 'nearest' # pour ne par faire d'interpolation lors du zoom sur les figures \n",
    "# Chargement de l'image\n",
    "im = io.imread('talvi.jpg') # Expérimenter avec d'autres images\n",
702
    "im_gris=color.rgb2grey(im)*255\n",
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
    "\n",
    "largeur = im_gris.shape[1]\n",
    "hauteur = im_gris.shape[0]\n",
    "\n",
    "# Réplication\n",
    "im_2x_replic = np.zeros( (hauteur*2,largeur*2) )\n",
    "\n",
    "for y in range(0, hauteur):\n",
    "    for x in range(0, largeur):\n",
    "        xx=2*x\n",
    "        yy=2*y\n",
    "        \n",
    "        im_2x_replic[yy][xx] = im_gris[y][x]\n",
    "        im_2x_replic[yy][xx+1] = im_gris[y][x]\n",
    "        im_2x_replic[yy+1][xx] = im_gris[y][x]\n",
    "        im_2x_replic[yy+1][xx+1] = im_gris[y][x]\n",
    "        \n",
    "# Interpolation bilinéaire\n",
    "im_2x_bilin = np.zeros( (hauteur*2,largeur*2) )\n",
    "\n",
    "for y in range(0, hauteur-1):\n",
    "    for x in range(0, largeur-1):\n",
    "        xx=2*x\n",
    "        yy=2*y\n",
    "        \n",
    "        im_2x_bilin[yy][xx] = im_gris[y][x]\n",
    "        im_2x_bilin[yy][xx+1] = 0.5*(im_gris[y][x]+im_gris[y][x+1])\n",
    "        im_2x_bilin[yy+1][xx] = 0.5*(im_gris[y][x]+im_gris[y+1][x])\n",
    "        im_2x_bilin[yy+1][xx+1] = 0.25*(im_gris[y][x]+im_gris[y][x+1]+im_gris[y+1][x]+im_gris[y+1][x+1])\n",
    "        \n",
    "# Affichage\n",
    "plt.figure()\n",
    "\n",
    "plt.subplot(121)\n",
    "plt.imshow(im_2x_replic, cmap=plt.cm.gray)\n",
    "plt.title(\"Réplication\")\n",
    "\n",
    "plt.subplot(122)\n",
    "plt.imshow(im_2x_bilin, cmap=plt.cm.gray)\n",
    "plt.title(\"Interpolation bilinéaire\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 18**: Comparez la complexité algorithmique des deux méthodes et leur rendu visuel (zoomez sur des parties bien contrastées de l'image)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
756
    "**Réponse 18:** VOTRE REPONSE ICI"
757
758
759
760
761
762
763
764
765
766
767
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 19**: Comment faire une interpolation bilinéaire pour un zoom d'un facteur plus élevé que 2 ? (proposez une modification de l'algorithm initial)"
   ]
  },
  {
   "cell_type": "code",
768
   "execution_count": 13,
769
770
771
   "metadata": {},
   "outputs": [],
   "source": [
772
    "# VOTRE CODE ICI"
773
774
775
776
777
778
779
780
781
782
783
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Question 20**: Comment réduire par 2 les dimensions d'une image ? (proposez et mettez en oeuvre deux méthodes : l'une naive, et l'autre prenant en compte les considérations spectrales vues en traitement du signal)"
   ]
  },
  {
   "cell_type": "code",
784
   "execution_count": 14,
785
786
787
   "metadata": {},
   "outputs": [],
   "source": [
788
    "# VOTRE CODE ICI"
789
790
791
792
793
794
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
795
   "display_name": "Python 3.8.5 64-bit",
796
   "language": "python",
797
   "name": "python_defaultSpec_1599038455849"
798
799
800
801
802
803
804
805
806
807
808
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
809
   "version": "3.7.3-final"
810
811
812
813
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
814
}