2011-08-17 13 views
9

puedo crear una imagen con PIL:PIL para llenar el espacio vacío de imagen con colores cercanos (aka inpainting)

example image

que necesito para llenar el espacio vacío (representado como negro). Podría llenarlo fácilmente con un color estático, pero lo que me gustaría hacer es llenar los píxeles con colores cercanos. Por ejemplo, el primer píxel después del borde podría ser un desenfoque gaussiano de los píxeles rellenos. O tal vez un algoritmo de tipo push-pull descrito en The Lumigraph, Gortler, et al..

Necesito algo que no sea demasiado lento porque tengo que ejecutar esto en muchas imágenes. Tengo acceso a otras bibliotecas, como numpy, y puedes asumir que conozco los bordes o una máscara de la región exterior o dentro de la región. ¿Alguna sugerencia sobre cómo abordar esto?

ACTUALIZACIÓN:

Como sugiere Belisario, opencv's inpaint método es perfecto para esto. Aquí hay algo de código Python que utiliza OpenCV para lograr lo que quería:

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() 

Y la imagen resultante:

painted image

Respuesta

8

Un método con buenos resultados es el Navier-Stokes Image Restoration. Sé que OpenCV lo tiene, no sé sobre PIL.

Su ejemplo:

enter image description hereenter image description here

lo hice con Mathematica.

Editar

Según su reuquest, el código es:

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

El ColorNegate @ ... Parte crea la máscara de reemplazo. El llenado se realiza solo con el comando Inpaint[].

+0

Esto se ve bien. ¿Puedes publicar tu código matemático? – jterrace

+0

Impresionante. He puesto un ejemplo de código python que convierte de PIL a opencv y hace la pintura en mi pregunta. Aceptó tu respuesta. ¡Gracias! – jterrace

+0

@jterrace ¡Me alegro de ayudar! También voté tu pregunta, porque es un muy buen ejemplo de lo útil que puede ser el SO. –

0

Dependiendo de cómo se va a implementar esta aplicación, otra opción podría ser usar el python interface de Gimp para hacer la manipulación de la imagen.

La página de doc a la que me he vinculado está más orientada a escribir complementos de GIMP en python, en lugar de interactuar con una instancia de gimp de fondo desde una aplicación de Python, pero estoy seguro de que eso también es posible. con la interfaz gimp/python, estoy un poco confuso).

+0

¿Tiene una rutina para hacer algo como esto? – jterrace

+0

Lamentablemente, no estoy seguro si tiene un complemento que coincida con lo que desea ... Principalmente lo publiqué como una opción que quizás no conozca, ya que tiene algunas herramientas más poderosas para construir a partir de: máscaras, gaussianas filtros de desenfoque y una interfaz pitónica para los objetos de la región de píxeles de bajo nivel.Ahora que lo pienso más, podría ser abrumador para tus propósitos, especialmente si tienes que procesar muchos archivos. Aunque un algoritmo que puede hacer que valga la pena es el plugin [resynthesizer] (http://www.logarithmic.net/pfh/resynthesizer) para el Gimp, que es un algoritmo de "relleno con conocimiento del contenido". –

-1

También puede crear la máscara con la función CreateImage(), por ejemplo:

inpaint_mask = cv.CreateImage(cv.GetSize(im), 8, 1) 
Cuestiones relacionadas