Advertisement
  1. Code
  2. Python

Mejora de imágenes en Python

Scroll to top
Read Time: 8 min

Spanish (Español) translation by Manuel (you can also view the original English article)

Permítanme empezar este tutorial quitando un poco de jerga teórica. Cuando hablamos de mejora de la imagen, esto significa básicamente que queremos una nueva versión de la imagen que sea más adecuada que la original.

Por ejemplo, al escanear un documento, la imagen de salida puede tener una calidad inferior a la de la imagen de entrada original. Por tanto, necesitamos una forma de mejorar la calidad de las imágenes de salida para que sean visualmente más expresivas para el espectador, y aquí es donde entra en juego la mejora de la imagen. Cuando mejoramos una imagen, lo que hacemos es afinar las características de la imagen, como su contraste y sus bordes.

Es importante tener en cuenta que la mejora de la imagen no aumenta el contenido de información de la imagen, sino que aumenta el rango dinámico de las características elegidas, aumentando finalmente la calidad de la imagen. Por lo tanto, aquí no sabemos cómo sería la imagen de salida, pero deberíamos ser capaces de decir (subjetivamente) si hubo mejoras o no, como observar más detalles en la imagen de salida, por ejemplo.

La mejora de la imagen suele utilizarse como paso previo al procesamiento de las etapas fundamentales del tratamiento digital de imágenes (es decir, la segmentación y la representación). Hay muchas técnicas para la mejora de la imagen, pero en este tutorial voy a cubrir dos técnicas: la inversa de la imagen y la transformación de la ley de potencia. Veremos cómo podemos implementarlas en Python. Así que, ¡Comencemos!

Imagen inversa

Como habrás adivinado por el título de esta sección (que también puede denominarse negación de la imagen), la inversión de la imagen pretende transformar las intensidades oscuras de la imagen de entrada en intensidades brillantes en la imagen de salida, y las intensidades brillantes de la imagen de entrada en intensidades oscuras en la imagen de salida. Es decir, las zonas oscuras se aclaran y las claras se oscurecen.

Digamos que I(i,j) se refiere al valor de intensidad del píxel situado en (i,j). Para aclararlo un poco, los valores de intensidad de la imagen en escala de grises están en el rango [0,255], y (i,j) se refiere a los valores de la fila y la columna, respectivamente. Cuando aplicamos el operador inverso de la imagen sobre una imagen en escala de grises, el valor del píxel de salida O(i,j) será:

1
O(i,j) = 255 - I(i,j)

Hoy en día, la mayoría de nuestras imágenes son imágenes en color. Esas imágenes contienen tres canales, rojo, verde y azul, denominados imágenes RGB. En este caso, a diferencia de la fórmula anterior, tenemos que restar la intensidad de cada canal a 255. Así que la imagen de salida tendrá los siguientes valores en el píxel (i,j):

1
O_R(i,j) = 255 - R(i,j)
2
O_G(i,j) = 255 - G(i,j)
3
O-B)i,j) = 255 - B(i,j)

Después de esta introducción, vamos a ver cómo podemos implementar el operador inverso de la imagen en Python. Me gustaría mencionar que, en aras de la simplicidad, voy a ejecutar el operador en una imagen en escala de grises. Pero te daré algunas ideas sobre la aplicación del operador en una imagen en color, y te dejaré el programa completo como ejercicio.

Lo primero que hay que hacer para una imagen en color es extraer el valor de intensidad de cada canal de píxel (es decir, RGB). Para ello, puedes utilizar la Python Imaging Library (PIL). Sigue adelante y descarga una imagen de ejemplo de babuino de baboon.png. El tamaño de la imagen es de 500x500. Digamos que quieres extraer los valores de intensidad del rojo, verde y azul situados en la ubicación del píxel (325, 432). Esto se puede hacer de la siguiente manera:

1
from PIL import Image
2
3
im = Image.open('baboon.png')
4
print im.getpixel((325,432))

Según la documentación, lo que hace el método getpixel() es

Devuelve el valor del píxel en una posición dada.

Después de ejecutar el script anterior, observarás que solo obtienes el siguiente resultado: ¡138! ¿Pero dónde están los valores de intensidad de los tres canales (RGB)? El problema parece estar en el mode de la imagen que se lee. Comprueba el modo ejecutando la siguiente sentencia:

1
print im.mode

Obtendrás la salida P, lo que significa que la imagen fue leída en un modo de paleta. Una cosa que puedes hacer es convertir la imagen a modo RGB antes de devolver los valores de intensidad de los diferentes canales. Para ello, puedes utilizar el método convert(), como se indica a continuación:

1
rgb_im = im.convert('RGB')

En este caso, se obtendría el siguiente valor devuelto: (180, 168, 178). Esto significa que los valores de intensidad de los canales rojo, verde y azul son 180, 168 y 178, respectivamente.

Para juntar todo lo que hemos descrito hasta ahora, el script de Python que devolvería los valores RGB de una imagen tiene el siguiente aspecto:

1
from PIL import Image
2
3
im = Image.open('baboon.png')
4
rgb_im = im.convert('RGB')
5
print rgb_im.getpixel((325,432))

Queda un punto antes de pasar al operador inverso de la imagen. El ejemplo anterior muestra cómo recuperar el valor RGB de un solo píxel, pero al realizar el operador inverso, es necesario realizarlo en todos los píxeles.

