python-pillow 中内核大小大于 5x5 的卷积
Convolution with kernel size larger than 5x5 in python-pillow
我想在 python-pillow 中使用简单的卷积核过滤图像。但是,要获得最佳结果,我需要一个 9x9 内核。这是 pillow 中的 not possible,至少在使用 ImageFilter.Kernel
和内置的 filter()
方法时是这样,它们仅限于 5x5 内核。
没有实现我自己的卷积代码,有没有办法filter/convolve一个内核大小大于5x5的图像?
看到 PIL 不支持超过 5 x 5 内核,我感到非常惊讶。因此,谨慎的做法是查看其他 Python 包,例如 OpenCV or scipy
... 为了节省时间,让我们使用 scipy
。尽管 OpenCV 非常强大,但配置起来却很痛苦。
我建议使用 scipy
来加载带有 imread
from the ndimage
package, convolve the image with your kernel, then convert to a PIL image when you're done. Use convolve
from the ndimage
package, then convert back to a PIL image by Image.fromArray
的图像。它确实支持转换 numpy.ndarray
(使用 scipy.ndimage.imread
时加载的内容),这很棒。
像这样,假设一个 9 x 9 平均滤波器:
# 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 is another option, if you're not tied to pillow, numpy or scipy. It's quite a bit faster and needs a lot less memory, especially for larger images. It'll beat opencv too, at least on some benchmarks.
我在这台笔记本电脑上试过:
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
所以 2015 i5 笔记本电脑上的 10k x 10k 像素单声道 jpg 大约需要 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 内存。
这是一个浮点卷积。您可以像这样将其交换为 int 精度:
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 秒。
我想在 python-pillow 中使用简单的卷积核过滤图像。但是,要获得最佳结果,我需要一个 9x9 内核。这是 pillow 中的 not possible,至少在使用 ImageFilter.Kernel
和内置的 filter()
方法时是这样,它们仅限于 5x5 内核。
没有实现我自己的卷积代码,有没有办法filter/convolve一个内核大小大于5x5的图像?
看到 PIL 不支持超过 5 x 5 内核,我感到非常惊讶。因此,谨慎的做法是查看其他 Python 包,例如 OpenCV or scipy
... 为了节省时间,让我们使用 scipy
。尽管 OpenCV 非常强大,但配置起来却很痛苦。
我建议使用 scipy
来加载带有 imread
from the ndimage
package, convolve the image with your kernel, then convert to a PIL image when you're done. Use convolve
from the ndimage
package, then convert back to a PIL image by Image.fromArray
的图像。它确实支持转换 numpy.ndarray
(使用 scipy.ndimage.imread
时加载的内容),这很棒。
像这样,假设一个 9 x 9 平均滤波器:
# 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 is another option, if you're not tied to pillow, numpy or scipy. It's quite a bit faster and needs a lot less memory, especially for larger images. It'll beat opencv too, at least on some benchmarks.
我在这台笔记本电脑上试过:
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
所以 2015 i5 笔记本电脑上的 10k x 10k 像素单声道 jpg 大约需要 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 内存。
这是一个浮点卷积。您可以像这样将其交换为 int 精度:
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 秒。