我想在Python-Pillow中使用简单卷积核对图像进行滤波。然而,为了获得最佳结果,我需要一个9x9的卷积核。在pillow中,使用ImageFilter.Kernel和内置的filter()方法时,最多只能使用5x5的卷积核,这是不可能的not possible。
除了实现自己的卷积代码外,是否有一种方法可以使用大于5x5的卷积核来过滤/卷积图像?
除了实现自己的卷积代码外,是否有一种方法可以使用大于5x5的卷积核来过滤/卷积图像?
我很惊讶地发现PIL没有超过5 x 5内核的支持。因此,最好看看其他Python包,例如OpenCV或scipy
...为了节省时间,让我们使用scipy
。尽管OpenCV非常强大,但配置起来很麻烦。
scipy
从ndimage
包中加载您的图像,并使用imread
函数将其转换为numpy.ndarray
,然后用您的卷积核对图像进行卷积操作,完成后再转换回PIL图像。使用ndimage
包中的convolve
函数进行卷积,在使用Image.fromArray
函数将其转换回PIL图像时,它支持将numpy.ndarray
转换为PIL格式,非常方便。假设您使用的是9x9平均滤波器,则代码类似于这样:# Import relevant packages
import numpy as np
from scipy import ndimage
from PIL import Image
# Read in image - change filename to whatever you want
img = ndimage.imread('image.jpg')
# Create kernel
ker = (1/81.0)*np.ones((9,9))
# Convolve
out = ndimage.convolve(img, ker)
# Convert back to PIL image
out = Image.fromArray(out, 'RGB')
pyvips 是另一个选择,如果您没有使用 pillow、numpy 或 scipy 的限制。它的速度更快,需要的内存更少,特别是对于较大的图像。在某些基准测试中,它甚至能够击败 opencv。
我在这台笔记本电脑上进行了尝试:
import sys
import numpy as np
from scipy import ndimage
from PIL import Image
img = ndimage.imread(sys.argv[1])
ker = (1 / 81.0) * np.ones((9, 9))
out = ndimage.convolve(img, ker)
out = Image.fromarray(out)
out.save(sys.argv[2])
$ /usr/bin/time -f %M:%e ./try257.py ~/pics/wtc-mono.jpg x.jpg
300352:22.47
一张10k x 10k像素的黑白jpg图片在2015年的i5笔记本电脑上需要大约22秒的时间,并且需要300mb的内存峰值。
而在pyvips中,这个过程可以更快更省资源:
import sys
import pyvips
im = pyvips.Image.new_from_file(sys.argv[1], access="sequential")
size = 9
kernel = size * [size * [1.0 / (size * size)]]
im = im.conv(kernel)
im.write_to_file(sys.argv[2])
$ /usr/bin/time -f %M:%e ./try258.py ~/pics/wtc-mono.jpg x.jpg
44336:4.76
大约需要5秒钟和45MB的内存。
这是浮点卷积。你可以像这样将其转换为整型精度:
im = im.conv(kernel, precision="integer")
我看到:
$ /usr/bin/time -f %M:%e ./try258.py ~/pics/wtc-mono.jpg x.jpg
44888:1.79
1.8秒。
scipy
吗? - rayryengfilter()
会引发“坏内核大小”ValueError。 - jpfenderscipy
,请看一下ndimage
包中的convolve
:http://docs.scipy.org/doc/scipy-0.15.1/reference/generated/scipy.ndimage.filters.convolve.html。你可以使用[`scipy.imread`](http://docs.scipy.org/doc/scipy-0.13.0/reference/generated/scipy.ndimage.imread.html)加载图像,进行卷积,然后使用[`Image.fromArray`](http://pillow.readthedocs.org/en/latest/reference/Image.html#PIL.Image.fromarray)将其转换为PILImage
对象。 - rayryeng