#!/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()