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

was*_*tor 170 python matplotlib

我正在尝试使用matplotlibRGB图像读取并将其转换为灰度.

在matlab中我用这个:

img = rgb2gray(imread('image.png'));
Run Code Online (Sandbox Code Playgroud)

matplotlib教程中,他们没有涵盖它.他们只是读入图像

import matplotlib.image as mpimg
img = mpimg.imread('image.png')
Run Code Online (Sandbox Code Playgroud)

然后他们切割数组,但这与我理解的将RGB转换为灰度不同.

lum_img = img[:,:,0]
Run Code Online (Sandbox Code Playgroud)

我发现很难相信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
Run Code Online (Sandbox Code Playgroud)

unu*_*tbu 257

如何用枕头做:

from PIL import Image
img = Image.open('image.png').convert('LA')
img.save('greyscale.png')
Run Code Online (Sandbox Code Playgroud)

使用matplotlib和公式

Y' = 0.2989 R + 0.5870 G + 0.1140 B 
Run Code Online (Sandbox Code Playgroud)

你可以这样做:

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()
Run Code Online (Sandbox Code Playgroud)

  • 为什么`.convert('LA')`?为什么不`.convert('grey')`?似乎不必要地神秘.[PIL文档](http://www.pythonware.com/library/pil/handbook/image.htm)没有提到有关转换功能的'LA'的任何内容. (31认同)
  • 使用PIL:`不能将模式LA写为JPEG`,我需要使用L模式而不是LA (20认同)
  • @BluePython:`LA`模式有亮度(亮度)和alpha.如果你使用`LA`模式,那么`greyscale.png`将是一个RGBA图像,其alpha信道保存为`image.png`.如果你使用`L`模式,那么`greyscale.png`将是一个RGB图像(没有alpha). (11认同)
  • 如果由于其他原因他必须使用`matplotlib`,他应该能够使用内置的'colorsys.rgb_to_yiq()`来转换加一个切片来获得亮度通道. (3认同)
  • 获得与[Matlab版本]完全相同的结果(http://stackoverflow.com/questions/12201577/how-can-i-convert-an-rgb-image-into-grayscale-in-python/12201744#comment16351468_12201577 )(与[ITU-R 601-2亮度变换]略有不同(http://pillow.readthedocs.io/en/3.2.x/reference/Image.html#PIL.Image.Image.convert),I指定一个调整后的matix:`img.convert('L',(0.2989,0.5870,0.1140,0))`. (3认同)
  • 这个`img = Image.open('image.png').convert('LA')`需要是`img = Image.open('image.png').convert('L')` (3认同)
  • 如果它对任何人的用例都很重要,请注意“LA”是 8 位模式,因此“.convert('LA')”会将颜色深度降低到 8 位(如果颜色深度最初较高)。 (2认同)

yan*_*jie 60

您还可以使用scikit-image,它提供了一些转换图像的功能ndarray,例如rgb2gray.

from skimage import color
from skimage import io

img = color.rgb2gray(io.imread('image.png'))
Run Code Online (Sandbox Code Playgroud)

注意:此转换中使用的权重是针对当代CRT荧光粉校准的:Y = 0.2125 R + 0.7154 G + 0.0721 B

或者,您可以通过以下方式读取灰度图像:

from skimage import io
img = io.imread('image.png', as_gray=True)
Run Code Online (Sandbox Code Playgroud)


Max*_*ers 46

在Ubuntu 16.04 LTS(带有SSD的Xeon E5 2670)上使用Python 3.5运行的1000 RGBA PNG图像(224 x 256像素)测试了三种建议的方法的速度.

平均运行时间

pil : 1.037秒

scipy: 1.040秒

sk : 2.120秒

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

SkImage: SkImage

PIL : PIL

SciPy : SciPy的

Original: 原版的

Diff : 在此输入图像描述

  1. 性能

    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)
    
    Run Code Online (Sandbox Code Playgroud)

    for k,v in run_times.items():print('{:5}:{:0.3f} seconds'.format(k,sum(v)/ len(v)))

  2. 产量
    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))
    
  3. 对照
    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'))
    
  4. 进口
    import skimage.color
    import skimage.io
    import random
    import time
    from PIL import Image
    import numpy as np
    import scipy.ndimage
    import IPython.display
    
  5. 版本
    skimage.version
    0.13.0
    scipy.version
    0.19.1
    np.version
    1.13.1
    

  • SciPy的图像I/O实际上是*PIL/Pillow.因此,测试SciPy有效地重新测试PIL/Pillow,而SciPy的包装函数引入的开销可以忽略不计.替换OpenCV(它不会*利用PIL/Pillow)替代SciPy(确实如此)会更加有用.尽管如此,感谢您的专业基准测试!SciKit强加的明显减速令人着迷......**并且令人恐惧.** (5认同)

