kshitizrimal / deepStyle
Esta es una implementación de TensorFlow de varias técnicas descritas en los artículos:
- Transferencia de estilo de imagen utilizando redes neuronales convolucionalespor Leon A. Gatys, Alexander S. Ecker, Matthias Bethge
- Transferencia de estilo artístico para vídeospor Manuel Ruder, Alexey Dosovitskiy, Thomas Brox
- Preservación del color en la transferencia de estilo artístico neuronalpor Leon A. Gatys, Matthias Bethge, Aaron Hertzmann, Eli Shechtman
Además, se presentan técnicas para la segmentación semántica y la transferencia de estilos múltiples.
El algoritmo de Estilo Neural sintetiza un pastiche separando y combinando el contenido de una imagen con el estilo de otra utilizando redes neuronales convolucionales (CNN). A continuación se muestra un ejemplo de transferencia del estilo artístico de La noche estrellada a una fotografía de un león africano:
Transferir el estilo de varias obras de arte a la misma imagen de contenido produce resultados cualitativamente convincentes:
Aquí reproducimos la Figura 3 del primer trabajo, que representa una fotografía del Neckarfront en Tübingen, Alemania, en el estilo de 5 pinturas icónicas diferentes El naufragio del minotauro, La noche estrellada, Composición VII, El grito, Desnudo sentado:
Compensación Contenido/Estilo
Se puede controlar el peso relativo del estilo y del contenido.
Aquí renderizamos con un peso de estilo creciente aplicado a Red Canna:
Múltiples imágenes de estilo
Se puede utilizar más de una imagen de estilo para mezclar múltiples estilos artísticos.
Fila superior (de izquierda a derecha): La noche estrellada + El grito, El grito + Composición VII, Desnudo sentado + Composición VII
Fila inferior (de izquierda a derecha): Desnudo sentado + La noche estrellada, Oversoul + Frescura del frío, David Bowie + Calavera
Interpolación de estilos
Cuando se utilizan varias imágenes de estilo, se puede controlar el grado de mezcla entre las imágenes.
Fila superior (de izquierda a derecha): imagen de contenido, .2 La noche estrellada + .8 El grito, .8 La noche estrellada + .2 El grito
Fila inferior (de izquierda a derecha): .2 Superalma + .8 Frescura del frío, .5 Superalma + .5 Frescura del frío, .8 Superalma + .2 Frescura del frío
Transfiere el estilo pero no el color
La combinación de colores de la imagen original puede conservarse incluyendo la bandera --original_colors
. Los colores se transfieren utilizando los espacios de color YUV, YCrCb, CIE L*a*b* o CIE L*u*v*.
Aquí reproducimos la Figura 1 y la Figura 2 del tercer artículo utilizando la transferencia de sólo luminancia:
De izquierda a derecha: imagen de contenido, imagen estilizada, imagen estilizada con los colores originales de la imagen de contenido
Texturas
El algoritmo no se limita a los estilos de pintura artística. También puede aplicarse a texturas fotográficas para crear imágenes pareidólicas.
Segmentación
El estilo puede transferirse a segmentaciones semánticas en la imagen de contenido.
Se pueden transferir múltiples estilos al primer plano y al fondo de la imagen de contenido.
De izquierda a derecha: imagen de contenido, estilo de primer plano, estilo de fondo, máscara de primer plano, máscara de fondo, imagen estilizada
Vídeo
Las animaciones se pueden renderizar aplicando el algoritmo a cada fotograma fuente. Para obtener los mejores resultados, el descenso de gradiente se inicializa con el fotograma previamente estilizado deformado al fotograma actual de acuerdo con el flujo óptico entre el par de fotogramas. Las funciones de pérdida para la consistencia temporal se utilizan para penalizar los píxeles que excluyen las regiones desoclusivas y los límites de movimiento.
Fila superior (de izquierda a derecha): fotogramas de origen, flujo óptico verdadero visualizado
Fila inferior (de izquierda a derecha): regiones desoclusivas y límites de movimiento, fotogramas estilizados
Inicialización del descenso de gradiente
La inicialización del descenso de gradiente se controla utilizando --init_img_type
para imágenes individuales y --init_frame_type
o --first_frame_type
para fotogramas de vídeo. El ruido blanco permite generar un número arbitrario de imágenes distintas. Mientras que al inicializar con una imagen fija siempre se obtiene el mismo resultado.
Aquí reproducimos la Figura 6 del primer trabajo:
Fila superior (de izquierda a derecha): Inicializada con la imagen de contenido, la imagen de estilo, ruido blanco (semilla RNG 1)
Fila inferior (de izquierda a derecha): Inicializada con ruido blanco (semillas RNG 2, 3, 4)
Representaciones de las capas
Las complejidades de las características y los tamaños de los campos receptivos aumentan hacia abajo en la jerarquía de la CNN.
Aquí reproducimos la figura 3 del artículo original:
1 x 10^-5 | 1 x 10^-4 | 1 x 10^-3 | 1 x 10^-2 | |
conv1_1 | ||||
conv2_1 | ||||
conv3_1 | ||||
conv4_1 | ||||
conv5_1 |
Filas: subconjuntos crecientes de las capas de la CNN; es decir.e. ‘conv4_1’ significa utilizar ‘conv1_1’, ‘conv2_1’, ‘conv3_1’, ‘conv4_1’.
Columnas: relación alfa/beta de la reconstrucción de contenido y estilo (ver Content / Style Tradeoff).
Configuración
Dependencias:
- tensorflow
- opencv
Dependencias opcionales (pero recomendadas):
- CUDA 7.5+
- cuDNN 5.0+
Después de instalar las dependencias:
- Descarga los pesos del modelo VGG-19 (consulta la sección «Modelos VGG-VD del proyecto Very Deep Convolutional Networks for Large-Scale Visual Recognition»). Puede encontrar más información sobre la red VGG-19 aquí.
- Después de la descarga, copie el archivo de pesos
imagenet-vgg-verydeep-19.mat
al directorio del proyecto.
Uso
Uso básico
Una sola imagen
- Copiar 1 imagen de contenido al directorio de contenido de imágenes por defecto
./image_input
- Copiar 1 o más imágenes de estilo al directorio de estilo por defecto
./styles
- Ejecutar el comando:
bash stylize_image.sh <path_to_content_image> <path_to_style_image>
Ejemplo:
bash stylize_image.sh ./image_input/lion.jpg ./styles/kandinsky.jpg
Nota: Los formatos de imagen admitidos son: .png
, .jpg
, .ppm
, .pgm
Nota: Las rutas de acceso a las imágenes no deben contener el carácter ~
para representar su directorio principal; en su lugar, debe utilizar una ruta relativa o la ruta absoluta.
Fotogramas de vídeo
- Copiar 1 vídeo de contenido al directorio de contenido de vídeo predeterminado
./video_input
- Copiar 1 o más imágenes de estilo al directorio de estilo predeterminado
./styles
- Ejecutar el comando:
bash stylize_video.sh <path_to_video> <path_to_style_image>
Ejemplo:
bash stylize_video.sh ./video_input/video.mp4 ./styles/kandinsky.jpg
Nota: Los formatos de vídeo soportados incluyen: .mp4
, .mov
, .mkv
Uso avanzado
Imagen individual o fotogramas de vídeo
- Copiar imágenes de contenido al directorio de contenido de imagen predeterminado
./image_input
o copiar fotogramas de vídeo al directorio de contenido de vídeo predeterminado./video_input
- Copiar 1 o más imágenes de estilo al directorio de estilo predeterminado
./styles
- Ejecutar el comando con argumentos específicos:
python neural_style.py <arguments>
Ejemplo (una sola imagen):
python neural_style.py --content_img golden_gate.jpg \ --style_imgs starry-night.jpg \ --max_size 1000 \ --max_iterations 100 \ --original_colors \ --device /cpu:0 \ --verbose;
Para utilizar varias imágenes de estilo, pase una lista separada por espacios de los nombres de las imágenes y de los pesos de las mismas así:
--style_imgs starry_night.jpg the_scream.jpg --style_imgs_weights 0.5 0.5
Ejemplo (fotogramas de vídeo):
python neural_style.py --video \ --video_input_dir ./video_input/my_video_frames \ --style_imgs starry-night.jpg \ --content_weight 5 \ --style_weight 1000 \ --temporal_weight 1000 \ --start_frame 1 \ --end_frame 50 \ --max_size 1024 \ --first_frame_iterations 3000 \ --verbose;
Nota: Al utilizar --init_frame_type prev_warp
debe haber calculado previamente el flujo óptico hacia delante y hacia atrás entre los fotogramas. Ver ./video_input/make-opt-flow.sh
y ./video_input/run-deepflow.sh
Argumentos
-
--content_img
: Nombre de archivo de la imagen de contenido. Ejemplo:lion.jpg
-
--content_img_dir
: Ruta de directorio relativa o absoluta a la imagen de contenido. Por defecto:./image_input
-
--style_imgs
: Nombres de archivo de las imágenes de estilo. Para utilizar varias imágenes de estilo, pase una lista separada por espacios. Ejemplo:--style_imgs starry-night.jpg
-
--style_imgs_weights
: Los pesos de mezcla para cada imagen de estilo. Por defecto:1.0
(asume sólo 1 imagen de estilo) -
--style_imgs_dir
: Ruta de directorio relativa o absoluta a las imágenes de estilo. Por defecto:./styles
-
--init_img_type
: Imagen utilizada para inicializar la red. Opciones:content
,random
,style
. Por defecto:content
-
--max_size
: Ancho o alto máximo de las imágenes de entrada. Por defecto:512
-
--content_weight
: Peso para la función de pérdida de contenido. Por defecto:5e0
-
--style_weight
: Peso para la función de pérdida de estilo. Por defecto:1e4
-
--tv_weight
: Peso para la función de pérdida variacional total. Por defecto:1e-3
-
--temporal_weight
: Peso para la función de pérdida temporal. Por defecto:2e2
-
--content_layers
: Nombres de capas VGG-19 separados por el espacio que se utilizan para la imagen de contenido. Por defecto:conv4_2
-
--style_layers
: Nombres de capas VGG-19 separados por espacios utilizados para la imagen de estilo. Por defecto:relu1_1 relu2_1 relu3_1 relu4_1 relu5_1
-
--content_layer_weights
: Pesos separados por espacios de cada capa de contenido a la pérdida de contenido. Por defecto:1.0
-
--style_layer_weights
: Pesos separados por espacios de cada capa de estilo a la pérdida. Por defecto:0.2 0.2 0.2 0.2 0.2
-
--original_colors
: Bandera booleana que indica si se transfiere el estilo pero no los colores. -
--color_convert_type
: Espacios de color (YUV, YCrCb, CIE L*u*v*, CIE L*a*b*) para la conversión de coincidencia de luminancia con los colores originales. Opciones:yuv
,ycrcb
,luv
,lab
. Por defecto:yuv
-
--style_mask
: Bandera booleana que indica si el estilo se transfiere a las regiones enmascaradas. -
--style_mask_imgs
: Nombres de archivo de las imágenes de máscara de estilo (ejemplo:face_mask.png
). Para utilizar varias imágenes de máscara de estilo, pase una lista separada por espacios. Ejemplo:--style_mask_imgs face_mask.png face_mask_inv.png
-
--noise_ratio
: Valor de interpolación entre la imagen de contenido y la imagen de ruido si la red se inicializa conrandom
. Por defecto:1.0
-
--seed
: Semilla para el generador de números aleatorios. Por defecto:0
-
--model_weights
: Pesos y sesgos de la red VGG-19. Descargar aquí. Por defecto:imagenet-vgg-verydeep-19.mat
-
--pooling_type
: Tipo de pooling en la red neuronal convolucional. Opciones:avg
,max
. Por defecto:avg
-
--device
: Dispositivo GPU o CPU. El modo GPU es muy recomendable pero requiere NVIDIA CUDA. Opciones:/gpu:0
/cpu:0
. Por defecto:/gpu:0
-
--img_output_dir
: Directorio para escribir la salida. Por defecto:./image_output
-
--img_name
: Nombre del archivo de la imagen de salida. Por defecto:result
-
--verbose
: Bandera booleana que indica si las declaraciones deben imprimirse en la consola.
Argumentos de optimización
-
--optimizer
: Optimizador de minimización de pérdidas. L-BFGS da mejores resultados. Adam utiliza menos memoria. Opciones:lbfgs
,adam
. Por defecto:lbfgs
-
--learning_rate
: Parámetro de tasa de aprendizaje para el optimizador Adam. Por defecto:1e0
-
--max_iterations
: Número máximo de iteraciones para el optimizador Adam o L-BFGS. Por defecto:1000
-
--print_iterations
: Número de iteraciones entre sentencias de impresión del optimizador. Por defecto:50
-
--content_loss_function
: Diferentes constantes K en la función de pérdida de contenido. Opciones:1
,2
,3
. Por defecto:1
Argumentos del fotograma de vídeo
-
--video
: Bandera booleana que indica si el usuario está creando un vídeo. -
--start_frame
: Número del primer fotograma. Por defecto:1
-
--end_frame
: Número del último fotograma. Por defecto:1
-
--first_frame_type
: Imagen utilizada para inicializar la red durante el renderizado del primer fotograma. Opciones:content
,random
,style
. Por defecto:random
-
--init_frame_type
: Imagen utilizada para inicializar la red durante el renderizado de cada cuadro después del primero. Opciones:prev_warped
,prev
,content
,random
,style
. Por defecto:prev_warped
-
--video_input_dir
: Ruta de directorio relativa o absoluta a los marcos de entrada. Por defecto:./video_input
-
--video_output_dir
: Ruta de directorio relativa o absoluta para escribir los fotogramas de salida. Por defecto:./video_output
-
--content_frame_frmt
: Cadena de formato de los fotogramas de entrada. Por defecto:frame_{}.png
-
--backward_optical_flow_frmt
: Cadena de formato de los archivos de flujo óptico hacia atrás. Por defecto:backward_{}_{}.flo
-
--forward_optical_flow_frmt
: Cadena de formato de los archivos de flujo óptico hacia adelante. Por defecto:forward_{}_{}.flo
-
--content_weights_frmt
: Cadena de formato de los archivos de consistencia de flujo óptico. Por defecto:reliable_{}_{}.txt
-
--prev_frame_indices
: Fotogramas anteriores a considerar para la consistencia temporal a largo plazo. Por defecto:1
-
--first_frame_iterations
: Número máximo de iteraciones del optimizador de la primera trama. Por defecto:2000
-
--frame_iterations
: Número máximo de iteraciones del optimizador para cada fotograma después del primer fotograma. Por defecto:800
Preguntas y erratas
Envíe sus preguntas o problemas:
Memoria
Por defecto, neural-style-tf
utiliza el backend de la GPU NVIDIA cuDNN para las convoluciones y L-BFGS para la optimización.Estos producen resultados mejores y más rápidos, pero pueden consumir mucha memoria. Puede reducir el uso de memoria con lo siguiente:
- Utilizar Adam: Añada la bandera
--optimizer adam
para utilizar Adam en lugar de L-BFGS. Esto debería reducir significativamente el uso de la memoria, pero requerirá el ajuste de otros parámetros para obtener buenos resultados; en particular, debería experimentar con diferentes valores de--learning_rate
,--content_weight
,--style_weight
- Reducir el tamaño de la imagen: Puede reducir el tamaño de la imagen generada con el argumento
--max_size
.
Detalles de la implementación
Todas las imágenes se renderizaron en una máquina con:
- CPU: Intel Core i7-6800K @ 3.40GHz × 12
- GPU: NVIDIA GeForce GTX 1080/PCIe/SSE2
- SO: Linux Ubuntu 16.04.1 LTS 64 bits
- CUDA: 8.0
- python: 2.7.12
- tensorflow: 0.10.0rc
- opencv: 2.4.9.1
Agradecimientos
La implementación se basa en los proyectos:
- Implementación de Torch (Lua) ‘neural-style’ por jcjohnson
- Implementación de Torch (Lua) ‘artistic-videos’ por manuelruder
Los fotogramas de vídeo fuente se obtuvieron de:
- MPI Sintel Flow Dataset
Las imágenes artísticas fueron creadas por los artistas modernos:
- Alex Grey
- Minjae Lee
- Leonid Afremov
- Françoise Nielly
- James Jean
- Ben Giles
- Callie Fink
- H.R. Giger
- Voka
Las imágenes artísticas fueron creadas por los populares artistas históricos:
- Vincent Van Gogh
- Wassily Kandinsky
- Georgia O’Keeffe
- Jean-Michel Basquiat
- Édouard Manet
- Pablo Picasso
- Joseph Mallord William Turner
- Frida Kahlo
Los scripts de shell de Bash para las pruebas fueron creados por mi hermano Sheldon Smith.
Citación
Si encuentra este código útil para su investigación, por favor cite:
@misc{Smith2016, author = {Smith, Cameron}, title = {neural-style-tf}, year = {2016}, publisher = {GitHub}, journal = {GitHub repository}, howpublished = {\url{https://github.com/cysmith/neural-style-tf}},}