Démosaïquification


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:

mosaicMais combien de petites images distinctes sont utilisées pour produire la mosaïque ? Pour répondre à cette question, j’ai développé un petit programme avec Python(x,y) en utilisant la “Python Imaging Library” (PIL)

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'
  • Merci pour les précisions

  • @Tibo : le smiley est un “Easter Egg” produit par le module de stats de WordPress. C’est un peu bizarre qu’ils aient fait ça, mais je préfère avoir des statistiques sur mes visiteurs, au prix d’un smiley 😉

  • Au fait c’est exprès le mini smiley noir sur le haut de la bande grise droite de votre bolg ?

  • Oui c’est vrai, je vais m’y mettre mieux que ça, merci beaucoup pour le coup d’œil en tout cas. à très bientôt.

  • J’ai fait quelques essais avec pictosaic, très efficace pour un traitement en ligne, si vous voulez y jeter un œil, j’ai mis deux grands formats sur mon blog photo : http://cmosmique.blogspot.com/
    Merci à bientôt

    • @Tibo : cool. mais faire des mosaïques à partir d’une seule image recoloriée, c’est de la triche. A mon humble avis, le sport dans la mosaïque c’est de trouver les petites images qui correspondent le mieux à la grande…

  • Python est-il assez rapide en traitement d’images ? J’utilise plus volontiers MATLAB personnellement …

    • @Tom : pas de doute, MatLab c’est la Rolls du pro. La librairie PIL n’arrive pas à la cheville de l’Image Processing Toolbox côté fonctionnalités, mais elle est gratuite… Côté vitesse, les deux langages sont interprétés avec des librairies numériques compilées, ça doit se valoir à quelque chose près
      En passant, un peu de pub pour SysQuake, le “compatible matlab” interactif de mon confrère Yves.

  • Je crois que je préfère la galaxie moche personnellement. Deux oublis dans le programme : il faut désactiver l’appel à la librairie Gifanimation qui ne sert à rien mais qui bloque ceux qui ne l’ont pas, et il faut mettre stroke(col) dans le setup plutôt que dans draw(). Très efficace en tout cas.

  • OUaaaa merci beaucoup vive Docteur Goulu héhé merci merci merci… hum pardon.
    à bientôt ; )

  • Joli !!!
    Processing peut être étendu à tout Java et par ailleurs il existe diverses librairies qui ont été développées pour apporter à processing des compétences dans des domaines du genre tracking de “blobs” ou détection de visages,… Je n’ai rien essayé de tout ça à vrai dire. La première qualité de processing pour moi, en tant qu’enseignant (en art) c’est l’immédiateté du résultat, les étudiants comprennent ce qu’ils font.

  • @Yogi : oui c’est pas encore top. D’une part je ça compare les images en niveaux de gris, pas les couleurs. D’autre part tout dépend de la valeur du seuil qu’on utilise pour considérer que deux images sont identiques ou distinctes. Rien que les artefacts induites par la compression jpeg créent des différences entre images…

    L’idéal serait de pouvoir ajuster ce seuil et de voir en temps réel le résultat, ce qui nous amène tout naturellement à …

    @Jean-no : … oui, processing est cool, je m’y suis mis il y a quelques temps mais il me manque des talents d’artiste. Voir:

    mon premier programme ici : http://www.openprocessing.org/visuals/?visualID=699

    ce qu’un vrai artiste en a fait : http://www.openprocessing.org/visuals/?visualID=700

    Par contre je ne sais pas s’il existe des librairies de traitement d’image aussi efficaces que la PIL sous Processing (si ça existe c’est probablement du Java)

  • Yogi

    Sans doute y a-t-il de subtiles différences entre les images non clarement visibles à l’oeil nu … L’image “love you” ou certains oiseaux par exemple apparaissent plusieurs fois dans le fichier de sortie comme des images différentes me semble-t-il …

  • Joli, ça semble court et efficace. Pour la programmation visuelle, il y a aussi Processing (hyper spécialisé) que les scientifiques devraient connaître : http://www.hyperbate.com/dernier/?page_id=2482
    ça a été inventé pour des artistes mais c’est très adapté à bien d’autres cas.