Está en la página 1de 5

RESUMEN 6:Caricaturizar una imagen

Saul Rivera Lopéz, Horlando Vargas Vargas


12 de Junio 2020

1. Caricaturizar una imagen


En OpenCV podemos convertir una imagen en un boceto o una imagen de dibujos animados de color. Estas transfor-
maciones de la hacia la imagen se pueden lograr mediante el siguiente código:
import cv2 import
numpy as np

def print howto():


print(”
Change cartoonizing mode of image:
1. Cartoonize without Color - press ’s’
2. Cartoonize with Color - press ’c’
”)

def cartoonize image(img, ksize=5, sketch mode=False):


num repetitions, sigma color, sigma space, ds factor = 10, 5, 7, 4
# Convert image to grayscale
img gray = cv2.cvtColor(img, cv2.COLOR BGR2GRAY)

# Apply median filter to the grayscale image


img gray = cv2.medianBlur(img gray, 7)

# Detect edges in the image and threshold it


edges =cv2.Laplacian(img gray, cv2.CV 8U, ksize=ksize)
ret, mask =cv2.threshold(edges, 100, 255, cv2.THRESHB IN ARY IN V )

# ’mask’ is the sketch of the image if sketch mode:


return cv2.cvtColor(mask, cv2.COLOR GRAY2BGR)

# Resize the image to a smaller size for faster computation img small = cv2.resize(img, None, fx=1.0/ds factor,
fy=1.0/ds factor, interpolation=cv2.INTER AREA)

# Apply bilateral filter the image multiple times


for i in range(num repetitions): img small = cv2.bilateralFilter(img small, ksize, sigma color, sigmas pace)

img output = cv2.resize(img small, None, fx=ds factor, fy=ds factor,


interpolation=cv2.INTER LINEAR)

dst = np.zeros(img gray.shape)

# Add the thick boundary lines to the image using ’AND’ operator dst = cv2.bitwise and(img output, img output,
mask=mask) return dst
if name ==’ main ’:
print howto()
cap = cv2.VideoCapture(0)

cur mode = None


while True:

1
ret, frame = cap.read()
frame = cv2.resize(frame, None, fx=0.5, fy=0.5,
interpolation=cv2.INTER AREA)

c = cv2.waitKey(1)
if c == 27:
break

if c != -1 and c != 255 and c != cur mode:


cur mode = c

if cur mode == ord(’s’):


cv2.imshow(’Caricaturizar sin color’, cartoonize image(frame, ksize=5,
sketch mode=True))
elif cur mode == ord(’c’):
cv2.imshow(’Caricaturizar con color’, cartoonize image(frame, ksize=5,
sketch mode=False))
else: cv2.imshow(’imagen’, frame)

cap.release()
cv2.destroyAllWindows()

Resultado:

a)

b) c)

Figura 1: Caricaturiza de unasecuencia de video a) video original, b) caricarura sin color, c) caricatura con color.

2
2. Deconstruyendo el código
Si pulsa S en el programa anterior, la secuencia de vı́deo cambiará al modo de boceto y verá su contorno similar al
lápiz. Si pulsa C, verá la versión dibujante en color de la secuencia de entrada. Si pulsa cualquier otra tecla, volverá al
modo normal.
En la función cartoonize image primero se convierte la imagen en una imagen en escala de grises y la ejecutamos a través
de un filtro mediana. Los filtros mediana son muy buenos para eliminar el ruido de sal y pimienta. Este es el tipo de
ruido donde se ven pı́xeles aislados en blanco o negro en la imagen. Es común en webcams y cámaras móviles, por lo que
tenemos que filtrarlo antes de continuar. Para dar un ejemplo, mire las siguientes imágenes:

Como se ve en la imagen de entrada, hay una gran cantidad de pı́xeles blancos aislados. Lo que ocasiona una mala calidad
de la imagen por lo que se tiene que aplicar un tipo de filtro que elimine los puntos. Aquı́ es donde el filtro mediana es útil.
Simplemente miramos el vecindario NxN alrededor de cada pı́xel y elegimos el valor medio de esos números. Dado que
los pı́xeles aislados, en este caso, tienen valores altos, tomar el valor medio eliminará estos valores y también suavizará la
imagen. Como se puede ver en la imagen de salida, el filtro mediana se deshizo de todos esos pı́xeles aislados y la imagen
se ve limpia. A continuación, se muestra el código para esto:

