C’est très facile de faire une photomosaïque comme celle ci-contre. Des sites comme Pictosaic juxtaposent en quelques secondes des centaines d’images pour approximer une image de base.
Par exemple, voici un détail du goulot du bécher ci-contre:

Le programme produit un résultat sous forme d’une image composée d’une ligne pour chaque image unique, avec à côté toutes les copies de cette image identifiées par le programme.
Le programme Python est ci-dessous, il est relativement simple, à l’exception de la fonction permettant de comparer les images pour laquelle j’ai pas mal ramé, et il reste un seuil numérique à ajuster au cas par cas, mais dans l’ensemble ça marche…
A quoi ça sert tout ça ? Outre à tester le traitement d’image en Python avec PIL, c’est pour gagner un concours, mais je ne vous dirai pas (encore) lequel

import Image; #PIL
import ImageChops;
import ImageStat;
import math;
im = Image.open("mosaic.jpg")
smallx=40; smally=40;
border=1; #ignore border of picture
print im.size[0],im.size[1]
n=(im.size[0]/smallx)*(im.size[0]/smally)
nx=math.sqrt(n)
res=Image.new(im.mode,(smallx*nx,smally*n))
L=[]; jmax=0;
y=0;
while y<im.size[1]:
x=0;
while x<im.size[0]:
box = (x+border, y+border, x+smallx-border, y+smally-border)
mini = im.crop(box)
mininb=ImageOps.equalize(mini.convert('L'))
min=1000;
for i in range(len(L)):
rms=ImageStat.Stat(
ImageChops.difference(
mininb,L[i][0]
)
).mean[0]
if rms<min: f=i; min=rms;
if min<30: #this must be tuned for each case ...
j=L[f][1]
L[f][1]=j+1
else:
j=0
f=len(L)
L.append([mininb,1])
if j>jmax: jmax=j;
box = (smallx*j+border, smally*f+border)
res.paste(mini,box);
x=x+smallx
print '.',
y=y+smally
res.crop((0,0,(jmax+1)*smallx,len(L)*smally)).save('result.jpg')
print 'DONE!'
print len(L),'different images over',n,'max',jmax+1,'copies'
res.crop((0,0,(jmax+1)*smallx,len(L)*smally)).save('result.jpg')
print len(L),'different images over',n,'max',jmax+1,'copies'
Posted in Casse-Têtes, Photo, Programmation
