如何在Python中将RGB图像转换为灰度图像?

310

我正在尝试使用matplotlib读取RGB图像并将其转换为灰度图像。

在Matlab中,我使用以下代码:

img = rgb2gray(imread('image.png'));

Matplotlib教程中,他们没有涵盖这个问题。他们只是读取了图片。

import matplotlib.image as mpimg
img = mpimg.imread('image.png')

然后他们切片数组,但据我所知,这与将RGB转换为灰度不是同一件事。

lum_img = img[:,:,0]

我觉得很难相信numpy或matplotlib没有内置的将RGB转换为灰度图像的函数。这不是图像处理中常见的操作吗?

我用imread导入的图像写了一个非常简单的函数,只用了5分钟就完成了。它效率极低,但这也是我希望有内置的专业实现的原因。

Sebastian改进了我的函数,但我仍然希望找到内置的函数。

Matlab的(NTSC/PAL)实现:

import numpy as np

def rgb2gray(rgb):

    r, g, b = rgb[:,:,0], rgb[:,:,1], rgb[:,:,2]
    gray = 0.2989 * r + 0.5870 * g + 0.1140 * b

    return gray

2
请注意,您可以使用以下方式编写与rgb2gray相同的函数:gray = np.mean(rgb, -1)。如果实际上是RGBA,则可能需要在此处添加rgb[...,:3] - seberg
嗯,gray = np.mean(rgb, -1) 运行良好。谢谢。不使用这个的原因是什么?为什么要使用下面答案中的解决方案呢? - waspinator
8
“灰度维基百科页面”(http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale)指出将RGB转换为灰度的方法并不唯一,但提供了一些基于亮度的常用公式。这与“np.mean(rgb, -1)”有很大不同。 - unutbu
3
我想您需要Matlab的版本吗?0.2989 * R + 0.5870 * G + 0.1140 * B,我假设这是标准的做法。 - waspinator
1
难道不应该是0.2990 * R + 0.5870 * G + 0.1140 * B吗?权重总和应该等于1而不是0.9999。在这里检查:https://en.wikipedia.org/wiki/Grayscale - Alexandre Cartaxo
您可以在此处找到有关将图像转换为灰度的不同方法的详细讨论 - https://e2eml.school/convert_rgb_to_grayscale.html - truth
15个回答

5
使用img.Convert()函数,支持“L”、“RGB”和“CMYK.”模式。
import numpy as np
from PIL import Image

img = Image.open("IMG/center_2018_02_03_00_34_32_784.jpg")
img.convert('L')

print np.array(img)

输出:

[[135 123 134 ...,  30   3  14]
 [137 130 137 ...,   9  20  13]
 [170 177 183 ...,  14  10 250]
 ..., 
 [112  99  91 ...,  90  88  80]
 [ 95 103 111 ..., 102  85 103]
 [112  96  86 ..., 182 148 114]]

2
第5行应该是 img = img.convert('L') 吗? - Allan Ruin

3

我通过谷歌搜索了解到这个问题,寻找一种将已加载的图像转换为灰度的方法。

以下是使用SciPy进行操作的方法:

import scipy.misc
import scipy.ndimage

# Load an example image
# Use scipy.ndimage.imread(file_name, mode='L') if you have your own
img = scipy.misc.face()

# Convert the image
R = img[:, :, 0]
G = img[:, :, 1]
B = img[:, :, 2]
img_gray = R * 299. / 1000 + G * 587. / 1000 + B * 114. / 1000

# Show the image
scipy.misc.imshow(img_gray)

1
不错。我只想指出一个更短的解决方案是 img_gray = numpy.average(img, weights=[0.299, 0.587, 0.114], axis=2) - Akavall
scipy.ndimage.imread()scipy.misc.imread()在SciPy 1.0.0中已被正式弃用,并将在SciPy 1.2.0中被永久删除。您可能只想使用Pillow的内置灰度转换支持(例如unutbu答案)。 - Cecil Curry
你的代码中有哪些神奇数字?299、587、114... - Dave Kielpinski

2

当一个像素的RGB三个颜色通道的值相同时,该像素将始终处于灰度格式。

将RGB图像转换为灰度图像的一个简单而直观的方法是对每个像素中所有颜色通道的平均值进行计算,并将该值分配回该像素。

import numpy as np
from PIL import Image

img=np.array(Image.open('sample.jpg')) #Input - Color image
gray_img=img.copy()

for clr in range(img.shape[2]):
    gray_img[:,:,clr]=img.mean(axis=2) #Take mean of all 3 color channels of each pixel and assign it back to that pixel(in copied image)

#plt.imshow(gray_img) #Result - Grayscale image

输入图像: 输入图像

输出图像: 输出图像


你可以使用这个:img = np.mean(color_img, axis=2) 但这并不是正确的方法,阅读这篇文章:https://e2eml.school/convert_rgb_to_grayscale.html - ffsedd
灰度图像仍然有3个通道。为什么会这样? - Regi Mathew

0
假设我的图像在原始形式下是3通道的。
my_image = cv2.imread("./5d10e5939c5101174c54bb98.png")
#greyscaling the image
image_sum = my_image.sum(axis=2)
new_image = image_sum/image_sum.max() 

new_image是我的单通道灰度图像

plt.figure(figsize=[12,8])
plt.imshow(new_image, cmap=plt.cm.gray)
plt.show()

[ 这是不使用cv2的cv2.COLOR_BGR2GRAY参数或PIL的.convert('L')方法 ]

-3
image=myCamera.getImage().crop(xx,xx,xx,xx).scale(xx,xx).greyscale()

你可以直接使用 greyscale() 进行转换。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接