Dia*_*vas 23

您始终可以使用imreadOpenCV 从头开始将图像文件读取为灰度:

img = cv2.imread('messi5.jpg', 0)
Run Code Online (Sandbox Code Playgroud)

此外,如果您想要将图像读取为RGB,请执行一些处理,然后转换为您可以cvtcolor从OpenCV 使用的灰度:

gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
Run Code Online (Sandbox Code Playgroud)

  • Ftr:`0`标志是[`cv2.CV_LOAD_IMAGE_GRAYSCALE`](http://docs.opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html#cv2.imread). (6认同)

YPC*_*ble 20

最快和最新的方法是使用Pillow,通过安装pip install Pillow.

那么代码就是:

from PIL import Image
img = Image.open('input_file.jpg').convert('L')
img.save('output_file.jpg')
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果您没有像上面的示例那样链接您的方法,`convert`将返回图像的转换副本 (3认同)

Sil*_*Ray 11

该教程是作弊的,因为它是以RGB编码的灰度图像开始的,因此它们只是切割单个颜色通道并将其视为灰度.您需要做的基本步骤是从RGB颜色空间转换为用近似亮度/色度模型编码的颜色空间,例如YUV/YIQ或HSL/HSV,然后切掉类似亮度的通道并将其用作你的灰度图像. matplotlib似乎没有提供转换为YUV/YIQ的机制,但它确实允许您转换为HSV.

尝试使用matplotlib.colors.rgb_to_hsv(img)然后从数组中切割最后一个值(V)作为灰度.它与亮度值并不完全相同,但它意味着你可以全部完成matplotlib.

背景:

或者,您可以使用PIL或内置colorsys.rgb_to_yiq()转换为具有真实亮度值的颜色空间.你也可以全力以赴推出自己的仅限转换器,尽管这可能有点过头了.


小智 8

你可以这样做:

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

def rgb_to_gray(img):
        grayImage = np.zeros(img.shape)
        R = np.array(img[:, :, 0])
        G = np.array(img[:, :, 1])
        B = np.array(img[:, :, 2])

        R = (R *.299)
        G = (G *.587)
        B = (B *.114)

        Avg = (R+G+B)
        grayImage = img.copy()

        for i in range(3):
           grayImage[:,:,i] = Avg
           
        return grayImage       

image = mpimg.imread("your_image.png")   
grayImage = rgb_to_gray(image)  
plt.imshow(grayImage)
plt.show()
Run Code Online (Sandbox Code Playgroud)


dtk*_*dtk 7

如果您已经使用NumPy/SciPy,您可以使用:

scipy.ndimage.imread(file_name, mode='L')

Hth,dtk

  • 两个`scipy.ndimage.imread()`和`scipy.misc.imread()`是[**正式弃用**](https://docs.scipy.org/doc/scipy/reference/generated/scipy. ndimage.imread.html)在SciPy的1.0.0和将**永久SciPy的1.2.0除去**.而SciPy的文档建议[`imageio.imread()`](https://imageio.readthedocs.io/en/latest/userapi.html?highlight=imread#imageio.imread),其为合适的替代,该函数的API是裸骨子到了荒谬的地步.它提供*没有*灰度转换支持,因此仍然不适合许多应用 - 包括我们.`</叹息>` (5认同)
  • @CecilCurry,如何使用imageio将彩色图像转换为灰度图像? (4认同)

M.I*_*nat 6

使用这个公式

Y' = 0.299 R + 0.587 G + 0.114 B 
Run Code Online (Sandbox Code Playgroud)

我们能做的

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'))
Run Code Online (Sandbox Code Playgroud)

但是,GIMP将颜色转换为灰度图像软件有三种算法可以完成任务。


Sha*_*vid 6

使用 OpenCV 就很简单:

import cv2

im = cv2.imread("flower.jpg")

# To Grayscale
im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
cv2.imwrite("grayscale.jpg", im)

# To Black & White
im = cv2.threshold(im, 127, 255, cv2.THRESH_BINARY)[1]
cv2.imwrite("black-white.jpg", im)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


nar*_*ren 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)
Run Code Online (Sandbox Code Playgroud)

输出:

[[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]]
Run Code Online (Sandbox Code Playgroud)

  • 第 5 行应该是 `img = img.convert('L')` 吗? (2认同)