web-dev-qa-db-fra.com

Comment 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 coupent le tableau, mais ce n'est pas la même chose que convertir RVB en niveaux de gris d'après ce que j'ai compris.

lum_img = img[:,:,0]

J'ai du mal à croire que numpy ou matplotlib n’ait pas de fonction intégrée permettant de convertir de rgb en gris. N'est-ce pas une opération courante dans le traitement d'images?

J'ai écrit une fonction très simple qui fonctionne avec l'image importée avec 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 celui qui est intégré.

mise en œuvre 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
153
waspinator

Pourquoi ne pas le faire avec Pillow :

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

Utiliser matplotlib et la formule

Y' = 0.2989 R + 0.5870 G + 0.1140 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.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()
235
unutbu

Vous pouvez également utiliser scikit-image , qui fournit certaines fonctions pour convertir une image en ndarray, comme rgb2gray.

from skimage import color
from skimage import io

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

Remarques : 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

Alternativement, vous pouvez lire une image en niveaux de gris en:

from skimage import io
img = io.imread('image.png', as_gray=True)
56
yangjie

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

Temps moyens d'exécution

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 les tableaux de 0 à 1. De plus, les couleurs sont converties légèrement différentes, voir l'exemple du jeu de données CUB-200.

SkImage:SkImage

PIL :PIL

SciPy :SciPy

Original:Original

Diff :enter image description here

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

    pour k, v dans run_times.items (): print ('{: 5}: {: 0.3f} seconds'.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
    
42
Maximilian Peters

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

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

De plus, si vous souhaitez lire l’image en RVB, effectuez un traitement, puis convertissez-la en échelle de gris que vous pouvez utiliser cvtcolor à partir d’OpenCV:

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

La méthode la plus rapide et la plus courante consiste à utiliser Oreiller , 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')
19
YPCrumble

Le didacticiel est une triche, car il commence par une image en niveaux de gris encodée en RVB. Ils découpent donc un seul canal de couleur et le traitent en niveaux de gris. Les étapes de base que vous devez faire sont de passer de l’espace colorimétrique RVB à un espace colorimétrique codant avec un élément proche du modèle luma/chroma, tel que YUV/YIQ ou HSL/HSV, puis de découper le canal en forme de luma et de l’utiliser comme votre image en niveaux de gris. matplotlib ne semble pas fournir de mécanisme pour convertir en YUV/YIQ, mais 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 de luma, mais cela signifie que vous pouvez tout faire en matplotlib.

Contexte:

Vous pouvez également utiliser PIL ou la fonction intégrée colorsys.rgb_to_yiq() pour convertir un espace colorimétrique avec une valeur de luminosité réelle. Vous pouvez également vous lancer et lancer votre propre convertisseur de luminance seule, bien que ce soit probablement excessif.

11
Silas Ray

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

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

6
dtk

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

Toutefois, le logiciel GIMP convertissant les couleurs en logiciel d’image en niveaux de gris dispose de trois algorithmes pour effectuer cette tâche.

6
iNet

Utilisez img.Convert (), prend en charge les modes “L”, “RVB” et “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)

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]]
4
naren

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()
4
am.mansour

Je suis arrivé à cette question via Google, cherchant un moyen de convertir une image déjà chargée en niveaux de gris.

Voici une façon 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
Martin Thoma