import matplotlib.pyplot as plt
M = plt.imread("vig042.png")
plt.imshow(M)
plt.axis("off")
plt.show()
plt.rcParams['figure.figsize'] = [6, 6]
source = plt.imread("surfeur256.png")
plt.imshow(source)
plt.axis("off")
plt.show()
def taille(M):
return len(M), len(M[0])
def mystr(k):
S = str(k)
return (3 - len(S)) * "0" + S
mystr(42)
'042'
def name(k):
return "vig" + mystr(k) + ".png"
name(42)
'vig042.png'
def moyenne(L):
s = 0
for elt in L:
s += elt
return s / len(L)
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])
M = [[[1, 0, 0], [0, 1, 0]], [[1, 0, 1], [1, 1, 0]]]
pixel_moyen(M)
[0.75, 0.5, 0.25]
Vmoy = []
for k in range(1000):
vignette = plt.imread(name(k))
Pm = pixel_moyen(vignette)
Vmoy.append(Pm)
def distance(P, Q):
return ((P[0] - Q[0])**2 + (P[1] - Q[1])**2 + (P[2] - Q[2])**2)**0.5
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
best([1,1,1])
623
def mozaic(M):
m, n = taille(M)
return [[best(M[i][j]) for j in range(n)] for i in range(m)]
N = mozaic(source)
taille(N)
(256, 256)
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]
.
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
plt.rcParams['figure.figsize'] = [20, 20]
P = photomozaic(N, 64)
plt.imshow(P)
plt.axis("off")
plt.show()
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
dico = compte(N)
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.
import random as rd
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]<dmin+eps]
return rd.choice(echantillon)
N = mozaic(source)
plt.rcParams['figure.figsize'] = [20, 20]
P = photomozaic(N, 64)
plt.imshow(P)
plt.axis("off")
plt.show()
def extract(P, k, l, s):
return [P[q][l:l + s] for q in range(k, k + s)]
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
plt.rcParams['figure.figsize'] = [6, 6]
S = demozaic(P, 64)
plt.imshow(S)
plt.axis("off")
plt.show()