Python 使用PIL将RGB转换为灰度的不同像素值

Python 使用PIL将RGB转换为灰度的不同像素值,python,image-processing,computer-vision,python-imaging-library,Python,Image Processing,Computer Vision,Python Imaging Library,我正在使用PIL库进行图像处理,并测试PIL将图像从RGB转换为L灰度的方法 该图像是Set5中的butterfly.png 我使用枕头加载图像,如下所示: 从PIL导入图像 im=图像'butterfly.png' 并将其转换为灰度,如下所示: 灰度=im.convert'L' 打印灰度 数组[[32,45,68,…,63,60,60], [ 27, 32, 40, ..., 60, 61, 60], [ 65, 35, 28, ..., 62, 63, 58], ...,

我正在使用PIL库进行图像处理,并测试PIL将图像从RGB转换为L灰度的方法

该图像是Set5中的butterfly.png

我使用枕头加载图像,如下所示:

从PIL导入图像 im=图像'butterfly.png' 并将其转换为灰度,如下所示:

灰度=im.convert'L' 打印灰度 数组[[32,45,68,…,63,60,60], [ 27, 32, 40, ..., 60, 61, 60], [ 65, 35, 28, ..., 62, 63, 58], ..., [ 46, 49, 53, ..., 112, 114, 111], [ 46, 49, 66, ..., 115, 113, 114], [49,53,65,…,115,113,113]],数据类型=uint8 为了测试PIL使用的公式,我看到文档中说:

将彩色图像转换为灰度模式L时,库使用ITU-R 601-2 luma变换:L=R*299/1000+G*587/1000+B*114/1000

因此,我编写了自己的自定义函数:

def pil_rgb_至_grayim: R=np.arrayim.getchannel'R' G=np.arrayim.getchannel'G' B=np.arrayim.getchannel'B' L=R*299/1000+G*587/1000+B*114/1000 返回L 它会返回一个不同的结果:

灰度2=pil\u rgb\u至\u grayim 打印灰度2 数组[[30.372,42.731,64.337,…,57.696,55.208,55.208], [ 25.848, 31.278, 38.57 , ..., 55.18 , 56.038, 55.18 ], [ 60.438, 34.392, 27.321, ..., 56.326, 57.799, 52.724], ..., [ 44.153, 46.429, 50.457, ..., 104.68 , 105.712, 103.071], [ 43.463, 46.647, 62.079, ..., 107.327, 104.968, 105.701], [ 46.397, 50.435, 60.725, ..., 107.327, 104.968, 104.957]]
为什么我会得到不同的像素值?

您正在处理数组中的uint8数字,这意味着它们可能会溢出。这可能会导致违反直觉的结果,因为在您可能不期望的情况下,操作顺序很重要。例如,以下各项之间存在差异:

>> # multplity (and overflow) then divide
>> np.array([200], dtype=np.uint8) * 587/1000
array([51.864])

如果你把分数包起来,你会得到更好的结果

L = (R * (299/1000) + G * (587/1000) + B * (114/1000)).astype(np.uint8)

# ...
array([[ 32,  45,  68, ...,  63,  60,  60],
   [ 27,  32,  40, ...,  60,  61,  60],
   [ 65,  35,  28, ...,  62,  63,  58],

您正在处理数组中的uint8数字,这意味着它们可能会溢出。这可能会导致违反直觉的结果,因为在您可能不期望的情况下,操作顺序很重要。例如,以下各项之间存在差异:

>> # multplity (and overflow) then divide
>> np.array([200], dtype=np.uint8) * 587/1000
array([51.864])

如果你把分数包起来,你会得到更好的结果

L = (R * (299/1000) + G * (587/1000) + B * (114/1000)).astype(np.uint8)

# ...
array([[ 32,  45,  68, ...,  63,  60,  60],
   [ 27,  32,  40, ...,  60,  61,  60],
   [ 65,  35,  28, ...,  62,  63,  58],

非常感谢。我没有意识到添加括号会带来巨大的不同。现在,如果我的数组一开始是float64,它会缓解乘法带来的溢出问题吗?我认为这对图像数据@StevenChen没有帮助,因为你仍然有分布在整个范围内的值,当你乘以一个大的数字时,它仍然会溢出。也许你从8位数字开始,然后把它们放在64位数组中,但这对我来说似乎很难。谢谢。我没有意识到添加括号会带来巨大的不同。现在,如果我的数组一开始是float64,它会缓解乘法带来的溢出问题吗?我认为这对图像数据@StevenChen没有帮助,因为你仍然有分布在整个范围内的值,当你乘以一个大的数字时,它仍然会溢出。也许你从8位数字开始,把它们放在64位数组中,但这对我来说似乎是一条艰难的道路。