Por qué funciona: Unidad 1.2: Captura de la imagen, Unidad 1.3: La imagen como datos
Abrir una imagen y leer sus píxeles en OpenCV
Carga una foto con cv2.imread, comprueba que es una rejilla de números con forma y tipo, y lee un píxel y el brillo medio de una foto tomada dos pasos demasiado oscura.
Traducción asistida por máquina del original en inglés. Los números, el código y las referencias se comprobaron contra él; el texto no fue revisado por un hablante nativo. Leer el original. Los labs interactivos y el código están en inglés.
Para una computadora, una foto es una tabla de números: un número por color en cada punto. Esta lección abre una foto y lee esa tabla.

Dónde ya lo has visto: el cuentagotas de cualquier editor de imágenes, que muestra los números bajo el cursor; el diálogo Puntero de GIMP; la lectura RGB de una herramienta para capturar colores de la pantalla.
TL;DR. Abrir una foto en OpenCV te da una rejilla simple de números que puedes inspeccionar y modificar. Esta tiene 639 filas por 960 columnas por 3 canales de color con valores de 8 bits, y su brillo medio es 56,6 de 255, por eso se ve oscura.
El problema
Este módulo corrige la foto de arriba. Es una de dieciocho exposiciones de la misma lámpara y la misma carta de colores del HDR Photographic Survey [3], y se tomó a 1,3 segundos, unos dos pasos (casi cuatro veces menos luz) por debajo de la exposición de 5 segundos que el módulo usa como objetivo. Antes de corregir nada, necesitas ver qué te entrega OpenCV cuando abre el archivo.
Abre la imagen
cv2.imread lee el archivo y devuelve un array de NumPy [1]. Pulsa Ejecutar: el código es Python y OpenCV de verdad, ejecutándose en tu navegador.
import cv2
img = cv2.imread("dark.webp")
print("shape:", img.shape)
print("dtype:", img.dtype)
cv2.imshow("dark.webp", img)shape: (639, 960, 3) dtype: uint8
| Parte | Qué te dice |
|---|---|
shape (639, 960, 3) | 639 filas (alto), 960 columnas (ancho), 3 canales |
dtype uint8 | cada valor es un número entero de 0 a 255 |
cv2.imshow | muestra el array como imagen; aquí aparece debajo de la celda |
El orden es primero filas, luego columnas. El alto va antes que el ancho, al revés de como se suelen escribir los tamaños de imagen (“960 × 639”), y es lo primero que confunde a quien empieza.
Lee un píxel, luego la imagen entera
Indexar el array con [fila, columna] da los tres valores de un píxel. OpenCV los guarda como azul, verde, rojo, no rojo, verde, azul: su modo de lectura por defecto carga “the BGR 8-bit format” [1]. Convertir a gris junta los tres en un único valor de brillo por píxel, y la media de esos valores resume en un número qué tan clara es la foto.
# Un píxel: fila 320, columna 480. OpenCV guarda B, G, R.
print("pixel at row 320, column 480:", img[320, 480])
# La imagen entera en un número: su brillo medio
grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
print("mean brightness:", round(grey.mean(), 1), "of 255")pixel at row 320, column 480: [140 175 206] mean brightness: 56.6 of 255
Ese píxel está en el resplandor del fondo de la pantalla de la lámpara, por eso es claro. La foto en conjunto tiene una media de 56,6: casi todo es mesa y pared oscuras. La exposición de 5 segundos de la misma escena, que el módulo usa como objetivo, tiene una media de 104,7, y la lección 2 lo muestra con un histograma.
Rómpelo
Muchas otras bibliotecas de Python esperan rojo, verde, azul. Pásales un array de OpenCV sin convertir y los canales azul y rojo se intercambian. La celda de abajo hace el cambio a propósito para que veas cómo queda: la lámpara cálida se vuelve azul fría.
# Finge que otra biblioteca leyó el array como R, G, B
swapped = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
cv2.imshow("blue and red swapped", swapped)
Tu turno
Encuentra el mayor valor de gris de la foto y guárdalo en brightest.
brightest = 0 # cámbialo por el mayor valor de gris de img
print(brightest)Por qué funciona
Una cámara cuenta la luz que llegó a cada fotositio durante la exposición. Guardar el resultado muestrea la escena en una rejilla y cuantiza cada valor en uno de 256 niveles [2], y de ahí vienen la forma y el uint8. La lección An image is an array (en inglés) explica qué significan la forma y el tipo, From photons to counts de dónde salen los números, y Colour spaces por qué hay tres canales. Las tres están en la ruta de Fundamentos, unidades 1.2 y 1.3.
Errores comunes
imreaddevuelveNoneen lugar de fallar. Una ruta equivocada no da error hasta que la siguiente línea toca el array. Compruebaimg is Nonecuando el archivo pueda no existir.- Azul y rojo intercambiados. OpenCV usa B, G, R; matplotlib, Pillow y casi todo el código web usan R, G, B. Convierte con
cv2.cvtColor(img, cv2.COLOR_BGR2RGB)antes de pasar el array. img[x, y]en lugar deimg[y, x]. Las filas van primero. En una imagen que no es cuadrada, esto lee el píxel equivocado o falla con un error de índice.cv2.imshowen un notebook. En un script abre una ventana y necesitacv2.waitKey; en Colab y Jupyter no funciona. El notebook del módulo muestra las imágenes con matplotlib.
Referencias
[1] OpenCV. Getting Started with Images (tutorial, doc/tutorials/introduction/display_image/display_image.markdown). OpenCV 4.11.0, commit 31b0eee. github.com/opencv/opencv
[2] Gonzalez, R. C., & Woods, R. E. (2018). Digital Image Processing (4th ed.), section 2.4 “Image Sampling and Quantization”, p. 47. Pearson.
[3] Fairchild, M. D. (2007). The HDR Photographic Survey. IS&T 15th Color Imaging Conference, pp. 233–238. doi:10.2352/CIC.2007.15.1.art00044