How can I convert an RGB image into grayscale in Python?

前端 未结 12 1119
Happy的楠姐
Happy的楠姐 2020-11-22 04:43

I\'m trying to use matplotlib to read in an RGB image and convert it to grayscale.

In matlab I use this:

img = rgb2gray(imread(\'image.p         


        
相关标签:
12条回答
  • 2020-11-22 05:02

    Using this formula

    Y' = 0.299 R + 0.587 G + 0.114 B 
    

    We can do

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

    However, the GIMP converting color to grayscale image software has three algorithms to do the task.

    0 讨论(0)
  • 2020-11-22 05:05

    If you're using NumPy/SciPy already you may as well use:

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

    0 讨论(0)
  • 2020-11-22 05:06

    You can also use scikit-image, which provides some functions to convert an image in ndarray, like rgb2gray.

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

    Notes: The weights used in this conversion are calibrated for contemporary CRT phosphors: Y = 0.2125 R + 0.7154 G + 0.0721 B

    Alternatively, you can read image in grayscale by:

    from skimage import io
    img = io.imread('image.png', as_gray=True)
    
    0 讨论(0)
  • 2020-11-22 05:06

    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.

    Try using matplotlib.colors.rgb_to_hsv(img) then slicing the last value (V) from the array for your grayscale. It's not quite the same as a luma value, but it means you can do it all in matplotlib.

    Background:

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

    Alternatively, you could use PIL or the builtin colorsys.rgb_to_yiq() to convert to a colorspace with a true luma value. You could also go all in and roll your own luma-only converter, though that's probably overkill.

    0 讨论(0)
  • 2020-11-22 05:12

    How about doing it with Pillow:

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

    Using matplotlib and the formula

    Y' = 0.2989 R + 0.5870 G + 0.1140 B 
    

    you could do:

    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()
    
    0 讨论(0)
  • 2020-11-22 05:13

    Three of the suggested methods were tested for speed with 1000 RGBA PNG images (224 x 256 pixels) running with Python 3.5 on Ubuntu 16.04 LTS (Xeon E5 2670 with SSD).

    Average run times

    pil : 1.037 seconds

    scipy: 1.040 seconds

    sk : 2.120 seconds

    PIL and SciPy gave identical numpy arrays (ranging from 0 to 255). SkImage gives arrays from 0 to 1. In addition the colors are converted slightly different, see the example from the CUB-200 dataset.

    SkImage:

    PIL :

    SciPy :

    Original:

    Diff :

    Code

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

    2. 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))
      
    3. 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'))
      
    4. 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
      
    5. Versions
      skimage.version
      0.13.0
      scipy.version
      0.19.1
      np.version
      1.13.1
      
    0 讨论(0)
提交回复
热议问题