2011-08-17 12 views
9

creo un'immagine con PIL:Utilizzando PIL per riempire lo spazio vuoto di immagini con colori nelle vicinanze (aka inpainting)

example image

ho bisogno di riempire lo spazio vuoto (dipinto come il nero). Potrei facilmente riempirlo con un colore statico, ma quello che mi piacerebbe fare è riempire i pixel con i colori vicini. Ad esempio, il primo pixel dopo il bordo potrebbe essere una sfocatura gaussiana dei pixel riempiti. O forse un tipo di algoritmo di push-pull descritto in The Lumigraph, Gortler, et al..

ho bisogno di qualcosa che non è troppo lento perché devo correre questo su molte immagini. Ho accesso ad altre biblioteche, come NumPy, e si può supporre che io conosco le frontiere o una maschera della regione al di fuori o regione all'interno. Qualche suggerimento su come affrontarlo?

UPDATE:

Come suggerito da Belisario, opencv's inpaint metodo è perfetto per questo. Ecco alcuni codice Python che utilizza OpenCV per ottenere quello che volevo:

import Image, ImageDraw, cv 

im = Image.open("u7XVL.png") 
pix = im.load() 

#create a mask of the background colors 
# this is slow, but easy for example purposes 
mask = Image.new('L', im.size) 
maskdraw = ImageDraw.Draw(mask) 
for x in range(im.size[0]): 
    for y in range(im.size[1]): 
     if pix[(x,y)] == (0,0,0): 
      maskdraw.point((x,y), 255) 

#convert image and mask to opencv format 
cv_im = cv.CreateImageHeader(im.size, cv.IPL_DEPTH_8U, 3) 
cv.SetData(cv_im, im.tostring()) 
cv_mask = cv.CreateImageHeader(mask.size, cv.IPL_DEPTH_8U, 1) 
cv.SetData(cv_mask, mask.tostring()) 

#do the inpainting 
cv_painted_im = cv.CloneImage(cv_im) 
cv.Inpaint(cv_im, cv_mask, cv_painted_im, 3, cv.CV_INPAINT_NS) 

#convert back to PIL 
painted_im = Image.fromstring("RGB", cv.GetSize(cv_painted_im), cv_painted_im.tostring()) 
painted_im.show() 

E l'immagine risultante:

painted image

risposta

8

Un metodo con buoni risultati è il Navier-Stokes Image Restoration. So che OpenCV ce l'ha, non so di PIL.

Il vostro esempio:

enter image description hereenter image description here

ho fatto con Mathematica.

Modifica

Secondo il vostro reuquest, il codice è:

i = Import["http://i.stack.imgur.com/uEPqc.png"]; 
Inpaint[i, [email protected]@i, Method -> "NavierStokes"] 

Il ColorNegate @ ... parte crea la maschera di sostituzione. Il riempimento viene eseguito con il solo comando Inpaint[].

+0

Questo sembra carino. Puoi pubblicare il tuo codice mathematica? – jterrace

+0

Fantastico. Ho messo un codice Python esemplificativo che converte da PIL in opencv e fa il dipinto nella mia domanda. Accettata la tua risposta Grazie! – jterrace

+0

@jterrace Contento di aiutare! Ho votato anche la tua domanda, perché è un ottimo esempio di quanto possa essere utile SO. –

0

A seconda di come si sta distribuendo questa applicazione, un'altra opzione potrebbe essere quella di utilizzare Gimp's python interface per manipolare le immagini.

La pagina doc a cui mi sono collegato è orientata più verso la scrittura di plugin GIMP in python, piuttosto che interagire con un'istanza di gimp in background da un'app python, ma sono abbastanza sicuro che sia anche possibile (è da un po 'che non gioco con l'interfaccia gimp/python, sono un po 'confuso).

+0

Ha una routine per fare qualcosa di simile? – jterrace

+0

Purtroppo non sono sicuro che abbia un plug-in che corrisponda a quello che vuoi ... L'ho postato principalmente come un'opzione di cui potresti non essere a conoscenza, dal momento che ha alcuni strumenti più potenti da cui costruire: maschere, gaussiane filtri sfocatura e un'interfaccia pythonic per gli oggetti regione pixel di livello inferiore.Ora che ci penso di più, potrebbe essere un eccesso eccessivo per i tuoi scopi, specialmente se devi elaborare molti file. Anche se un algoritmo che potrebbe valerne la pena è il plug-in [resynthesizer] (http://www.logarithmic.net/pfh/resynthesizer) per Gimp, che è un algoritmo "content aware fill". –

-1

È anche possibile creare la maschera con la funzione CreateImage(), per esempio:

inpaint_mask = cv.CreateImage(cv.GetSize(im), 8, 1) 
Problemi correlati