2009/04/23

Un script para hacer HDR en Linux

This article is also available in English: Script to make HDRs with Linux.

En el artículo HDR en Linux expliqué mi flujo de trabajo para hacer HDR en Linux. Continuando con ese tema, en este artículo presento el script uso habitualmente para automatizar este proceso en una única llamada.

El código del script en cuestión es el siguiente:

#! /bin/bash

set -e

SELF=`basename $0`

DIR=.
ALIGN=N
ENFUSE=N
TONEMAP=N

echo "$SELF: `date`"

while [ "$1" != "" ]; do
 case "$1" in
  "-a")
   ALIGN=Y
   ;;
  "-e")
   ENFUSE=Y
   ;;
  "-t")
   TONEMAP=Y
   ;;
  "-d")
   DIR="$2"
   shift
   ;;
  *)
   echo "$SELF: Parameters"
   echo "$SELF:  -d      -> Directory"
   echo "$SELF:  -a      -> Align images"
   echo "$SELF:  -e      -> Create enfuse"
   echo "$SELF:  -t      -> Create and tonemap HDR"
   exit
   ;;
 esac

 shift
done

HDR="$DIR"/HDR
FILES=("$DIR"/*.[Cc][Rr]2)
COUNT=${#FILES[@]}

echo "$SELF: Options:"
echo "$SELF:  Directory  = $DIR"
echo "$SELF:  Output     = $HDR"
echo "$SELF:  Align      = $ALIGN"
echo "$SELF:  Enfuse     = $ENFUSE"
echo "$SELF:  Tonemap    = $TONEMAP"
echo "$SELF:  Files      = ${FILES[*]}"

if [ $COUNT -eq 0 ]; then
 echo "$SELF: No files found!!!"
 exit 1
fi

echo "$SELF: Creating output directory:"
mkdir "$HDR"

echo "$SELF: Parsing EXIF information:"
dcraw2hdrgen ${FILES[*]} > "$HDR"/pfs_raw.hdrgen

echo "$SELF: Generating TIFFs"
ufraw-batch --wb=camera --gamma=0.45 --linearity=0.10 --exposure=0.0 --saturation=1.0 --out-type=tiff --out-depth=16 --overwrite --out-path="$HDR" ${FILES[*]}

FILES=("$HDR"/*.tif)

if [ "$ALIGN" = "Y" -a $COUNT -gt 1 ]; then
 echo "$SELF: Aligning images"
 align_image_stack -a "$HDR"/AIS_ ${FILES[*]} > "$HDR"/align_image_stack.log
 rm -f ${FILES[*]}
 FILES=("$HDR"/AIS_*.tif)
fi

if [ "$ENFUSE" = "Y" ]; then
 if [ $COUNT -gt 1 ]; then
  echo "$SELF: Generating enfuse:"
  enfuse -o "$HDR"/enfuse.tif ${FILES[*]} > "$HDR"/enfuse.log
 else
  echo "$SELF: By-passing enfuse:"
  ln ${FILES[*]} "$HDR"/enfuse.tif
 fi
fi

if [ "$TONEMAP" = "Y" ]; then
 echo "$SELF: Parsing hdrgen"
 i=0
 > "$HDR"/pfs_tif.hdrgen
 cat "$HDR"/pfs_raw.hdrgen | while read LINE; do
  echo "${FILES[$i]} $LINE" | cut -d' ' -f1,3- >> "$HDR"/pfs_tif.hdrgen
  i=`expr $i + 1`
 done

 echo "$SELF: Generating HDR:"
 pfsinhdrgen "$HDR"/pfs_tif.hdrgen | pfshdrcalibrate -b 16 -x | pfsout "$HDR"/pfs.hdr

 echo "$SELF: Tone-mapping HDR:"

 echo "$SELF:  Operator = mantiuk06"
 pfsin "$HDR"/pfs.hdr | pfstmo_mantiuk06 -e 1 -s 1 | pfsgamma -g 2.2 | pfsoutimgmagick "$HDR"/pfstmo_mantiuk06.tif

 echo "$SELF:  Operator = fattal02"
 pfsin "$HDR"/pfs.hdr | pfstmo_fattal02 -s 1 | pfsoutimgmagick "$HDR"/pfstmo_fattal02.tif
fi

echo "$SELF: Cleanning:"
rm -f ${FILES[*]}

Es script está preparado para usarse con los ficheros RAW generados por una Canon 400D, pero creo que es fácilmente adaptable a otras cámaras. En concreto, donde dice "FILES=("$DIR"/*.[Cc][Rr]2)" se están seleccionando los ficheros con extensión "CR2", que son los que generan todas las cámaras Canon (Nikon utiliza la extensión "NEF", por ejemplo); y los parámetros "--gamma=0.45 --linearity=0.10" que se le pasan a "ufraw-batch" son específicos de la 400D. El resto creo que debería ser bastante genérico.

Lo primero que hay que hacer es bajarse el código al ordenador y guardarlo en un fichero que podamos ejecutar. Supongo que lo más sencillo es conectarse como usuario "root" y crear un fichero llamado "hdr.sh" en el directorio "/usr/local/bin/". Entonces seleccionamos y copiamos el código, lo pegamos en el fichero, y lo guardamos; finalmente hay que ir a la línea de comandos y dar permisos de ejecución con "chmod +x /usr/local/bin/hdr.sh".

Para utilizarlo, el primer paso es descargar en un directorio vacío todas las exposiciones de una escena que queramos juntar. Entonces ejecutamos el script con "hdr.sh -d _directorio_ -a -e -t". Lo dejamos que trabaje un rato, y cuando acabe tendremos tres ficheros nuevos en nuestro directorio: "enfuse.tif", "pfstmo_mantiuk06.tif", y "pfstmo_fattal02.tif".

El parámetro "-a" sirve para alinear automáticamente las imágenes; si hemos hecho las fotos con trípode y estamos completamente seguros de que están perfectamente alineadas, podemos quitarlo y el script acabará antes. Con "-e" indicamos que debe generarse la versión enfuse, y también podemos quitarlo si sabemos que no vamos a usarla; análogamente, podemos quitar el parámetro "-t" si no queremos que se haga el mapeo de tonos.

Notas

2009/07/27: He actualizado el artículo, para mejorar el paso del mapeo tonal, usando parámetros que generan un mejor resultado; también lo he ampliado para poder generar HDRs a partir de una única foto.

2009/09/21: Vincent Tassy ha publicado una versión mejorada de este script; su versión genera autoáticamente el fichero GIMP al final del proceso (un detalle muy interesante), y puede generar HDRs a partir de ficheros JPEG (yo no suelo usar JPEG, sólo RAW, sin embargo). Su versión es mejor que la mia, yo iría allí y la cogería: Linux script to generate HDR images from bracketed images.

2010/09/21: Gracias al consejo de un lector anónimo, he conseguido que funcione la salida a TIFF en el paso del mapeo de tonos; espero que con esto se ganará algo de calidad en la imagen final.

2011/01/20: El script usa "pfshdrcalibrate -b 16 -x" durante la generación del HDR; los resultados son mucho mejores ahora.

7 comentarios :

Carlos Cabrera dijo...

Genial tu script. Sólo olvidaste ponerle una licencia por lo que no sé si sería de tu agrado que publiquemos derivados en base a él.

¿Podría hacerlo?, dando los debidos créditos, claro.

eduperez dijo...

@Carlos Cabrera:

En principio, todo el contenido está bajo la licencia Creative Commons que se muestra al pié de cada página. Pero en el caso de los scripts, posiblemente sea demasiado restrictiva, ya que no permite distribuir modificaciones; así que he decidido que todo el código esté bajo licencia GPL v2.

¡Adelante con las modificaciones! Es más: incluso podría añadir un enlace, como es el caso de la versión de Vicent Tassy, si tienen una utilidad general.

No le había dado importancia a este tema hasta ahora, al tratarse de una cantidad de código tan pequeña; pero trataré de actualizar todo el contenido lo antes posible.

Anónimo dijo...

Muchas gracias por todos tus aportes. Muy útil tu ayuda desde que me pasé a Linux.
Tengo un problema con el script: en kubuntu 10.10, al ejecutarlo me aparece:
hdr.sh: Creating output directory:
mkdir: no se puede crear el directorio «_directorio_/HDR»: No existe el archivo o directorio

Si me puedes ayudar te lo agradecería.

eduperez dijo...

@Anonimo:

En las instrucciones que están más arriba, se comenta que se debe llamar al script con el parámetro "-d _directorio_"; lo que no está bien explicado es que "_directorio_" debe sustituirse por el nombre del directorio donde están los ficheros.

Lamento no haber sido más claro, espero que ahora sí te funcione.

Anónimo dijo...

Muy bueno el script. Con ayudas como la tuya, me encanta haberme pasado a Gnu/Linux.
El script empieza bien, pero después hay un problemita. Primer está generando los tiffs, después las imágenes alineadas, y después la enfuse. Pero cuando está generando el archivo psf.hdr aparece un error que dice:
pfshdrcalibrate error: input value higher than defined number of input levels (adjust the number of bits per pixel)
No he cambiado absolutamente nada del script.
Si sirve de algo...estoy usando archivos CR2 de una Canon 550D y están instaladas las versiones de pfstools 1.8.3 y pfscalibration 1.5 que son las más nuevas.
Por favor, si pudieras ayudarme un poco.
Siempre gracias por compartirnos tu conocimiento.

Carlos.

Anónimo dijo...

Muy bueno el script, y el artículo sobre HDR desde Linux.

Me he encontrado con un problema: el script falla con un "segmentation fault" del ufraw-batch. He buscado por la red y parece ser un bug que aparece al ponerle al ufraw-batch la opcion wb=camera. Si la quitas del script funciona, pero entonces no calcula bien el bamlance de blancos.

La solucion que mejor me ha ido es convertir con el UFRaw en modo gràfico un fichero raw, con todas las opciones que pone el script (tambien uso una Canon EOS 400D) y copiarme el fichero de configuracion .ufraw.

Luego modifico el script que hay aquí, borrando las opciones de wb, gama, etc, y en cambio le añado el parámetro --conf=fichero,ufraw
Así ya funciona usando el balance de blancos de la cámara.

Josep V.

Anónimo dijo...

He visto que el error de ufraw-batch que he comentado antes me aparecia con la versión 0.17 de UFRaw. He actualizado a la versión 0.18 y ya funciona correctamente la opción wb=camera

Josep V.

Publicar un comentario en la entrada