Focus stacking en ligne de commande sous GNU/Linux Imprimer
Écrit par Eddy   
Jeudi, 23 Décembre 2010 20:54

Bonjour,

        Le focus stacking est une technique qui vise à augmenter la profondeur de champ d'une photomicrographie en réalisant la synthèse de plusieurs clichés obtenus en faisant varier la mise au point d'un bout à l'autre du spécimen. En microscopie, elle apporte une solution élégante au problème posé par la faible profondeur de champ des objectifs à ouverture numérique élevée.


        Les utilisateurs de Microsoft Windows disposent de nombreux outils dédiés au focus stacking, notamment CombineZP, Helicon Focus, Zerene Stacker ou PhotoAcute Studio ; la plupart d'entre eux ont fait l'objet de présentations détaillées sur le forum. Sous GNU/Linux, ces outils sont utilisables à travers Wine ou des outils de virtualisation  comme VirtualBox ou VMware. Cependant, il existe aussi des solutions en ligne de commande, simples d'emploi et surtout faciles à automatiser, qui motivent l'écriture du présent article.

        Étant surtout intéressé par la mycologie, j'ai choisi d'appliquer cette technique à des basidiospores de russule. La détermination des russules est généralement considérée comme difficile : elle fait appel, entre autres choses, à l'examen des caractères microscopiques et, en particulier, de l'ornementation sporale. Celle-ci est mise en évidence par le réactif de Melzer, un colorant iodo-ioduré pour lequel un protocole de coloration rapide a été présenté sur le forum. Afin d'aider le déterminateur, les livres de mycologie proposent des schémas détaillés de l'ornementation sporale, réalisés par de talentueux dessinateurs.

 

         À ce stade, je suppose que des préparations soignées ont été réalisées et que des images ont été prises en vue d'un traitement par focus stacking. Dans la mesure du possible, celles-ci doivent être bien alignées, bien contrastées et comporter des zones nettes légèrement chevauchantes (on recommande environ 30% de recouvrement pour deux images adjacentes). En pratique, entre 5 et 10 images au format JPEG suffisent à donner de bons résultats. Les tests réalisés avant la rédaction de cet article me donnent à penser que, dans le cas présent, le recours au format RAW n'est pas indispensable.

 