import cv2 import


numpy as np
img = cv2.imread(’images/input.jpg’)
output = cv2.medianBlur(img, ksize=7)
cv2.imshow(’Input’, img)
cv2.imshow(’Median filter’, output)
cv2.waitKey()

Resultado:

a) b)

Figura 2: a) video original, b) eliminacion de ruido mediante filtro mediano.

3
El código es bastante sencillo. Sólo usamos la función medianBlur para aplicar el filtro mediana a la imagen de entrada.
El segundo argumento de esta función especı́fica el tamaño del kernel que estamos utilizando. El tamaño del kernel está
relacionado con el tamaño de vecindad que debemos tener en cuenta. Puede jugar con este parámetro y ver cómo afecta
a la salida; recuerde, los valores posibles son sólo números impares: 1, 3, 5, 7, y ası́ sucesivamente.
Volviendo a cartoonize image, procedemos a detectar los bordes de la imagen en escala de grises. Necesitamos saber dónde
están los bordes para poder crear el efecto de lı́nea de lápiz. Una vez que detectamos los bordes, los umbralamos para que
las cosas se vuelvan blancas y negras.
En el siguiente paso, comprobamos si el modo de boceto está activado. Si es ası́, simplemente lo convertimos en una imagen
en color y la devolvemos. Para hacer las lı́neas más gruesas se reemplaza el bloque de código if por el siguiente fragmento
de código:
if sketch mode: img sketch = cv2.cvtColor(mask, cv2.COLOR GRAY2BGR)
kernel = np.ones((3,3), np.uint8)
img eroded = cv2.erode(img sketch, kernel, iterations=1)
return cv2.medianBlur(img eroded, ksize=5)

El resultado del código anterior se verá como la siguiente imagen:

En el siguiente paso, utilizamos el filtrado bilateral para suavizar la imagen. El filtrado bilateral es un concepto interesan-
te, y su rendimiento es mucho mejor que un filtro gaussiano. Lo bueno del filtrado bilateral es que conserva los bordes,
mientras que el filtro gaussiano suaviza todo por igual. Para comparar y contrastar, echemos un vistazo a la siguiente
imagen de entrada:

Aplicando el filtro gaussiano a la imagen anterior obtenemos como resultado:


Si se aplica el filtro bilateral a la imagen obtenemos como resultado la siguiente imagen:
Como se puede ver, la calidad es mejor si usamos el filtro bilateral. La imagen es suave y los bordes son nı́tidos. Esto se
logra utilizando el siguiente código:
import cv2 import

4
numpy as np img = cv2.imread(’images/input.jpg’)
img gaussian = cv2.GaussianBlur(img, (13,13), 0) Gaussian Kernel Size 13x13
img bilateral = cv2.bilateralFilter(img, 13, 70, 50)
cv2.imshow(’Input’, img)
cv2.imshow(’Gaussian filter’, img gaussian)
cv2.imshow(’Bilateral filter’, img bilateral)
cv2.waitKey()

Observando las imágenes de salida, puede ver que los bordes de la imagen filtrada con el filtro gaussiano se ven borrosos.
Por lo general, sólo queremos suavizar las áreas ásperas de la imagen y mantener los bordes intactos. Aquı́ es donde el filtro
bilateral es útil. El filtro gaussiano solo mira la vecindad inmediata y promedia los valores de pı́xel utilizando un núcleo
gaussiano, aplicado por el método GaussianBlur. El filtro bilateral lleva este concepto al siguiente nivel promediando solo
los pı́xeles que son similares entre sı́ en intensidad. Si nos fijamos en la siguiente función:

img small = cv2.bilateralFilter(img small, size, sigma color, sigma space)

Los dos últimos argumentos especifican el color y la vecindad del espacio. Esta es la razón por la que los bordes se
ven nı́tidos en la salida del filtro bilateral. Ejecutamos este filtro varias veces en la imagen para suavizarla, para que
parezca una caricatura. A continuación, superponemos la máscara de lápiz en la parte superior de esta imagen en color
para crear un efecto de dibujos animados.

También podría gustarte