Insérer une image dans un texte en Python est ce que j’ai souhaité faire aujourd’hui. Je me suis penché sur la question et voici ce que j’ai fait.

Insérer une image dans un texte en Python: prémices

Nous aurons besoin du module PIL ainsi que de numpy. Nous allons convertir dans un premier temps l’image suivante:

Insérer une image dans un texte en Python

en une matrice.

img = Image.open("image.png")
imgArray = np.array(img)
>>> imgArray.shape
(512, 768, 4)

Avec imgArray.shape, nous avons les dimensions de l’images (le dernier nombre ne va pas nous intéresser).

Maintenant, on créé une image vierge sur fond blanc:

tmp = Image.new('RGB', ( imgArray.shape[1] , imgArray.shape[0] ) , 'white' )
image_result = ImageDraw.Draw(tmp)

Dans cette nouvelle image, on va mettre une suite de « O » écrits en noir, et on va changer la couleur en rouge quand le « O » sera au niveau de ce qui était en noir dans l’image de départ.

Pour cela, on va d’abord choisir la fonte:

myFont = ImageFont.truetype('arial.ttf', 16)

Ensuite, on va faire des boucles (comme chez le coiffeur, mais en plus fun !).

for y in range( 0 , imgArray.shape[0] , 16):
    for x in range( 0 , imgArray.shape[1] , 16 ):
        r, v, b, t = imgArray[y, x] # r, v, b, t
        if (r,v,b) == (255,255,255):
            image_result.text((x, y), "O", font=myFont, fill=(0, 0, 0))
        else:
            image_result.text((x, y), "O", font=myFont, fill=(255, 0, 0))

Maintenant, on affiche l’image:

tmp.show()

C’est plutôt pas mal pour un début, mais ça pique un peu les yeux non ?

Insérer une image dans un texte en Python: lettres aléatoires

Pour ne pas toujours mettre la même lettre (précédemment, le « O »), je vais faire appel au pseudo-hasard, et donc au module random et sa fonction choice, ainsi qu’au module string et à sa variable ascii_uppercase.

import numpy as np
from PIL import Image, ImageDraw, ImageFont
from string import ascii_uppercase
from random import choice

img = Image.open("image.png")
imgArray = np.array(img)

tmp = Image.new('RGB', ( imgArray.shape[1] , imgArray.shape[0] ) , 'white' )
image_result = ImageDraw.Draw(tmp)

myFont = ImageFont.truetype('arial.ttf', 16)


for y in range( 0 , imgArray.shape[0] , 16):
    for x in range( 0 , imgArray.shape[1] , 16 ):
        r, v, b, t = imgArray[y, x] # r, v, b, t
        if (r,v,b) == (255,255,255):
            image_result.text((x, y), choice(ascii_uppercase), font=myFont, fill=(0, 0, 0))
        else:
            image_result.text((x, y), choice(ascii_uppercase), font=myFont, fill=(255, 0, 0))

tmp.save('result.jpg')
Insérer une image dans un texte en Python

Bon, là, vous allez me dire : « C’est bien gentil Coco, mais le texte ne veut rien dire ». Ok ! Alors prenons un texte contenu dans un fichier externe…

Insérer une image dans un texte en Python: à partir d’un fichier externe

Voici une première proposition:

import numpy as np
from PIL import Image, ImageDraw, ImageFont

img = Image.open("image.png")
imgArray = np.array(img)

tmp = Image.new('RGB', ( imgArray.shape[1] , imgArray.shape[0] ) , 'white' )
image_result = ImageDraw.Draw(tmp)

myFont = ImageFont.truetype('arial.ttf', 16)

lorem = open("lorem-ipsum.txt", "r" , encoding='utf8').read()
c = 0 # compteur de position de la lettre dans lorem

for y in range( 0 , imgArray.shape[0] , 16):
    for x in range( 0 , imgArray.shape[1] , 16 ):
        r, v, b, t = imgArray[y, x] # r, v, b, t
        if (r,v,b) == (255,255,255):
            image_result.text((x, y), lorem[c], font=myFont, fill=(0, 0, 0))
        else:
            image_result.text((x, y), lorem[c], font=myFont, fill=(255, 0, 0))
        c += 1

tmp.save('result.jpg')
Insérer une image dans un texte en Python: à partir d'un fichier externe

