Comment puis-je convertir une image RVB en niveaux de gris en Python?

J'essaie d'utiliser matplotlib pour lire une image RVB et la convertir en niveaux de gris.

Dans matlab j'utilise ceci:

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

Dans le tutoriel matplotlib ils ne le couvrent pas. Ils viennent de lire dans l'image

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

Et puis ils découpent le tableau, mais ce n'est pas la même chose que de convertir RVB en niveaux de gris d'après ce que je comprends.

lum_img = img[:,:,0]

J'ai du mal à croire que numpy ou matplotlib n'a pas de fonction intégrée pour convertir du RVB en gris. N'est-ce pas c'est une opération courante dans le traitement d'image?

J'ai écrit une fonction très simple qui fonctionne avec l'image importée en utilisant imread en 5 minutes. C'est horriblement inefficace, mais c'est pourquoi j'espérais une implémentation professionnelle intégrée.

Sebastian a amélioré ma fonction, mais j'espère toujours trouver celle intégrée.

Implémentation de 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
109
demandé sur Mark Amery 2012-08-30 20:37:37

12 réponses

Que diriez-vous de le faire avec oreiller :

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

En utilisant matplotlib et la formule

Y' = 0.299 R + 0.587 G + 0.114 B 

Vous pourriez faire:

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()
168
répondu unutbu 2018-02-20 22:57:17

Vous pouvez aussi utiliser scikit-image, qui fournit des fonctions pour convertir une image en ndarray, comme rgb2gray.

from skimage import color
from skimage import io

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

Notes : les poids utilisés dans cette conversion sont étalonnés pour les luminophores CRT contemporains: Y = 0,2125 R + 0,7154 G + 0,0721 B

Vous pouvez également lire l'image en niveaux de gris par:

from skimage import io
img = io.imread('image.png', as_grey=True)
39
répondu yangjie 2017-03-26 14:14:43

Trois des méthodes suggérées ont été testées pour la vitesse avec 1000 images PNG RGBA (224 x 256 pixels) fonctionnant avec Python 3.5 sur Ubuntu 16.04 LTS (Xeon E5 2670 avec SSD).

Durée moyenne

pil : 1.037 secondes

scipy: 1.040 secondes

sk : 2.120 secondes

PIL et SciPy ont donné des tableaux numpy identiques (allant de 0 à 255). SkImage donne des tableaux de 0 à 1. En plus les couleurs sont converties légèrement différentes, voir le exemple de l'ensemble de données CUB-200.

SkImage: SkImage

PIL : PIL

SciPy : SciPy

Original: Original

Diff : entrez la description de l'image ici

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)
    

    Pour k, v dans run_times.article(): imprimer('{:5}: {:0.3 f} secondes.format (k, sum (v) / len (v)))

  2. Sortie
    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. comparaison
    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. importations
    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
    
26
répondu Maximilian Peters 2017-09-27 13:46:15

Vous pouvez toujours lire le fichier image en niveaux de gris dès le début en utilisant imread de OpenCV:

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

En outre, si vous voulez lire L'image en RVB, faites un peu de traitement, puis convertissez en échelle de gris que vous pouvez utiliser cvtcolor de OpenCV:

gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
19
répondu Diamantatos Paraskevas 2017-01-04 13:00:58

Le moyen le plus rapide et actuel est d'utiliser Pillow , installé via pip install Pillow.

Le code est alors:

from PIL import Image
img = Image.open('input_file.jpg').convert('L')
img.save('output_file.jpg')
14
répondu YPCrumble 2015-12-02 15:25:32

Le tutoriel triche car il commence par une image en niveaux de gris codée en RVB, donc ils ne font que découper un seul canal de couleur et le traiter en niveaux de gris. Les étapes de base que vous devez faire sont de transformer de l'espace colorimétrique RVB en un espace colorimétrique qui Code avec quelque chose qui se rapproche du modèle luma/chroma, tel que YUV/YIQ ou HSL/HSV, puis découper le canal de type luma et l'utiliser comme image en niveaux de gris. matplotlib ne semble pas fournir un mécanisme pour convertir en YUV / YIQ, mais il vous permet de convertir en HSV.

Essayez d'utiliser matplotlib.colors.rgb_to_hsv(img) puis découpez la dernière valeur (V) du tableau pour votre échelle de gris. Ce n'est pas tout à fait la même chose qu'une valeur luma, mais cela signifie que vous pouvez tout faire dans matplotlib.

Contexte:

Vous pouvez également utiliser PIL ou le colorsys.rgb_to_yiq() intégré pour convertir en un espace de couleurs avec un vrai la luminance de la valeur. Vous pouvez également aller tout et rouler votre propre convertisseur luma seulement, bien que ce soit probablement exagéré.

10
répondu Silas Ray 2012-08-30 17:19:49

Si vous utilisez déjà NumPy/SciPy, vous pouvez également utiliser :

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

Hth, dtk

5
répondu dtk 2016-08-19 23:35:17

Je suis venu à cette question via Google, à la recherche d'un moyen de convertir une image déjà chargée en niveaux de gris.

Voici un moyen de le faire avec 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)
3
répondu Martin Thoma 2016-11-10 09:05:40

Vous pourriez faire:

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

        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()
3
répondu am.mansour 2017-11-19 19:15:37

Utiliser img.Convertir (), prend en charge "L", " RVB " et " CMJN."le mode de

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)

Sortie:

[[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
répondu naren 2018-02-03 07:19:19

Utiliser cette formule

Y' = 0.299 R + 0.587 G + 0.114 B 

Nous pouvons faire

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

Cependant, le logicielGIMP convertissant la couleur en niveaux de gris a trois algorithmes pour effectuer la tâche.

1
répondu iPython 2018-07-28 11:44:21
image=myCamera.getImage().crop(xx,xx,xx,xx).scale(xx,xx).greyscale()

Vous pouvez utiliser greyscale() directement de la transformation.

-3
répondu Qian Han 2016-03-16 09:47:49