IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Fabriquer des word clouds


Sujet :

Python

  1. #1
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut Fabriquer des word clouds
    Bonjour,
    je voudrais créer un module qui fabriquerait des "word clouds" comme on peut en voir ici. Au passage, ce site propose ici une applet Java pour créer ses "word clouds".

    Avec PIL, cela devrait se faire et j'avais déjà posé des questions à ce propos. Avez-vous des idées pour faire un tel module ? Il devrait y avoir différents modes de construction, et si l'on souhaite éviter le plus possible les espaces vides, cela devrait se compliquer un peu.

    Pour commencer, il faudrait arriver à connaître les coordonnées du rectangle minimal contenant une lettre mise dans une image avec PIL. Les lettres "p" et "m", avec la même mise en forme, auront deux boîtes de tailles différentes.

  2. #2
    Membre expérimenté Avatar de pacificator
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 074
    Points : 1 728
    Points
    1 728
    Par défaut
    Bonjour,

    dans le module ImageDraw il y a une méthode textsize qui permet de connaître la taille d'un texte sans le dessiner.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    textsize
     
    draw.textsize(string, options) => (width, height)
     
    Return the size of the given string, in pixels.
     
    The font option is used to specify which font to use. It should be an instance of the ImageFont class, typically loaded from file using the load method in the ImageFont module.
    "Etre conscient de la difficulté permet de l'éviter.."
    Lao-Tseu.

  3. #3
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Merci.

    J'ai essayé ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #! /usr/bin/env python
    #coding=utf-8
     
    # Source :
    #    http://www.pythonware.com/library/pil/handbook/imagedraw.htm
    import Image, ImageDraw
     
    # Creation of an empty picture.
    im = Image.open("lena.png")
     
    # Infos about text.
    draw = ImageDraw.Draw(im)
     
    print draw.textsize('p')
    print draw.textsize('m')
    Cela me renvoie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Traceback (most recent call last):
    ...
      File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/PIL-1.1.7-py2.6-macosx-10.3-fat.egg/Image.py", line 1952, in open
        fp = __builtin__.open(fp, "rb")
    IOError: [Errno 2] No such file or directory: 'lena.png'
    Pourtant dans la FAQ, il y a un exemple de création d'une image ex-nihilo ici, il me semble.

    Où est l'erreur ?

  4. #4
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 049
    Points : 1 380
    Points
    1 380
    Par défaut
    pygame aussi ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    from pygame import *
    font.init()
     
    fontsize = 25
    text = 'foo'
     
    systemfont = font.Font(font.get_default_font(),25)
    size = systemfont.size(text)

  5. #5
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Citation Envoyé par rambc Voir le message
    im = Image.open("lena.png")
    N'est-ce pas plutôt Image.new que tu devrais utiliser ? C'est ce que je lis dans la FAQ en tout cas.

  6. #6
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Citation Envoyé par Antoine_935 Voir le message
    N'est-ce pas plutôt Image.new que tu devrais utiliser ? C'est ce que je lis dans la FAQ en tout cas.
    Oups... J'ai un peu honte...

    Bon j'ai essayé ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #! /usr/bin/env python
    #coding=utf-8
     
    import Image, ImageFont, ImageDraw
    import pygame
     
    print '=== PIL - textsize ===' 
    im = Image.new("RGB", (1,1))
    draw = ImageDraw.Draw(im)
    font = ImageFont.load_default()
    print draw.textsize('p', font)
    print draw.textsize('m', font)
     
    print '=== PIL - font.getsize ===' 
    print font.getsize('p')
     
    print '=== PyGame ===' 
    pygame.font.init()
    fontName = pygame.font.get_default_font()
    fontsize = 25
    systemfont = pygame.font.Font(fontName, fontsize)
    print systemfont.size('p')
    print systemfont.size('m')
    J'obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    === PIL - textsize ===
    (6, 11)
    (6, 11)
    === PIL - font.getsize ===
    (6, 11)
    === PyGame ===
    (15, 26)
    (22, 26)
    On voir donc que rien n'est parfait :
    • ImageFont et ImageDraw renvoient la même info...
    • PyGame est précis sur la largeur mais excessif sur la hauteur...

  7. #7
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 049
    Points : 1 380
    Points
    1 380
    Par défaut
    ben, normal, avec pygame faut donner la hauteur de la font.
    j'ai mis 25 arbitrairement ...

    mets:
    et tu obtiens:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    === PIL - textsize ===
    (6, 11)
    (6, 11)
    === PIL - font.getsize ===
    (6, 11)
    === PyGame ===
    (6, 11)
    (9, 11)

  8. #8
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Merci mais ce n'est pas ceci qui me pose souci, et là je reconnais ne pas avoir été assez clair.

    Je précise ce qui me chagrine. Un "m" n'ayant pas de béquille prend moins de place qu'un "p". PyGame repère bien le fait qu'un "m" est plus large qu'un "p" mais pas qu'il est moins haut...
    Avec LaTeX, on a accès aux infos relativement à la ligne d'écriture, ie la ligne où l'on pose le "m" et la boucle du "p" .

    Pourquoi je vous enquiquine avec cela. C'est parce que l'on pourrait essayer de remplir les mots sous ou sur une série de lettre.

  9. #9
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 049
    Points : 1 380
    Points
    1 380
    Par défaut
    je suis pas sûr que ça serve à ça ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    import pygame
    pygame.font.init()
    fontName = pygame.font.get_default_font()
    fontsize = 10
    systemfont = pygame.font.Font(fontName, fontsize)
    print systemfont.metrics('mp')
    retourne une liste d'offsets pour chaque caractere
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [(1, 8, 0, 6, 9), (1, 5, -2, 5, 6)]
    mais j'ai pas encore pigé comment ça marche

  10. #10
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Merci pour cette précision qui semble donner toutes les infos.

    J'ai essayé le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    #! /usr/bin/env python
    #coding=utf-8
     
    import pygame
     
    pygame.font.init()
    fontName = pygame.font.get_default_font()
    fontsize = 10
    systemfont = pygame.font.Font(fontName, fontsize)
     
    # http://www.pygame.org/docs/ref/font.html
    #
    # Font.metrics
    #
    #      Gets the metrics for each character in the pased string.
    #      Font.metrics(text): return list
    #
    #      The list contains tuples for each character,
    # which contain the minimum X offset, the maximum X offset,
    # the minimum Y offset, the maximum Y offset and
    # the advance offset (bearing plus width) of the character.
    #      [(minx, maxx, miny, maxy, advance),
    #       (minx, maxx, miny, maxy, advance), ...] 
     
    for oneExample in ['m', 'p', 'P']:
        print
        print oneExample
        print systemfont.size(oneExample)
        print systemfont.metrics(oneExample)
    Ceci me renvoie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    m
    (9, 11)
    [(0, 9, 0, 6, 9)]
     
    p
    (7, 11)
    [(0, 7, -2, 6, 7)]
     
    P
    (7, 11)
    [(0, 7, 0, 8, 7)]
    Ce qui surprend c'est le fait qu'on toujours la même hauteur renvoyée par systemfont.size.

    Les lignes ci-dessus donnent plus de précisions. Je pense côté hauteur qu'on a :
    • m n'occupe pas de place sous la ligne d'écriture, et 6 pixels au-dessus.
    • p occupe 2 pixels sous la ligne d'écriture, et 6 pixels au-dessus.
    • P n'occupe pas de place sous la ligne d'écriture, et 8 pixels au-dessus.

  11. #11
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Ceci m'amène à relancer ce post sur la méthode utilisée pour écrire les mots.

    Une 1ère idée qui me vient en tête est de considérer chaque mot comme une association rigide de lettres dont on connaît la boîte minimale grâce aux ligne ci-dessus.
    Tout revient à remplir au mieux, ou le plus joliment possible, un rectangle à l'aide d'ensembles rigides de carrés.

    Une autre idée serait de mettre les mots les moins importants un peu au hasard et de les considérer fixes. Ensuite avec des bibliothèques permettant d'avoir des comportements physiques, on pourrait lâcher au hasard les mots restant et simuler leur chute. Au final, on aurait un joyeux bazar.

    Tout ceci est très théorique mais bon...

  12. #12
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 049
    Points : 1 380
    Points
    1 380
    Par défaut
    pourquoi, au lieu de se baser sur la taille des caractères, ne pas faire des tests de collisions ? Considérer chaque "image-mot" comme un sprite ...

  13. #13
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Pas idiot. En fait, je n'ai jamais utilisé PyGame et forcément y a des outils tout fait.

    Je garde tout ceci sous le coude.

  14. #14
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Citation Envoyé par josmiley Voir le message
    pourquoi, au lieu de se baser sur la taille des caractères, ne pas faire des tests de collisions ? Considérer chaque "image-mot" comme un sprite ...
    Juste une petite question (étant donné que pour le moment je n'ai pas trop le temps de me plonger dans pyGame). Un sprite peut-il avoir une forme biscornue ? Peut-on définir un sprite comme réunion de carrés ? J'imagine que oui mais un oui certain serait bienvenue.

  15. #15
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 049
    Points : 1 380
    Points
    1 380
    Par défaut
    Peut-on définir un sprite comme réunion de carrés ?
    le module 'sprite' simplifie la gestions des sprites, mais ce n'est pas une obligation.
    Les modules 'Rect' et 'Mask' peuvent suffirent.
    je ne connais pas bien le module 'sprite', mais je sais que ça peut géré des 'groups' de sprites.
    Cependant l'image du mot 'pomme' peut être un sprite simple ayant un mask. Le fond transparent sera ignoré lors du test d'overlap..
    voilà un code (pas du tout optimisé c'est juste un exemple) qui n'utilise pas le module 'sprite' mais utilise les masks pour detecter l'overlap.
    utilisez les touches fléchées pour déplacer le mot 'pomme' vert le mot 'olive'.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    from pygame import *
    screen = display.set_mode((300,300))
    font.init()
    font30 = font.Font(font.get_default_font(),30)
    key.set_repeat(20,20)
     
    class mon_sprite:
    	''
    	def __init__(self,txt,pos,color):
    		self.surf = font30.render(txt,1,color)
    		self.mask = mask.from_surface(self.surf,0)
    		self.pos = pos
     
    	def move(self,x,y):
    		self.pos = self.pos[0]+x,self.pos[1]+y
     
    	def collide(self,other_sprite):
    		def offset():
    			return other_sprite.pos[0]-self.pos[0],other_sprite.pos[1]-self.pos[1]
    		if self.mask.overlap(other_sprite.mask, offset()): return True
     
     
    olive = mon_sprite('olive',(100,250),(130,175,130))
    pomme = mon_sprite('pomme',(100,50),(240,150,20))
     
    #_____________________________________________________________________________________
    #_____________________________________________________________________________________
     
    def redraw():
    	screen.fill(0)
    	screen.blit(olive.surf,olive.pos)
    	screen.blit(pomme.surf,pomme.pos)
    	display.flip()
     
    redraw()
    while True:
    	ev = event.wait()
    	if ev.type == KEYDOWN:
    		if ev.key == K_LEFT:
    			pomme.move(-2,0)
    		elif ev.key == K_RIGHT:
    			pomme.move(2,0)
    		elif ev.key == K_DOWN:
    			pomme.move(0,2)
    		elif ev.key == K_UP:
    			pomme.move(0,-2)
    		if pomme.collide(olive):
    			screen.blit(font30.render('BOOM',1,(255,255,255)),(100,150))
    			display.flip()
    			while event.wait().type != QUIT: pass
    			break
    		else: redraw()

  16. #16
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Merci pour ce bout de code tout à fait compréhensible. Efficace ce pyGame.

    Quand j'en aurais fini avec mon projet (j'espère que ce sera pour début 2011), j'aimerais faire un petit jeu comme çà pour le fun.

  17. #17
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 049
    Points : 1 380
    Points
    1 380
    Par défaut
    Citation Envoyé par rambc Voir le message
    Merci pour ce bout de code tout à fait compréhensible.
    heu ... oui, je pense jamais à commenter, désolé.
    je rajouterai des coms.

  18. #18
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Ce n'était pas du 2nd degré. Je trouve cela facile à appréhender. Je ne connais pas du tout pyGame mais cela ne m'a pas empêché de comprendre ton code sans souci.

Discussions similaires

  1. Fabriquer des états / reports ?
    Par patxi.draks dans le forum Général Python
    Réponses: 2
    Dernier message: 28/05/2008, 15h47
  2. Fabriquer des formulaires sur Oracle
    Par mlaiti dans le forum Forms
    Réponses: 4
    Dernier message: 25/02/2008, 17h52
  3. TmemoryStream: definition des Word
    Par cfalcot dans le forum Langage
    Réponses: 8
    Dernier message: 03/03/2006, 18h46
  4. Fabriquer des requêtes sql à partir d'un document xml
    Par ktel dans le forum XQUERY/SGBD
    Réponses: 4
    Dernier message: 18/10/2005, 16h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo