为什么 ImageFilter.BoxBlur 会给出错误的结果?
Why does ImageFilter.BoxBlur give wrong results?
我正在尝试将 Pillow 与我生成的一些黑白测试数据一起使用,逐个像素。我想用这些数据来测试我的 one pixel box blur。我已经将灰度像素存储在这样的 3x3 行矩阵中:
5 10 5
10 15 10
5 10 5
使用一个像素的框模糊,我希望结果如下:
10 9 10
9 8 9
10 9 10
但是,我调用 image.tobytes()
后的结果是一个包含九个新行的数组 (\n
)。谁能指出我做错了什么?
我理解你的预期输出,但让我们先检查一下现实:
import numpy as np
from PIL import Image, ImageFilter
array = np.array([[5, 10, 5], [10, 15, 10], [5, 10, 5]]).astype(np.uint8)
img = Image.fromarray(array).filter(ImageFilter.BoxBlur(1))
print(np.array(img), '\n\n', img.tobytes())
# [[9 9 9]
# [9 9 9]
# [9 9 9]]
#
# b'\t\t\t\t\t\t\t\t\t'
结果是一个包含所有 9
的数组 – 当将 9
转换为字节时,您会得到水平制表符的 ASCII character 或 \t
。老实说,我不明白,为什么你得到 \n
或换行符,这将 10
转换为字节,在这里!?
但是,为什么会有这样的结果呢?来自文档(我强调):
Blurs the image by setting each pixel to the average value of the pixels in a square box extending radius pixels in each direction.
因此,您的矩阵实际上看起来像这样用于计算九个(内部)像素:
5 5 10 5 5
5 5 10 5 5
10 10 15 10 10
5 5 10 5 5
5 5 10 5 5
对于九个内部像素中的每一个,我们得到:
(4 * 5 + 4 * 10 + 15) / 9 = 75 / 9 = 8.333
看来,我们这里也有上限,而不是常见的四舍五入。
这可能是由于:
Uses an optimized implementation which runs in linear time relative to the size of the image for any radius value.
所以,可能是一些位移魔法而不是实际除法或类似的东西。
您还可以检查边框像素是否被复制,而不是镜像:
import numpy as np
from PIL import Image, ImageFilter
array = np.array([[5, 10, 5], [10, 15, 10], [5, 10, 5]]).astype(np.uint8)
img = Image.fromarray(array).filter(ImageFilter.BoxBlur(2))
print(np.array(img), '\n\n', img.tobytes())
# [[7 7 7]
# [7 7 7]
# [7 7 7]]
像上面为 5x5 矩阵所做的那样设置两个可能的 7x7 矩阵,并比较结果。
底线:BoxBlur
没有按您预期的方式工作。而且,它仍然令人困惑,为什么你得到 \n
,而不是 \t
。
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.9.1
PyCharm: 2021.1.1
NumPy: 1.20.2
Pillow: 8.2.0
----------------------------------------
我正在尝试将 Pillow 与我生成的一些黑白测试数据一起使用,逐个像素。我想用这些数据来测试我的 one pixel box blur。我已经将灰度像素存储在这样的 3x3 行矩阵中:
5 10 5
10 15 10
5 10 5
使用一个像素的框模糊,我希望结果如下:
10 9 10
9 8 9
10 9 10
但是,我调用 image.tobytes()
后的结果是一个包含九个新行的数组 (\n
)。谁能指出我做错了什么?
我理解你的预期输出,但让我们先检查一下现实:
import numpy as np
from PIL import Image, ImageFilter
array = np.array([[5, 10, 5], [10, 15, 10], [5, 10, 5]]).astype(np.uint8)
img = Image.fromarray(array).filter(ImageFilter.BoxBlur(1))
print(np.array(img), '\n\n', img.tobytes())
# [[9 9 9]
# [9 9 9]
# [9 9 9]]
#
# b'\t\t\t\t\t\t\t\t\t'
结果是一个包含所有 9
的数组 – 当将 9
转换为字节时,您会得到水平制表符的 ASCII character 或 \t
。老实说,我不明白,为什么你得到 \n
或换行符,这将 10
转换为字节,在这里!?
但是,为什么会有这样的结果呢?来自文档(我强调):
Blurs the image by setting each pixel to the average value of the pixels in a square box extending radius pixels in each direction.
因此,您的矩阵实际上看起来像这样用于计算九个(内部)像素:
5 5 10 5 5
5 5 10 5 5
10 10 15 10 10
5 5 10 5 5
5 5 10 5 5
对于九个内部像素中的每一个,我们得到:
(4 * 5 + 4 * 10 + 15) / 9 = 75 / 9 = 8.333
看来,我们这里也有上限,而不是常见的四舍五入。
这可能是由于:
Uses an optimized implementation which runs in linear time relative to the size of the image for any radius value.
所以,可能是一些位移魔法而不是实际除法或类似的东西。
您还可以检查边框像素是否被复制,而不是镜像:
import numpy as np
from PIL import Image, ImageFilter
array = np.array([[5, 10, 5], [10, 15, 10], [5, 10, 5]]).astype(np.uint8)
img = Image.fromarray(array).filter(ImageFilter.BoxBlur(2))
print(np.array(img), '\n\n', img.tobytes())
# [[7 7 7]
# [7 7 7]
# [7 7 7]]
像上面为 5x5 矩阵所做的那样设置两个可能的 7x7 矩阵,并比较结果。
底线:BoxBlur
没有按您预期的方式工作。而且,它仍然令人困惑,为什么你得到 \n
,而不是 \t
。
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.9.1
PyCharm: 2021.1.1
NumPy: 1.20.2
Pillow: 8.2.0
----------------------------------------