On se rapproche d’un résultat plutôt satisfaisant. Cependant, l’espace entre les lettres est trop important lorsque ce sont des minuscules… Il faut absolument y remédier.

Pour cela, je prends le parti prix de mettre toutes les lettres en majuscules et de diminuer les espaces, que j’avais fixées à 16 pixels précédemment.

import numpy as np
from PIL import Image, ImageDraw, ImageFont
from string import ascii_lowercase, ascii_uppercase

img = Image.open("image.png")
imgArray = np.array(img)

tmp = Image.new('RGB', ( imgArray.shape[1] , imgArray.shape[0] ) , 'white' )
image_result = ImageDraw.Draw(tmp)

myFont = ImageFont.truetype('arial.ttf', 12)

lorem = open("lorem-ipsum.txt", "r" , encoding='utf8').read()
c = 0 # compteur de position de la lettre dans lorem

for y in range( 0 , imgArray.shape[0] , 12):
    for x in range( 0 , imgArray.shape[1] , 12 ):
        r, v, b, t = imgArray[y, x] # r, v, b, t       
        if (r,v,b) == (255,255,255):
            image_result.text((x, y), lorem[c].upper(), font=myFont, fill=(0, 0, 0))
        else:
            image_result.text((x, y), lorem[c].upper(), font=myFont, fill=(255, 0, 0))
        c += 1

tmp.save('result.jpg')

Un autre exemple: Marylin

Partons de l’image suivante:

marylin monroe portrait

Et utilisons le script suivant:

import numpy as np
from PIL import Image, ImageDraw, ImageFont
from string import ascii_lowercase, ascii_uppercase

img = Image.open("marylin.png")
imgArray = np.array(img)

tmp = Image.new('RGB', ( imgArray.shape[1] , imgArray.shape[0] ) , 'white' )
image_result = ImageDraw.Draw(tmp)

myFont = ImageFont.truetype('arial.ttf', 12)

lorem = open("lorem-ipsum.txt", "r" , encoding='utf8').read()
c = 0 # compteur de position de la lettre dans lorem

for y in range( 0 , imgArray.shape[0] , 12):
    for x in range( 0 , imgArray.shape[1] , 12 ):
        b,w = imgArray[y, x] # r, v, b, t       
        if (b,w) == (255,255):
            image_result.text((x, y), lorem[c].upper(), font=myFont, fill=(200, 200, 200))
        else:
            image_result.text((x, y), lorem[c].upper(), font=myFont, fill=(0, 0, 0))
        c += 1

tmp.save('result.jpg')

Un autre exemple: pi dans pi

On part de l’image:

pi

et on utilise un fichier texte contenant plein de décimales de pi:

On utilise enfin le programme suivant:

import numpy as np
from PIL import Image, ImageDraw, ImageFont
from string import ascii_lowercase, ascii_uppercase

img = Image.open("pi.jpg")
imgArray = np.array(img)

tmp = Image.new('RGB', ( imgArray.shape[1] , imgArray.shape[0] ) , 'white' )
image_result = ImageDraw.Draw(tmp)

myFont = ImageFont.truetype('arial.ttf', 12)

pi = open("pi.txt", "r" , encoding='utf8').read().replace('\n','')
c = 0 # compteur de position de la lettre dans lorem

for y in range( 0 , imgArray.shape[0] , 12):
    for x in range( 0 , imgArray.shape[1] , 12 ):
        r, v,b = imgArray[y, x] # r, v, b, t
        if (r,v,b) == (255,255,255):
            image_result.text((x, y), pi[c].upper(), font=myFont, fill=(200, 200, 200))
        else:
            image_result.text((x, y), pi[c].upper(), font=myFont, fill=(255, 0, 0))
        c += 1

tmp.save('result-pi.jpg')

On obtient alors:

Catégories : Python

0 0 votes
Évaluation de l'article
S’abonner
Notification pour
guest
2 Commentaires
Le plus ancien
Le plus récent Le plus populaire
Commentaires en ligne
Afficher tous les commentaires
houps

Bonjour et merci pour cet exemple,

chez moi cette ligne ne fonctionne pas
b,w = imgArray[y, x] # r, v, b, t

car imgArray vaut 0 ou 1

je n’ai pas trouvé mon erreur

2
0
Nous aimerions avoir votre avis, veuillez laisser un commentaire.x