I have the following definition to create a function that displays an image in grayscale:
def escala_grises(imagen):
''' Transforma una imagen en color a grados de grises
ENTRADA:
- imagen: matriz de píxeles -> [[(float, float, float)]]
SALIDA:
- matriz de píxeles con la imagen de entrada en escala de grises -> [[float]]
Toma como entrada una matriz de píxeles RGB, y produce como salida una
matriz de píxeles con intensidades en escala de grises (un único valor por
cada pixel).
Para convertir una imagen en color a escala de grises hay que aplicar
los siguientes pesos para integrar los tres canales de color en un único
valor de intensidad:
- Rojo: 0.2989
- Verde: 0.5870
- Azul: 0.1140
'''
The argument imagen
is an array extracted from a ".jpeg" file using an array. Ex: [[[82, 119, 171], [91, 128, 180], [85, 122, 174], [84, 121, 173], [88, 125, 177], [84, 121, 173], [84, 121, 173], [85, 122, 174]]]
.
I'm guessing it's a 3D array since the method shape
returns (330, 600, 3)
, the 3 I think comes from the number of colors present in the "RGB" file.
The question is, how to modify the array so that the average color intensities match [0.2989, 0.5870, 0.1140]
, considering that I can only use the following imported modules:
from matplotlib import pyplot as plt
import numpy as np
-Reply to abulafia regarding the comments
Apparently, I shouldn't use métodos
the library numpy
since I'm not supposed to have given them. So I tried to recreate what you have told me using the following code:
filtro = []
for i in imagen:
for r,g,b in i:
rojo = r*0.2989
verde = g*0.5870
azul = b*0.1140
numero = [int(rojo + verde + azul)]
filtro.append(numero)
return filtro
But it gives a blank image with the error:
ValueError: Image size of 1x198000 pixels is too large. It must be less than 2^16 in each direction.
Attached Test of the grayscale function and the function to display the image:
def test_escala_grises(imagen):
grises = escala_grises(imagen)
muestra_imagen(grises, cmap='gray')
guarda_imagen('../img/grises.jpeg', grises, cmap='gray')
def muestra_imagen(imagen, cmap=None):
imagen = np.array(imagen, dtype='uint8')
plt.imshow(imagen, cmap=cmap)
plt.show()
The code that converts each pixel to grayscale is correct. But you have an error:
escala_grises()
is no longer a two-dimensional array, like the input image was, but a mere sequence of pixels. You must usereshape
to return it to its original two-dimensional shape, otherwiseplt.imgshow()
it won't know how to display it.cmap="Gray_r"
to use a grayscale where 0 represents black and 255 represents white (the default is the other way around).Fixing these issues:
Example of use (with the following image, taken from here )
Result:
Update
So that it is not necessary to use
np.reshape()
, the result returned byescala_grises()
should be a list of lists, so that each of its elements represents a row (with as many elements as there were columns in the original image).The following code implements this version: