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
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()
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)
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.
Code
-
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)))
- 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))
- 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'))
- 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
- Versions
skimage.version 0.13.0 scipy.version 0.19.1 np.version 1.13.1
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)
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é.
Si vous utilisez déjà NumPy/SciPy, vous pouvez également utiliser :
scipy.ndimage.imread(file_name, mode='L')
Hth, dtk
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)
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()
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]]
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.
image=myCamera.getImage().crop(xx,xx,xx,xx).scale(xx,xx).greyscale()
Vous pouvez utiliser greyscale()
directement de la transformation.