#!/usr/bin/env python # coding: utf-8 #
#
DS n°1 (photomosaïque) : Éléments de correction
# In[1]: import matplotlib.pyplot as plt # ## Partie I. Placement des vignettes # In[2]: M = plt.imread("vig042.png") plt.imshow(M) plt.axis("off") plt.show() # In[3]: plt.rcParams['figure.figsize'] = [6, 6] # In[4]: source = plt.imread("surfeur256.png") plt.imshow(source) plt.axis("off") plt.show() #
# Exercice 1 (2 pts) #
# In[5]: def taille(M): return len(M), len(M[0]) #
# Exercice 2 (3 pts) #
# In[6]: def mystr(k): S = str(k) return (3 - len(S)) * "0" + S # In[7]: mystr(42) #
# Attention : pour convertir un entier en chaîne de caractères, il ne suffit pas de lui rajouter des guillements... #
#
# Exercice 3 (2 pts) #
# In[8]: def name(k): return "vig" + mystr(k) + ".png" # In[9]: name(42) #
# La concaténation des chaînes de caractères se fait avec un +, pas une virgule. #
#
# Exercice 4 (3 pts) #
# In[10]: def moyenne(L): s = 0 for elt in L: s += elt return s / len(L) #
# Exercice 5 (3 pts) #
# In[11]: def pixel_moyen(M): Sr, Sg, Sb = 0, 0, 0 for ligne in M: for pixel in ligne: r, g, b = pixel Sr += r Sg += g Sb += b m, n = taille(M) nb = m * n return ([Sr / nb, Sg / nb, Sb / nb]) # In[12]: M = [[[1, 0, 0], [0, 1, 0]], [[1, 0, 1], [1, 1, 0]]] pixel_moyen(M) #
# On demandait d'adapter la fonction précédente, c'est-à-dire de reprendre son code et de le modifier pour obtenir votre nouvelle fonction. #
#
# Exercice 6 (3 pts) #
# In[13]: Vmoy = [] for k in range(1000): vignette = plt.imread(name(k)) Pm = pixel_moyen(vignette) Vmoy.append(Pm) #
# Beaucoup ont oublié le imread. #
#
# Exercice 7 (2 pts) #
# In[14]: def distance(P, Q): return ((P[0] - Q[0])**2 + (P[1] - Q[1])**2 + (P[2] - Q[2])**2)**0.5 #
# Exercice 8 (3 pts) #
# In[15]: def best(P): dmin = 2 # la distance max entre 2 pixels vaut sqrt(3)<2 ind = 0 for k in range(1000): d = distance(P, Vmoy[k]) if d < dmin: dmin = d ind = k return ind # In[16]: best([1,1,1]) #
# Il s'agissait ici de réutiliser la liste Vmoy dans la recherche du minimum. #
#
# Exercice 9 (3 pts) #
# In[17]: def mozaic(M): m, n = taille(M) return [[best(M[i][j]) for j in range(n)] for i in range(m)] # In[18]: N = mozaic(source) # In[19]: taille(N) #
# Revoir les listes de listes par compréhension. #
# ## Partie II. Construction et affichage de la photomosaïque #
# Exercice 10 (2 pts) #
# ```P[i * s + k][j * s + l]``` est en fait le pixel de position (k,l) dans la vignette dont le numéro est donné par ```N[i][j]```. #
# Exercice 11 (3 pts) #
# In[20]: def photomozaic(N, s): m, n = taille(N) P = [[0 for j in range(n * s)] for i in range(m * s)] for i in range(m): for j in range(n): vignette = plt.imread(name(N[i][j])) for k in range(s): for l in range(s): P[i * s + k][j * s + l] = vignette[k][l] return P # In[41]: plt.rcParams['figure.figsize'] = [20, 20] # In[42]: P = photomozaic(N, 64) plt.imshow(P) plt.axis("off") plt.show() # ## Partie III. Une amélioration possible #
# Exercice 12 (2 pts) #
# In[23]: def compte(N): dico = {} m, n = taille(N) for i in range(m): for j in range(n): nb = N[i][j] if nb in dico: dico[nb] += 1 else: dico[nb] = 1 return dico # In[24]: dico = compte(N) #
# Revoir le comptage du nombre d'occurences à l'aide d'un dictionnaire. #
#
# Exercice 13 (1 pt) #
# Il y a beaucoup de façons de faire, certaines plus élaborées que d'autres. # # Une technique simple est d'enlever une vignette dès qu'elle est trop utilisée, en se fixant un seuil à ne pas dépasser par exemple. # # On peut aussi, au lieu de choisir à chaque étape la vignette la plus proche en terme de pixel moyen, en prendre une au hasard dans un échantillon de quelques vignettes dont le pixel moyen est assez proche. #
# Exercice 14 (2 pts) #
# In[25]: import random as rd # In[26]: def best(P): dmin = 2 # la distance max entre 2 pixels vaut sqrt(3)<2 ind = 0 L = [] D = [] eps = 0.1 for k in range(1000): d = distance(P, Vmoy[k]) if d < dmin: dmin = d ind = k L.append(ind) D.append(d) echantillon = [L[-i] for i in range(1,len(L)+1) if D[-i]Partie IV. « Déphotomosaïcation » #
# Exercice 15 (2 pts) #
# In[29]: def extract(P, k, l, s): return [P[q][l:l + s] for q in range(k, k + s)] # In[30]: def demozaic(P, s): p, q = taille(P) m, n = p // s, q // s S = [[[0, 0, 0] for j in range(n)] for i in range(m)] for i in range(m): for j in range(n): vignette = extract(P, i * s, j * s, s) S[i][j] = pixel_moyen(vignette) return S # In[31]: plt.rcParams['figure.figsize'] = [6, 6] # In[32]: S = demozaic(P, 64) plt.imshow(S) plt.axis("off") plt.show()