我试图使用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分钟内导入图像。它的效率非常低,但这就是为什么我希望内置一个专业的实现。

塞巴斯蒂安改进了我的功能,但我仍然希望找到内置的功能。

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

当前回答

使用这个公式

Y' = 0.299 R + 0.587 G + 0.114 B 

我们可以

import imageio
import numpy as np
import matplotlib.pyplot as plt

pic = imageio.imread('(image)')
gray = lambda rgb : np.dot(rgb[... , :3] , [0.299 , 0.587, 0.114]) 
gray = gray(pic)  
plt.imshow(gray, cmap = plt.get_cmap(name = 'gray'))

然而,将彩色图像转换为灰度图像的GIMP软件有三种算法来完成这项任务。

其他回答

使用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]]

用Pillow怎么做呢:

from PIL import Image
img = Image.open('image.png').convert('L')
img.save('greyscale.png')

如果在输入图像中存在alpha(透明)通道,并且应该保留,则使用模式LA:

img = Image.open('image.png').convert('LA')

使用matplotlib和公式

Y' = 0.2989 R + 0.5870 G + 0.1140 B 

你可以这样做:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

def rgb2gray(rgb):
    return np.dot(rgb[...,:3], [0.2989, 0.5870, 0.1140])

img = mpimg.imread('image.png')     
gray = rgb2gray(img)    
plt.imshow(gray, cmap=plt.get_cmap('gray'), vmin=0, vmax=1)
plt.show()

在Ubuntu 16.04 LTS (Xeon E5 2670 with SSD)上运行Python 3.5,测试了1000个RGBA PNG图像(224 x 256像素)的速度。

平均运行时间

pil: 1.037秒

1040秒

Sk: 2秒120

PIL和SciPy给出了相同的numpy数组(范围从0到255)。SkImage给出了从0到1的数组。此外,颜色转换略有不同,请参阅来自CUB-200数据集的示例。

SkImage:

PIL:

SciPy:

原:

差异:

Code

Performance run_times = dict(sk=list(), pil=list(), scipy=list()) for t in range(100): start_time = time.time() for i in range(1000): z = random.choice(filenames_png) img = skimage.color.rgb2gray(skimage.io.imread(z)) run_times['sk'].append(time.time() - start_time) start_time = time.time() for i in range(1000): z = random.choice(filenames_png) img = np.array(Image.open(z).convert('L')) run_times['pil'].append(time.time() - start_time) start_time = time.time() for i in range(1000): z = random.choice(filenames_png) img = scipy.ndimage.imread(z, mode='L') run_times['scipy'].append(time.time() - start_time) for k, v in run_times.items(): print('{:5}: {:0.3f} seconds'.format(k, sum(v) / len(v))) Output z = 'Cardinal_0007_3025810472.jpg' img1 = skimage.color.rgb2gray(skimage.io.imread(z)) * 255 IPython.display.display(PIL.Image.fromarray(img1).convert('RGB')) img2 = np.array(Image.open(z).convert('L')) IPython.display.display(PIL.Image.fromarray(img2)) img3 = scipy.ndimage.imread(z, mode='L') IPython.display.display(PIL.Image.fromarray(img3)) Comparison img_diff = np.ndarray(shape=img1.shape, dtype='float32') img_diff.fill(128) img_diff += (img1 - img3) img_diff -= img_diff.min() img_diff *= (255/img_diff.max()) IPython.display.display(PIL.Image.fromarray(img_diff).convert('RGB')) Imports import skimage.color import skimage.io import random import time from PIL import Image import numpy as np import scipy.ndimage import IPython.display Versions skimage.version 0.13.0 scipy.version 0.19.1 np.version 1.13.1

The tutorial is cheating because it is starting with a greyscale image encoded in RGB, so they are just slicing a single color channel and treating it as greyscale. The basic steps you need to do are to transform from the RGB colorspace to a colorspace that encodes with something approximating the luma/chroma model, such as YUV/YIQ or HSL/HSV, then slice off the luma-like channel and use that as your greyscale image. matplotlib does not appear to provide a mechanism to convert to YUV/YIQ, but it does let you convert to HSV.

尝试使用matplotlib.colors.rgb_to_hsv(img),然后从数组中切片最后一个值(V)来获取灰度。它与亮度值不完全相同,但它意味着您可以在matplotlib中完成所有操作。

背景:

http://matplotlib.sourceforge.net/api/colors_api.html http://en.wikipedia.org/wiki/HSL_and_HSV

或者,您可以使用PIL或内置的colorsys.rgb_to_yiq()来转换为具有真正亮度值的色彩空间。你也可以完全投入到你自己的光转换器中,尽管这可能有点过头了。

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

下面是一种使用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)