Estou tentando usar matplotlib
para ler uma imagem RGB e convertê-la em escala de cinza.
No matlab eu uso isso:
img = rgb2gray(imread('image.png'));
No tutorial matplotlib, eles não abordam isso. Eles apenas lêem na imagem
import matplotlib.image as mpimg
img = mpimg.imread('image.png')
e eles dividem a matriz, mas isso não é o mesmo que converter RGB em escala de cinza do que eu entendo.
lum_img = img[:,:,0]
Acho difícil acreditar que numpy ou matplotlib não tenha uma função integrada para converter de rgb para cinza. Isso não é uma operação comum no processamento de imagens?
Eu escrevi uma função muito simples que funciona com a imagem importada usando imread
em 5 minutos. É terrivelmente ineficiente, mas é por isso que eu esperava uma implementação profissional integrada.
Sebastian melhorou minha função, mas ainda espero encontrar a incorporada.
implementação do 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
fonte
gray = np.mean(rgb, -1)
. Talvezrgb[...,:3]
exista se for realmente rgba.gray = np.mean(rgb, -1)
funciona bem. obrigado. Existe alguma razão para não usar isso? Por que eu usaria as soluções nas respostas abaixo?np.mean(rgb, -1)
.0.2989 * R + 0.5870 * G + 0.1140 * B
Estou assumindo que é a maneira padrão de fazê-lo.Respostas:
Que tal fazer isso com o Pillow :
Usando matplotlib e a fórmula
você poderia fazer:
fonte
matplotlib
por algum outro motivo, ele poderá usar o built-incolorsys.rgb_to_yiq()
para transformar mais uma fatia para obter apenas o canal luma..convert('LA')
? por que não.convert('gray')
? Parece desnecessariamente enigmático. A documentação do PIL não menciona nada sobre 'LA' para a função de conversão.cannot write mode LA as JPEG
, eu precisava usar o modo L não LAimg = Image.open('image.png').convert('LA')
precisa serimg = Image.open('image.png').convert('L')
LA
modo possui luminosidade (brilho) e alfa. Se você usar oLA
modo,greyscale.png
haverá uma imagem RGBA com o canal alfa deimage.png
preservado. Se você usar oL
modo,greyscale.png
haverá uma imagem RGB (sem alfa).Você também pode usar o scikit-image , que fornece algumas funções para converter uma imagem
ndarray
, comorgb2gray
.Notas : Os pesos usados nesta conversão são calibrados para os fósforos de CRT contemporâneos: Y = 0,2125 R + 0,7154 G + 0,0721 B
Como alternativa, você pode ler a imagem em escala de cinza por:
fonte
cmap
comogray' then only the image is shown as gray in
pyplot.imshow () `? Alguma ideia ? Onde eu estou errado?Três dos métodos sugeridos foram testados quanto à velocidade com 1000 imagens PNG RGBA (224 x 256 pixels) em execução com Python 3.5 no Ubuntu 16.04 LTS (Xeon E5 2670 com SSD).
Tempos médios de execução
pil :
1.037 segundosscipy:
1.040 segundossk :
2.120 segundosPIL e SciPy deram
numpy
matrizes idênticas (variando de 0 a 255). O SkImage fornece matrizes de 0 a 1. Além disso, as cores são convertidas ligeiramente diferentes, veja o exemplo do conjunto de dados CUB-200.SkImage:
PIL :
SciPy :
Original:
Diff :
Código
atuação
fonte
Você sempre pode ler o arquivo de imagem como escala de cinza desde o início, usando o
imread
OpenCV:Além disso, caso você queira ler a imagem como RGB, faça algum processamento e, em seguida, converta em Escala de cinza que você pode usar
cvtcolor
no OpenCV:fonte
0
bandeira écv2.CV_LOAD_IMAGE_GRAYSCALE
.A maneira mais rápida e atual é usar o Pillow , instalado via
pip install Pillow
.O código é então:
fonte
convert
retorna uma cópia convertida do imagemO tutorial está enganando, porque está começando com uma imagem em escala de cinza codificada em RGB, para que eles apenas cortem um canal de cor única e o tratem como em escala de cinza. As etapas básicas que você precisa fazer são transformar o espaço de cores RGB em um espaço de cores que codifique algo semelhante ao modelo luma / chroma, como YUV / YIQ ou HSL / HSV, em seguida, corte o canal tipo luma e use-o como sua imagem em escala de cinza.
matplotlib
parece não fornecer um mecanismo para converter em YUV / YIQ, mas permite converter em HSV.Tente usar e
matplotlib.colors.rgb_to_hsv(img)
depois fatiar o último valor (V) da matriz para sua escala de cinza. Não é exatamente o mesmo que um valor luma, mas significa que você pode fazer tudomatplotlib
.Fundo:
Como alternativa, você pode usar o PIL ou o builtin
colorsys.rgb_to_yiq()
para converter em um espaço de cores com um verdadeiro valor de luma. Você também pode usar o seu próprio conversor de luma, mas isso provavelmente é um exagero.fonte
Usando esta fórmula
Nós podemos fazer
No entanto, o software de conversão de cores em escala de cinza do GIMP possui três algoritmos para executar a tarefa.
fonte
Se você já usa o NumPy / SciPy, também pode usar :
scipy.ndimage.imread(file_name, mode='L')
fonte
scipy.ndimage.imread()
escipy.misc.imread()
são formalmente obsoleto em SciPy 1.0.0 e será removido permanentemente em SciPy 1.2.0. Embora a documentação do SciPy recomendeimageio.imread()
como um substituto adequado, a API dessa função é essencial para o absurdo. Ele não oferece suporte à conversão em escala de cinza e, portanto, permanece inadequado para muitos aplicativos - incluindo o nosso.</sigh>
você poderia fazer:
fonte
Use img.Convert (), suporta "L", "RGB" e "CMYK". modo
Resultado:
fonte
img = img.convert('L')
?Cheguei a essa pergunta pelo Google, procurando uma maneira de converter uma imagem já carregada em escala de cinza.
Aqui está uma maneira de fazer isso com o SciPy:
fonte
img_gray = numpy.average(img, weights=[0.299, 0.587, 0.114], axis=2)
numpy.average
é um pouco mais rápido, mas não é praticamente diferente. Sua solução é clara e possui informações relevantes sobre R, G, B, portanto, eu a manteria. Meu comentário foi mais uma opção adicional, não uma substituição.scipy.ndimage.imread()
escipy.misc.imread()
são formalmente obsoleto em SciPy 1.0.0 e será removido permanentemente em SciPy 1.2.0. Você provavelmente só quer usar suporte de conversão embutida em tons de cinza do Pillow (ala unutbu de resposta ), em vez.Você pode usar
greyscale()
diretamente para a transformação.fonte