當前位置: 首頁>>技術問答>>正文


在Python中,如何將RGB圖像轉換為灰度圖像?

我正在嘗試使用matplotlib讀取RGB圖像並將其轉換為灰度圖像。

在matlab中,我使用這個:

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

matplotlib tutorial中,並沒有這個功能。這裏隻能讀取圖像

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

然後切片數組,但是這不是從我所了解的將RGB轉換為灰度。

lum_img = img[:,:,0]

編輯:

很難相信numpy或matplotlib沒有內置函數來從rgb轉換為灰色。這不是圖像處理中的常見操作嗎?

我寫了一個非常簡單的函數,可以在5分鍾內使用imread導入的圖像。但這是非常低效的,所以我希望有專業的內置實現。

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

最佳解決思路

PIL來做是可以的吧:

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

基於matplotlib和公式

Y' = 0.299 R + 0.587 G + 0.114 B 

可以這樣做:

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

def rgb2gray(rgb):
    return np.dot(rgb[...,:3], [0.299, 0.587, 0.114])

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

次佳解決思路

也可以使用scikit-image,它提供了一些功能來轉換ndarray中的圖像,如rgb2gray

from skimage import color
from skimage import io

img = color.rgb2gray(io.imread('image.png'))

注:此轉換中使用的權重是針對當前CRT熒光屏校準的:Y = 0.2125 R + 0.7154 G + 0.0721 B

或者,可以通過以下方式讀取灰度圖像:

from skimage import io
img = io.imread('image.png', as_grey=True)

第三種解決思路

可以始終使用OpenCV中的imread將圖像文件從一開始就讀取為灰度圖:

img = cv2.imread('messi5.jpg', 0)

此外,如果想讀取圖像為RGB,做一些處理,然後轉換為灰度,可以使用OpenCV中的cvtcolor

gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

第四種思路

最快和最新的方法是使用Pillow,通過pip install Pillow安裝。

代碼是:

from PIL import Image
img = Image.open('input_file.jpg').convert('L')
img.save('output_file.jpg')

第五種思路

在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 dataset.中的示例

SkImage:

python,matplotlib

PIL :

python,matplotlib

SciPy :

python,matplotlib

Original:

python,matplotlib

Diff :

python,matplotlib

代碼

  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)
    
    
    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
    

參考資料

本文由《純淨天空》出品。文章地址: https://vimsky.com/zh-tw/article/3729.html,未經允許,請勿轉載。