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

10 投票
3 回答
5352 浏览
提问于 2025-04-16 23:49

我用PIL创建了一张图片:

示例图片

现在我需要填补空白的地方(黑色部分)。我可以简单地用一种固定的颜色来填充,但我想要的是用周围的颜色来填充这些像素。比如,边界之后的第一个像素可以用填充像素的高斯模糊效果来处理。或者可以使用一种推拉算法,具体可以参考The Lumigraph, Gortler等人的研究

我需要的方法不能太慢,因为我需要在很多图片上运行这个操作。我可以使用其他库,比如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()

这是处理后的图片:

处理后的图片

3 个回答

-1

你还可以使用 CreateImage() 这个函数来创建一个遮罩,比如:

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

根据你部署这个应用的方式,另一个选择可能是使用Gimp的Python接口来进行图像处理。

我链接的文档页面主要是关于用Python编写GIMP插件的,而不是从Python应用与后台的GIMP实例进行交互,但我相信这也是可以做到的(我已经有一段时间没玩GIMP/Python接口了,有点记不清了)。

8

一种效果不错的方法是 Navier-Stokes 图像修复. 我知道 OpenCV 有这个功能,不确定 PIL 是否也有。

你的例子:

enter image description here enter image description here

我用 Mathematica 做了这个。

编辑

根据你的要求,代码如下:

i = Import["https://i.stack.imgur.com/uEPqc.png"];
Inpaint[i, ColorNegate@Binarize@i, Method -> "NavierStokes"]

ColorNegate@ ... 这一部分是用来创建替换的遮罩。填充的过程只需要用 Inpaint[] 命令就可以完成。

撰写回答