Foto-blog de Antonio Castro

Retoque fotográfico con Gimp, fotos copyleyft, licencia Creative Commons (CC-BY), fotos gratis para uso comercial con reconocimiento.

Macrofotografía abeja

Categoría: Script Página 1 de 3

Como hacer scrolling para créditos finales. (Tutorial avanzado)

Imagen para el scroll.

Imagen para el scroll.

La mayoría de mis tutoriales son para usuarios noveles, pero de vez en cuando me gusta incluir alguna cosilla con algo más de chicha. Este es el caso.

Trataré de explicar como se hizo el final de uno de mis vídeos.

Ignoro como harán los demás las cosas, porque en el tema de edición y producción de vídeo hay auténticas maravillas de software, pero yo me limito a usar Software Libre.

Muchas veces me apaño usando scripts propios. Eso me da mucha flexibilidad y me permite ir construyendo poco a poco una librería de recursos de software que iré compartiendo con vosotros.

Esta vez no nos vamos a conformar con añadir un scrolling. Vamos a construir un final en tres partes: Un fundido previo, un efecto 3D y un scrolling con los créditos.

1) Preparación previa al scrolling:

Mi técnica de scrolling consiste en meter todo lo que necesito para el scrolling en una imagen alargada verticalmente.

La imagen debe tener el mismo ancho que el ancho de la imagen de la película. En nuestro caso usamos HD 720p. Es decir  1280×720. Así que el ancho será 1280 pixels.

Yo he usado Gimp para eso.

Quedará como la imagen de la izquierda.

2) Fundido previo:

Tomaremos una imagen de 1280×720 recortando la parte superior. Yo usé gThumb para eso.

Guardamos esta imagen con el nombre de ‘Fin04.jpg’. Sacamos una copia que llamaremos  ‘FinAux.jpg’ y la editamos suprimendo todo excepto el título.

También tomamos la última imagen de la película y la copiamos con el nombre de ‘Fin01.jpg’. La abrimos con Gimp y cargamos ‘FinAux.jpg’. Superponemos ambas inmágenes. (Yo lo hice pasando el negro a a blanco, conviertiéndo el blanco en transparente con la opción clolores -> color a alfa y luego desde editar copie y pegué sobre ‘Fin01.jpg’ y salve con el nombre de ‘Fin02.jpg’.

La imágenes a las que acabo de referirme son estas:

Fin01

Fin01.jpg

Fin02

Fin02.jpg

Fin04

Fin04.jpg

FinAux

FinAux.jpg

(No existe ninguna imagen ‘Fin03.jpg’ porque decidí  no incluirla en el fundido y la renombré como ‘FinAux.jpg’)

Ahora para hacer una transición fundiendo secuencialmente estas imágenes ejecuto un script muy sencillito que hace uso de la opción ‘-morph‘ de la utilidad ‘convert’ de ‘ImageMagick’ de la que hemos hablado en otras ocasiones.

Nos genera un directorio con los fotogramas. Estos pueden compilarse usando la utilidad ‘ffmpeg’. (Yo uso un script propio ‘dirs2vid.py’ del que ya hablaré en otra ocasión y que es muy similar a otro que ya mencioné como ‘dir2avi.py‘ descrito aquí.)

#!/bin/bash
rm -fr morph 2> /dev/null
rm morph.avi 2> /dev/null
mkdir morph
convert -morph 25 Fin0?.jpg morph/FIN%04d.JPG
dirs2vid.py -exif -out=FIN.avi morph

Con esto ya tenemos el fundido.

3) Preparar un bonito efecto de explosión invertida en 3D para nuestro logo:

Esto obviamente es una filigrana opcional, pero dar al logo una presentación variada es una idea que permite aumentar la atención sobre él y con esta costumbre iremos reforzando la imagen de la marca de nuestro sitio. Uno de los sitios que practica esta idea es Google a pesar de que ya tiene una imagen de marca potente.

Para ello recurrimos al trazador de rayos PovRay del cual ya hemos tratado ampliamente en otros artículos. Para no extendernos me limito a copiar el fuente.

[…]

Vemos cerca del final dentro de la cláusula object un #include «Explode.inc» Que llama al fichero que realiza la explosión de objetos.

Este include se proporciona como una utilidad para PovRay. Su autor es Chris Colefax. ‘OBJECT EXPLODER INCLUDE FILE for Persistence of Vision 3.x’