Para imprimir todos los valores de intensidad de los diferentes canales de cada píxel, puedes hacer lo siguiente:

1
from PIL import Image
2
3
im = Image.open('baboon.png')
4
rgb_im = im.convert('RGB')
5
width, height = im.size
6
7
for w in range(width):
8
    for h in range(height):
9
		print rgb_im.getpixel((w,h))

Llegados a este punto, dejaré como ejercicio que averigües cómo aplicar el operador inverso de la imagen en todos los canales de color de la imagen (es decir, RGB) de cada píxel.

Veamos un ejemplo que aplica el operador inverso de la imagen en una imagen en escala de grises. Descarga el archivo boat.tiff, que servirá como imagen de prueba en esta sección. Este es el aspecto que tiene:

Sample image of a boat for this tutorialSample image of a boat for this tutorialSample image of a boat for this tutorial

Voy a utilizar la biblioteca scipy para esta tarea. El script de Python para aplicar el operador inverso de la imagen en la imagen anterior debes tener el siguiente aspecto:

1
import scipy.misc
2
from scipy import misc
3
from scipy.misc.pilutil import Image
4
5
im = Image.open('boat.tiff')
6
im_array = scipy.misc.fromimage(im)
7
im_inverse = 255 - im_array
8
im_result = scipy.misc.toimage(im_inverse)
9
misc.imsave('result.tiff',im_result)

Lo primero que hacemos después de leer la imagen es convertirla en un ndarray para poder aplicar el operador de inversión de la imagen sobre ella. Después de aplicar el operador, simplemente convertimos el ndarray de nuevo en una imagen y guardamos esa imagen como result.tiff. La figura siguiente muestra el resultado de aplicar la inversión de la imagen a la imagen anterior (la imagen original está a la izquierda, y el resultado de aplicar el operador de inversión de la imagen está a la derecha):

Image InversedImage InversedImage Inversed

Observa que algunas características de la imagen se han hecho más claras después de aplicar el operador. Fíjate, por ejemplo, en las nubes y el faro de la imagen de la derecha.

Transformación de la ley de la potencia

Este operador, también llamado corrección gamma, es otro operador que podemos utilizar para mejorar una imagen. Veamos la ecuación del operador. En el píxel (i,j), el operador tiene el siguiente aspecto:

1
p(i,j) = kI(i,j)^gamma

I(i,j) es el valor de la intensidad en la posición de la imagen (i,j); y k y gamma son constantes positivas. No voy a entrar en detalles matemáticos aquí, pero creo que se pueden encontrar explicaciones exhaustivas de este tema en los libros de procesamiento de imágenes. Sin embargo, es importante tener en cuenta que en la mayoría de los casos, k=1, por lo que principalmente estaremos cambiando el valor de gamma. Así, la ecuación anterior puede reducirse a:

1
p(i,j) = I(i,j)^gamma

Voy a utilizar las bibliotecas OpenCV y NumPy aquí. Puedes consultar mi tutorial Introducing NumPy si necesitas aprender más sobre la librería. Nuestra imagen de prueba será de nuevo boat.tiff (adelante, descárgala).

El script de Python para realizar el operador de transformación de la ley de potencia tiene el siguiente aspecto:

1
import cv2
2
import numpy as np
3
4
im = cv2.imread('boat.tiff')
5
im = im/255.0
6
im_power_law_transformation = cv2.pow(im,0.6)
7
cv2.imshow('Original Image',im)
8
cv2.imshow('Power Law Transformation',im_power_law_transformation)
9
cv2.waitKey(0)

Observa que el valor gamma que hemos elegido es 0,6. La figura siguiente muestra la imagen original y el resultado de aplicar el operador de transformación de ley de potencia sobre esa imagen (la imagen de la izquierda muestra la imagen original, y la de la derecha el resultado tras aplicar el operador de transformación de ley de potencia).

Power Law TransformationPower Law TransformationPower Law Transformation

El resultado anterior es cuando gamma = 0,6. Veamos qué ocurre cuando aumentamos la gamma a 1,5, por ejemplo:

power law transformation with a higher gammapower law transformation with a higher gammapower law transformation with a higher gamma

Observa que a medida que aumentamos el valor de la gamma, la imagen se vuelve más oscura, y viceversa.

Cabe preguntarse para qué puede servir la transformación de la ley de la potencia. De hecho, los diferentes dispositivos utilizados para la adquisición, impresión y visualización de imágenes responden según el operador de transformación de la ley de potencia. Esto se debe a que el cerebro humano utiliza la corrección gamma para procesar una imagen. Por ejemplo, la corrección gamma se considera importante cuando queremos que una imagen se visualice correctamente (que se muestre el mejor contraste de la imagen en todas las imágenes) en un monitor de ordenador o en las pantallas de televisión.

Conclusión:

En este tutorial, has aprendido cómo mejorar imágenes usando Python. Has visto cómo resaltar características utilizando el operador inverso de la imagen, y cómo la transformación de la ley de potencia se considera un operador crucial para mostrar las imágenes correctamente en los monitores de los ordenadores y las pantallas de televisión.

Además, no dudes en ver lo que tenemos disponible para la venta y para el estudio en el Envato Market, y por favor, haz cualquier pregunta y proporciona tus valiosos comentarios utilizando el feed de abajo.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.