Conversion des images JPEG au format TIFF
 
        Les logiciels que nous allons utiliser pour empiler les images travaillent avec des fichiers au format TIFF. Or, les appareils photo proposent généralement de sauvegarder les images au format JPEG (c'est en tout cas ce que propose mon Canon EOS 500D, en plus du format RAW). Nous allons donc commencer par convertir nos images JPEG au format TIFF. Il existe pour cela une méthode fastidieuse car répétitive qui consiste à ouvrir chaque image dans un logiciel tel que Gimp, puis à l'enregistrer sous un autre format. Sous GNU/Linux, on peut traiter les images par lots à l'aide d'un outil de la suite logicielle ImageMagick appelé convert (installation sous Ubuntu : sudo apt-get install imagemagick). Celui-ci peut non seulement convertir une image dans un autre format, mais aussi effectuer des transformations diverses comme un logiciel de retouche photo. Je m'en sers donc pour convertir un lot d'images au format TIFF en leur appliquant des filtres (netteté, contraste) et une correction de type flat field.

 
eddy$ find *.jpg -execdir convert flat-field.jpg {} -unsharp 0x20 -compose divide -composite {}.tif \;


        Cette longue commande fait beaucoup de choses : d'abord, elle utilise le programme find pour trouver tous les fichiers JPEG du répertoire courant. Elle applique ensuite à chacun d'entre eux la commande convert, qui effectue les transformations suivantes :

  • Augmentation du contraste de l'image JPEG (option -unsharp 0x20).
  • Correction de type flat field (option -compose divide -composite) avec la carte des poussières flat-field.jpg.
  • Conversion au format TIFF.

        Vous aurez sans doute compris que les paires d'accolades {} sont remplacées par le nom du fichier JPEG récupéré par la commande find, de sorter que la commande est appliquée successivement à tous les fichiers du répertoire. J'ajoute que l'on peut combiner plein d'autres outils. Je vous renvoie pour cela au manuel d'utilisation de l'outil convert sur cette page (en anglais).


        Une dernière précision importante pour la suite : Les fichiers TIFF produits portent l'extension .jpg.tif, car nous n'avons indiqué à aucun moment que nous voulions supprimer l'extension JPEG ! C'est bête mais le savoir évite bien des tâtonnements... Sourire

 



Alignement des images en vue du focus stacking

        Nous allons maintenant vérifier l'alignement des images au format TIFF en vue de leur synthèse ultérieure par le programme de focus stacking. Cette étape est importante : elle conditionne en grande partie la qualité du résultat final. On utilise pour cela un outil appelé align_image_stack qui fait partie de la suite d'outils Hugin (installation sous Ubuntu :  sudo apt-get install hugin-tools). Son utilisation est très simple :

eddy$ align_image_stack -m -a zframe_ *.jpg.tif

        Cette commande indique à align_image_stack d'utiliser toutes les images au format TIFF du répertoire courant; elle crée des masques qui seront préfixés par zframe_, de sorte que nous pourrons facilement les réutiliser par la suite. Cette étape est relativement longue si l'on choisit de travailler sur les images en taille réelle, mais on peut aussi demander de travailler sur des miniatures... au prix d'une petite perte de précision. Malgré tout, avec les ordinateurs actuels, le programme vient à bout de 5-10 images en moins d'une minute.

 



Le focus stacking proprement dit !
 
        Maintenant que les images sont alignées, il ne reste plus qu'à construire l'image finale en utilisant un autre logiciel en ligne de commande appelé enfuse (installation sous Ubuntu : sudo apt-get install enfuse). On utilise les paramètres suivants :

 

eddy$ enfuse -o output.tif

  --exposure-weight=0

  --saturation-weight=0

  --contrast-weight=1

  --hard-mask

  --contrast-window-size=9 zframe_*.tif

 

        Les paramètres passés à enfuse lui indiquent qu'il faut accorder du poids aux pixels bien contrastés, (--contrast-weight=1) mais pas aux pixels bien exposés ( --exposure-weight=0) ou présentant une saturation convenable (--saturation-weight=0). Le contraste local est évalué à partir d'une « fenêtre » de 9 pixels ( --contrast-window-size=9). Les images utilisées en entrée sont les images alignées produites précédemment (celles qui sont préfixées par zframe_), et l'image finale est enregistrée dans le fichier output.tif. Elle peut ensuite faire l'objet de post-traitements divers (notamment NeatImage et MicroCartouche). Voici un exemple d'image finale obtenue à l'aide de ces outils :

 

output

        Comme vous pouvez le voir, l'ornementation des spores est assez nette. Il s'agit d'une réticulation incomplète, avec des crêtes et des connectifs un peu plus fins, ainsi que quelques verrues isolées. Sur l'image, on distingue aussi quelques plages supra-apiculaires. Les artefacts ne sont pas trop nombreux (les plus flagrants sont le fait d'un paramétrage un peu trop drastique de NeatImage), mais on aurait pu faire mieux en augmentant le nombre de clichés initiaux.


Pour finir voici un résumé illustré des commandes abordées tout au long de cet article :

 

resume-commandes

 

 

Et l'automatisation dans tout ça ?
 

        Les lecteurs attentifs auront sûrement remarqué que j'ai passé sous silence l'un des points les plus importants, à savoir l'automatisation de ces quelques commandes ! En fait, il suffit de les regrouper dans un script, comme ceci :

 

#! /bin/bash

 

FFIELD_IMAGE=$1 


echo "Conversion JPEG -> TIFF, correction flat field et netteté"

find *.jpg -execdir convert $FFIELD_IMAGE {} -unsharp 0x20 -compose divide -composite {}.tif


echo "Alignement des images à empiler"

align_image_stack -m -a zframe_ *.jpg.tif


echo "Empilement des images (focus stacking)"

enfuse -o output.tif \

  --exposure-weight=0 \

  --saturation-weight=0 \

  --contrast-weight=1 \

  --hard-mask \

  --contrast-window-size=9 zframe_*.tif

 


 

Le cas des fichiers RAW et les métadonnées
 

 

        Quelquefois, les images sont prises au format RAW et non directement en JPEG. Dans ce cas, il est également possible de travailler en ligne de commande avec des logiciels libres, en utilisant dcraw. Ce logiciel permet d'extraire les données d'un fichier au format RAW et de les exporter au format TIFF. Plusieurs options sont disponibles pour choisir les modalités d'extraction (saturation, contraste, réduction du bruit, encodage des couleurs, etc.).

        On peut aussi envisager d'utiliser l'utilitaire exiftool pour récupérer les métadonnées des images et les ajouter à l'image définitive... mais je laisse aux lecteurs intéressés le soin d'explorer cette piste... Complice 

 

Merci pour votre attention !

 

 

Supplément : un script bash prêt à l'emploi

 

        Le script ci-dessous effectue la plupart des tâches décrites dans cet article (lecture des images au format RAW ou JPEG, corrections diverses telles que flat-field, netteté ou bruit). Plus d'infos sur simple demande. Sourire

 

#! /bin/bash

# fstack.sh - Script de focus stacking pour GNU/Linux
# Utilisation : ./fstack.sh [SOURCE] [TARGET] [FFIELD] [OUTPUT]

SOURCE=${1:-jpg}
TARGET=${2:-tif}
FFIELD=${3:-ffield.tif}
OUTPUT=${4:-output}

assert_installed() {
   which "$1" &> /dev/null
   if [ $? != 0 ]; then
     echo "Info: logiciel $1 absent. Exécution annulée."
     exit 2
   else
     echo "Info: logiciel $1 trouvé."
  fi
}

# Vérification des logiciels installés.
assert_installed "exiftool"
assert_installed "dcraw"
assert_installed "convert"
assert_installed "align_image_stack"
assert_installed "enfuse"

mkdir work
cp *.$SOURCE work
cd work

# Si les images sont au format RAW, utiliser dcraw pour en extraire le contenu
# au format TIFF.
if [ "$SOURCE" == "CR2" ] || [ "$SOURCE" == "CRW" ]; then
  echo -n "> Extraction des images... "
  find *.$SOURCE -execdir dcraw -T -w {} \; &> /dev/null 
  SOURCE=tiff
  TARGET=tiff
  echo "Terminé"
fi 

# Convertir les images au format TIFF en leur appliquant une réduction du bruit,
# une augmentation de la netteté et une correction de type flat-field.
echo -n "> Conversion des images... "
find *.$SOURCE -execdir \
convert {} -unsharp 0x20 -noise 1 {}.convert.$TARGET \; &> /dev/null
echo "Terminé"

# Aligner les différents clichés en vue de leur empilement.
echo -n "> Alignement des images... "
align_image_stack -m -a zframe_ *.convert.$TARGET &> /dev/null
echo "Terminé"

# Empilement des clichés et calcul de l'image finale.
echo -n "> Empilement des images... "
enfuse -o $OUTPUT.$TARGET \
  --exposure-weight=0 \
  --saturation-weight=0 \
  --contrast-weight=1 \
  --hard-mask \
  --contrast-window-size=9 zframe_* &> /dev/null
mv $OUTPUT.$TARGET ..
echo "Terminé"

# Nettoyage des fichiers.
echo -n "> Nettoyage du répertoire... "
rm *
cd ..
rmdir work
echo "Terminé"

 

Cordialement,

Eddy

Mise à jour le Dimanche, 09 Janvier 2011 21:00