Usando nuestro lanzador PovRay usaríamos el comando:

pov.py Logo3_ j 11 11 1 500 0 4

Esto generará 500 fotogramas (‘Logo3_001.jpg’ … ‘Logo3_500.jpg’) haciendo variar el valor de clock entre 0 y 4.

Dado que en el fuente Povray hemos omitido el fondo, este aparecerá en negro.

Podemos obtener fotogramas en png con el fondo transparente reconvirtiendo esos fichros con mogrify de ImageMagick.

mogrify -format png -transparent black Logo3_???.jpg

De esa forma ya queda preparado para poder superponer esos fotogramas con fondo transparente sobre los fotogramas de nuestro scrolling. Para ello hacemos un script que genere el scrolling del texto y que superonga los fotogramas 3D que hemos generado en los fotogramas finales de nuestro scrolling.

#!/usr/bin/python
# -*- coding: latin1 -*-
import os, sys
################
def comando(comm):
print comm
os.system(comm)
######## MAIN ##########
comando ("mkdir fot1 fot2")
Top=1501
Ini3D=650
for n in range(1,Top):
comando("convert scroll.jpg -crop 1280x720+0+%d fot1/%04d.jpg" % (n, n))
m=0
# Añadir logo 3D
for n in range(1, Top):
if (n

Para finalizar juntamos el primer fundido con el vídeo de scroll que acabamos de generar ahora y ya está completo.
Puedes ver a continuación uno de los fotogramas generados.

Un fotograma del final del scrolling.

Un fotograma del final del scrolling.

El resultado completo puede verse en los créditos, al final del vídeo, de  LasVentas TML Noct 2011.

dirs2vid.py (Utilidad para pasar varios directorios a vídeo)

Esta utilidad ‘dirs2vid.py‘ es un nuevo script escrito en lenguaje Python y con licencia libre GPL, basada en una utilidad que propusimos hace ya un tiempo dir2avi.py‘.

Mejoras:
Las mejoras son significativas y justifican el cambio de nombre. Para empezar el anterior script tomaba un directorio y lo convertía en un avi. ‘dirs2vi.py’ puede tomar varios directorios de fotogramas, con lo cual resulta muy útil para hacer un montaje final. Además, el formato por defecto es avi, pero puede ser variado a cualquier otro formato compatible con ffmpeg que continúa siendo la base del nuevo script.

Entre otras novedades podemos pasar un fichero de audio para que lo use como audio del vídeo. Nuevamente resulta muy útil para montajes finales de vídeo partiendo de directorios de fotogramas.

Se ha añadido una opción –exif para evitar que cierto tipo de imágenes que vienen con información exif conflictiva para ffmpeg causen distorsiones del color en la imagen. En definitiva hace el proceso más lento, pero más seguro.

Está pensado para su uso en Linux, y resulta especialmente útil para los aficionados a realizar Timelapses.

Portabilidad:
Dado que existe un intérprete de Python para Windows, y un ffmpeg para Windows, su adaptación no debería ser complicada. (Por ejemplo: Algunos comandos Linux contenidos en el script, deberían ser reconvertidos a sus equivalentes en Windows).

Código fuente de ‘dirs2vid.py’
#!/usr/bin/python
# -*- coding: latin1 -*-
"""
Sinopsis: 'dirs2vid.py': Procesa las imagenes contenidas en los directorios indicados y crea un vídeo usando 'ffmpeg.
Autor**: Antonio Castro Snurmacher (acastro0841@gmail.com) (http://www.ciberdroide.com)
Licencia: GPL.
Version: version 1.0 (marzo-2011)
"""

import sys, os, Image
import string

##################
def comando(comm):
print comm
os.system(comm)

#######################################
def GetOpcion(cadopcion):
'''
Capturar y procesar las opciones.
'''
opc_val= string.split(cadopcion, '=')
if opc_val[0] not in [ '--help', '-help', '-h', '-exif', '-vcodec', '-fimg', '-size', '-audio', '-out' ]:
Uso("Opción '%s' desconocida" % opc_val[0])
if len(opc_val)==1:
return opc_val[0], ''
else:
opc_val[1]=opc_val[1].strip()
if opc_val[0]=='-size': # Expandir uso abreviado
if opc_val[1]=='720p':
opc_val[1]='1280x720'
if opc_val[1]=='1080p':
opc_val[1]='1920x1080'
return opc_val[0], opc_val[1]

############
def Uso(cad):
print "Error: %s" % cad
Help()

################################################################
def GetFilesDir(dir, ExtImg):
if not os.path.isdir(dir):
Uso("'%s' no es un directorio" % dir)
if (dir[len(dir)-1]=='/'):
dir=dir[:-1]
finamelist=[]
ListaFicheros=os.listdir(dir)

n=0
for fi in ListaFicheros:
finame, ext= os.path.splitext(fi)
if ext in ExtImg:
finamelist.append(finame)
n=n+1
if n==0:
Uso("El directorio '%s' no contiene ficheros '%s'" % (dir, ExtImg))
finamelist.sort()
return finamelist, ext

####################################################
def CompilaDir(n, finamelist, dir, ext, DirDest, Opc_Exif):
# Las listas se pasan por referencia (no es variable local)
for fi in finamelist:
FiNum="img_%06d%s" % ( n, ext.lower())
if Opc_Exif:
img=Image.open("%s/%s%s" % (dir, fi, ext))
(x,y)=img.size
img.resize(img.size) # Redimensionamos al mismo tamaño. (truco para suprimir toda la info exif)
img.save("%s/%s" % (DirDest, FiNum))
print "%s/%s" % (DirDest, FiNum)

else:
comando ("cd %s ; ln -s ../%s/%s%s %s" % (DirDest, dir, fi, ext, FiNum))
n=n+1
return n

####################
def Timestamp():
"Un Timestamp de 4 digitos se considera suficiente."
import time
return int(time.time()) % 10000

####################
def Help():

print """
USO:
dirs2vid.py [ Opciones... ] Dir...

OPCIONES:
-help # Muestra esta ayuda y finaliza.
-exif # Suprime la información exif. Necesario para evitar cierto bub y forzar el correcto procesado
de los canales RGB de algunas imágenes que contienen información exif erronea.
-fimg= # Para indicar el formato de la imagen que por defecto se considera '.jpg' o '.JPG'.
-size= # Para indicar la resolución del video de salida que por defecto conserva la resolución de las
imagenes originales.
-audio= # Para indicar el fichero que contiene el audio.
-vcodec= # Para especificar un codec de vídeo concreto a ffmpeg.
-out= # Especificar un nombre de fichero de video que por defecto sería del tipo 'd2v9999.avi'
"""
raw_input('Pulse la tecla [Intro] para continuar...')
print """
SINOPSIS:
'dirs2vid.py': Procesa las imágenes contenidas en los directorios indicados (dir...) y crea un vídeo usando 'ffmpeg.

REQUERIMIENTOS:
Dentro de cada directorio las imágenes serán procesadas siguiendo el orden alfabético del nombre del fichero.
Todas las imágenes de todos los directorios deben tener la misma resolución.

EJEMPLOS:
# Obtener un video 'avi' a partir del directorio 'dir_fotogramas' donde los ficheros son de la forma '*.jpg' o '*.JPG'
# (coincide con con los valores de las opciones por defecto)
dirs2vid.py dir_fotogramas

# Obtener un video con nombre 'video.avi' a partir del directorio 'dir_fotogramas' donde los ficheros son de la forma
# '*.jpg' o '*.JPG' e incluir el audido contenido en 'audio.mp3'
dirs2vid.py -out=video.avi -audio=audio.mp3 dir_fotogramas

# Obtener un video 'avi' de 1280x720 a partir del directorio 'dir_fotogramas' donde los ficheros son de la forma '*.jpg' o
# '*.JPG' suprimendo previamente la informacion exif de las imágenes. (Proteccion de ffmpeg frente a BUGS EXIF en JPG)
dirs2vid.py -exif -size=1280x720 dir_fotogramas

# Obtener un video 'mp4' con vcodec='libxvid' a partir del directorio dir_fotogramas donde los ficheros son de la forma '*.PNG' '
dirs2vid.py -fimg=PNG -fvidOut=mp4 -vcodec=libxvid dir_fotogramas

Para más detalle consulte el artículo de referencia en http://www.ciberdroide.com/fotos
Este programa se ofrece bajo licencia GPL. Si llegara a serle de alguna utilidad y tiene oportunidad, incluya desde su web una
referencia (link) a la web de ciberdroide. Si desea comunicar con el autor, localice el artículo de referencia y ponga allí un
comentario. Con mucho gusto resolveré las dudas que tenga.

Antonio Castro.
"""
sys.exit()

#######################################################
def main():
'''
Vease Help().
'''
import sys, os, Image

opc={}
while (len(sys.argv)>1 and sys.argv[1][0]=='-'):
opcion, valor=GetOpcion(sys.argv[1])
print opcion, valor
opc[opcion]=valor
del sys.argv[1]
for h in [ '--help', '-help', '-h']:
if h in opc.keys():
Help()
Opc_Exif = '-exif' in opc.keys()
if '-vcodec' in opc.keys():
Opc_Vcodec= " -vcodec %s " % opc['-vcodec']
else:
Opc_Vcodec='' # default
if '-fimg' in opc.keys():
ExtImg=[ '.'+ opc['-fimg'] ]
else:
ExtImg=['.jpg', '.JPG'] # default
if '-size' in opc.keys():
Opc_Size=" -s %s " % opc['-size']
else:
Opc_Size=''
if '-audio' in opc.keys():
Audio=" -i %s -acodec copy " % opc['-audio']
else:
Audio=' -an '
# print opc
# print "exif=%s, vcodec=%s, fvidOut=%s, fimg=%s," % (Opc_Exit, Opc_Vcode, ExtVidOut, ExtImg)
if (len(sys.argv)<2): Uso("Debe indicar como mínimo un directorio origen.") directorios=sys.argv del directorios[0] if '-out' in opc.keys(): Out=opc['-out'] else: Out="d2v%d.avi" % Timestamp() n=1 DirDest="tmp_fotogramas" comando("rm -r %s; mkdir %s" % (DirDest, DirDest)) for dir in directorios: if dir[-1:]=='/': # Si termina en '/' eliminarlo dir=dir[:-1] finamelist, ext =GetFilesDir(dir, ExtImg) n=CompilaDir(n, finamelist, dir, ext, DirDest, Opc_Exif) comando("ffmpeg %s -f image2 -i %s/img_%%06d%s %s -sameq %s -y %s" % (Audio, DirDest, ext.lower(), Opc_Vcodec, Opc_Size, Out ) ) ############################################################# if __name__ == "__main__": main()

Pack dflck v1.0 para suprimir los parpadeos en vídeos de time-lapse.

En este artículo presento la culminación de un pequeño proyecto que me ha tenido ocupado algunas semanas. Se trata de implementar un supresor de efecto parpadeo para vídeos time-lapses (deflicker). Que yo sepa no existe ningún deflicker de software libre para Linux.

El timelapsing se presta a un montón de trabajo de postprocesado y si bien hay mucho software para eso, los scrips te abren siempre la puerta a hacer un tratamiento particular y muy original. Un deflicker no es algo demasiado especial, pero si lo suficientemente complejo como para demostrar la potencia de un buen script. En el vídeo se muestra la efectividad de este script.

Test para validar la eficacia de deflick.py from Antonio Castro on Vimeo.


¿Tiene algo de especial este deflicker?

En primer lugar, es software libre.  En segundo lugar, la medición de la luz y el resto del trabajo está totalmente automatizado en otro tipo de deflickers, pero un programa que considere todo el fotograma en su conjunto además de ineficiente puede actuar de forma diferente a la pretendida.

Mi deflicker permite delimitar el recuadro donde el script mirará para actuar en la corrección de los fotogramas, lo cual es novedoso y bastante útil.

La primera versión es un programa en lenguaje python ‘deflick.py’ al cual hay que pasarle un directorio que ha de contener los fotogramas del timelapse, en segundo lugar un número que llamaremos NF, que determina el número de fotogramas previos y posteriores que serán promediados para obtener el valor de iluminación del fotograma a tratar, y después pasaremos unas coordenadas x1, y1, x2, y2 de un recuadro donde x1,y1 corresponden a la esquina superior izquierda y las coordenadas x2, y2 corresponden a la esquina opuesta de ese recuadro. La función de este será la de establecer una zona de referencia para que el programa la tome como zona estable. En ella se supone que los cambios bruscos de iluminación corresponderán a fenómenos globales no deseados. Es decir, serán tipo parpadeo. Para ello se tomará preferentemente una zona celeste. Si las nubes son de lenta evolución no serán un problema, pero objetos rápidos moviéndose en esa zona deben evitarse.

Un ejemplo de uso de este script sería el siguiente:

Desde la línea de comandos donde tengamos situado el directorio de los fotogramas tecleamos.

deflick.py 13 pru2 0 0 2784 400

Significado:

  • NF=13
  • Directo de los fotogramas= pru2
  • coordenadas x1,y1, x2,y2 = 0 0 2784 400

El valor NF no afectará apenas a la velocidad del procesado. Un valor NF adecuado para muchos casos puede estar comprendido entre 10 y 20. El resultado de este comando sería un nuevo directorio con fotogramas ‘pru2_dflck’ en los cuales se ha eliminado el parpadeo.

Validación de los resultados:

La gráfica en negro corresponde al resultado de aplicar deflick.py

La gráfica en negro corresponde al resultado de aplicar deflick.py

Se ha desarrollado un segundo programa ‘test_deflick.py’ que permite comparar gráficamente el resultado obtenido con el original. Para ello genera una gráfica mediante un programa externo ‘gnuplot’ y también genera un vídeo con dos mitades construido con ayuda de ‘convert’ de ‘ImageMagick’ en las cuales se puede apreciar la diferencia entre el original y el resultado de la supresión del parpadeo. El vídeo de cabecera se obtuvo con este script, y se corresponde con la gráfica anterior.

Ejemplos para elección de un recuadro de referencia:

En una escena donde hay muchos objetos móviles en primer plano tomaremos un recuadro celeste. En un cielo nocturno con aparato eléctrico tomaremos un recuadro del primer plano para estabilizar la iluminación del primer plano. En Gimp y en otros editores gráficos, las coordenadas de las esquinas del recuadro de referencia pueden averiguarse posicionando el puntero del ratón en las posiciones deseadas de la imagen.

¿Cómo funciona?

El programa inicialmente mide la luz en cada recuadro de referencia (x1, y1, x2, y2) de cada fotograma, tal y como lo haría un fotómetro y almacena este valor de luz para cada fotograma. Se puede tomar como recuadro de referencia la imagen global, pero un recuadro que sea suficientemente representativo será más eficiente.

Después de almacenar el valor promedio de iluminación de cada fotograma medido en el recuadro, se producirá una segunda pasada que irá comparando el valor de cada fotograma con el promedio de sus NF fotogramas vecinos anteriores y los NF posteriores. De esa comparación se calcula el factor de multiplicación aplicable a la totalidad de los pixels del fotograma que estamos tratando para que coincida con ese valor promedio de sus fotogramas vecinos.

Hay que tener en cuenta que el parpadeo es un fenómeno que afecta a todos los pixels del fotograma por igual ya que deriva de diferencias en la exposición con la que se obtuvo cada foto. Véase artículo sobre el parpadeo: ¿Por qué aparece el parpadeo (flicker) en los time-lapses?

El resultado como ya dijimos es un nuevo directorio con fotogramas corregidos. Para pasar a vídeo los fotogramas de un directorio ya propusimos un sencillo script ‘dir2avi.py’ que puede verse afectado por un BUG que ya comentamos en su momento: Bug repartido entre ImageMagick, ffmpeg, mencoder, y recordmydesktop.

Por eso se incorpora ahora un nuevo script con más opciones que el anterior y que llamamamos ‘dir2vid.py’. Este permite anticipar el efecto del bug y trabajar con más formatos de vídeo además del avi, incorporar un audio mp3, usar determinados codecs de vídeo, usar imágenes que no vengan en jpg, etc.

Lo que he decidido es empaquetar todos estos scripts para poderlos descargar juntos, ya que ocupan muy poco. Podéis des cargarlo en uno de los tres formatos siguientes:

Para finalizar:

No me gusta hacer artículos demasiado técnicos y tengo la sensación de haber aburrido con tanta parrafada. A los desconocedores les vendrá grande y a los versados en estas cosas les basta el código fuente del programa que es bastante legible. Para no resultar pesado prefiero ir resolviendo dudas en los comentarios a hacer un artículo demasiado extenso y en su caso hacer algún anexo más adelante. A mí a diferencia de algunos gurús engreídos me encanta la labor didática con los novatos.


Página 1 de 3

Funciona con WordPress & Tema de Anders Norén