2012-08-17 11 views
5

Sto filigranando alcune immagini usando il PIL e sto facendo fatica a leggere parte del testo (testo nero su sfondo scuro). Non posso semplicemente cambiare il colore del testo poiché ho una vasta gamma di colori di sfondo. C'è un modo per aggiungere un effetto alone attorno al testo?Crea un alone attorno al testo in Python usando PIL?

Ad esempio: http://i.imgur.com/WYxSU.jpg Il testo di fondo è quello che ho, e il testo in alto è quello che sto sperando di ottenere i colori (a parte). Ho solo bisogno di un contorno sottile attorno al testo. Qualche idea? Posso caricare del codice se pensi davvero che farà la differenza, ma è solo un normale comando PIL ImageDraw.Draw. Grazie!

+1

Stampa il testo tre volte. I primi due con il contorno e gli offset di (-1, -1) e (1, 1) e il terzo con il colore originale nella posizione originale. – Matthias

+2

http://mail.python.org/pipermail/image-sig/2009-May/005681.html http://stackoverflow.com/a/8050556/442650 –

+0

PIL.ImageDraw ha un'opzione 'outline' ma non è valido per il testo. –

risposta

7

Se non si cura di velocità troppo, puoi farlo utilizzando la composizione: testo

  1. pareggio con il colore alone sull'immagine un vuoto RGBA
  2. sfocatura è
  3. disegnare di nuovo con testo di colore
  4. invertito questa immagine per ottenere la composizione mascherare
  5. "merge" immagine originale con

Ad esempio:

import sys 
import Image, ImageChops, ImageDraw, ImageFont, ImageFilter 

def draw_text_with_halo(img, position, text, font, col, halo_col): 
    halo = Image.new('RGBA', img.size, (0, 0, 0, 0)) 
    ImageDraw.Draw(halo).text(position, text, font = font, fill = halo_col) 
    blurred_halo = halo.filter(ImageFilter.BLUR) 
    ImageDraw.Draw(blurred_halo).text(position, text, font = font, fill = col) 
    return Image.composite(img, blurred_halo, ImageChops.invert(blurred_halo)) 

if __name__ == '__main__': 
    i = Image.open(sys.argv[1]) 
    font = ImageFont.load_default() 
    txt = 'Example 1234' 
    text_col = (0, 255, 0) # bright green 
    halo_col = (0, 0, 0) # black 
    i2 = draw_text_with_halo(i, (20, 20), txt, font, text_col, halo_col) 
    i2.save('halo.png') 

Ha molti vantaggi:

  • il risultato è liscio e sembra piacevole
  • è possibile scegliere il filtro diverso, invece di BLUR per ottenere diversi "alone"
  • funziona anche con caratteri molto grandi e sembra ancora bello

Per ottenere alone più spessi, si può utilizzare il filtro in questo modo:

kernel = [ 
    0, 1, 2, 1, 0, 
    1, 2, 4, 2, 1, 
    2, 4, 8, 4, 1, 
    1, 2, 4, 2, 1, 
    0, 1, 2, 1, 0] 
kernelsum = sum(kernel) 
myfilter = ImageFilter.Kernel((5, 5), kernel, scale = 0.1 * sum(kernel)) 
blurred_halo = halo.filter(myfilter) 

La parte scale = 0.1 * sum(kernel) rende l'aureola più spesso (piccoli valori) o dimmer (grandi valori).

+0

Penso che una struttura corretta sarebbe meglio in questo caso, come nell'esempio nella domanda, ma questo è il modo corretto per generare un "alone". L'unico lato negativo è che più si allarga l'alone e più si attenua. Sono un po 'deluso dal fatto che il PIL non dia un modo più diretto di miscelare un'immagine RGBA rispetto ad un'altra. –

+0

Cool grazie. Solo una domanda ... la sfocatura è molto sfocata ... con testo nero e sfocatura bianca ... la sfocatura infatti si rivela invisibile su uno sfondo nero. Come possiamo affinare questo? Forse è questo che intendi per alone più spesso? – Jonny

+0

@Jonny si, sarebbe probabilmente quello. Oppure, puoi usare un filtro diverso (vedi: http://pillow.readthedocs.org/en/latest/reference/ImageFilter.html), gioca con i valori * scale * o * offset * in http://pillow.readthedocs.org/en/latest/reference/ImageFilter.html#PIL.ImageFilter.Kernel –

Problemi correlati