使用PIL填充空白图像区域以匹配附近颜色(即修复)

10
我使用PIL创建了一张图片:

example image

我需要填补空白区域(黑色区域)。我可以很容易地用静态颜色来填充它,但我想做的是用附近的颜色来填充像素。例如,边框后的第一个像素可能是填充像素的高斯模糊。或者是一种推拉类型算法,如The Lumigraph, Gortler, et al.所述。
我需要一些不太慢的东西,因为我必须在许多图像上运行它。我可以访问其他库,比如numpy,并且您可以假设我知道外部区域或内部区域的边界或掩码。有什么建议吗?
更新:
正如belisarius所建议的那样,opencv的inpaint方法非常适合这个问题。以下是使用opencv实现所需内容的Python代码:
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()

并生成相应的图像:

painted image

3个回答

8
一种具有良好结果的方法是Navier-Stokes图像恢复。我知道OpenCV有它,但不确定PIL是否有。
您的示例:

enter image description here enter image description here

我用Mathematica完成了它。 编辑 根据您的要求,代码如下:
i = Import["http://i.stack.imgur.com/uEPqc.png"];
Inpaint[i, ColorNegate@Binarize@i, Method -> "NavierStokes"]

ColorNegate@ ... 部分创建了替换掩模。 填充只需使用Inpaint[]命令即可完成。

太棒了。我在我的问题中放了一些示例Python代码,将PIL转换为OpenCV并进行绘画。接受了你的答案。谢谢! - jterrace
@jterrace 很高兴能帮忙!我也投了你的问题,因为它是 SO 有多么有用的很好的例子。 - Dr. belisarius
你有没有想过为什么修复图像时,inpaint 总是会忽略掉 x=0 和 y=0(即图像的顶部行和左侧列)? - jterrace

0

根据您部署此应用程序的方式,另一个选项可能是使用Gimp的Python接口来进行图像处理。

我链接的文档页面更多地面向使用Python编写GIMP插件,而不是从Python应用程序与后台GIMP实例交互,但我相信这也是可能的(我已经有一段时间没有使用gimp/python接口了,有点模糊)。


它是否有一个例程可以做类似这样的事情? - jterrace
很遗憾,我不确定它是否有符合您要求的插件... 我主要将其发布为您可能不知道的选项,因为它具有一些更强大的工具可供使用:蒙版、高斯模糊滤镜以及针对低级像素区域对象的Python接口。现在我想得更多了,如果您需要处理大量文件,它可能会过于臃肿。尽管有一个算法可能使它值得一试,那就是Gimp的resynthesizer插件,它是一种“内容感知填充”算法。 - Eli Collins

-1

你也可以使用函数CreateImage()来创建掩码,例如:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接