Retoucher les zones sombres/lumineuses (script Gimp)

20 12 2009

À l’aide d’un script pour The Gimp, je présente une méthode pour rattraper des images prises au flash.

Et j’en profiterai en même temps pour détailler et commenter le script.

Le problème

Les photos prises au flash (le flash de monsieur tout le monde s’entend) présentent généralement les problèmes suivants :

  • les sujets proches sont éclairés, mais les sujets éloignés sont dans l’ombre,
  • le flash atténue les détails et reliefs des sujets proches.

Prenons un exemple :

Photo originale

Photo originale

Cette photo illustre illustre bien le phénomène : les papiers sur la table ainsi que la nappe manquent de matière tandis que plus on s’éloigne, plus on est dans l’ombre.

Avec la méthode présentée, vous pourrez arriver à ceci :

Photo retouchée

Photo retouchée

La retouche n’étant pas excessive (volontairement), les versions réduites ne permettent pas de se rendre compte de la retouche. Si vous voulez comparer, vous pouvez télécharger la photo originale et la photo retouchée.

La méthode

Sous The Gimp, elle se décompose en :

  • duplication du calque actif,
  • ajout d’un masque de calque avec copie du calque en niveau de gris,
  • flou gaussien sur le masque avec un rayon de 200 pixels,
  • niveaux automatiques sur le masque,
  • utilisation de l’outil Courbes sur le calque.

L’idée réside dans l’utilisation du flou et du masque de calque.

Le flou, avec un rayon aussi important ne fait apparaître que des zones sombres et des zones lumineuses sans détail :

Flou sur l’exemple en niveaux de gris

Flou sur l’exemple en niveaux de gris

Une fois transformé en masque, ce flou filtrera plus ou moins fortement chaque pixel du calque en fonction de sa localisation dans une zone sombre ou lumineuse. En inversant le flou (négatif photo), on obtient l’effet inverse.

Il suffit donc de retoucher le nouveau calque pour que les effets de cette retouche portent principalement sur les zones lumineuses (ou sombres).

Le script

Si vous avez beaucoup de photos à retoucher, cette manipulation devient vite rébarbative.

Avec un script-fu, on peut s’alléger le travail.

J’avais déjà fait un billet “Décortiquons un script-fu pour Gimp”.

J’en ai profité pour faire quelques ajouts :

  • un fichier contenant 2 commandes (“Masque zones lumineuses” et “Masque zones sombres”),
  • utilisation de l’instruction “catch” pour récupérer d’un éventuel plantage,
  • utilisation d’un structure conditionnelle (if … then … else),
  • création de calque et de masque de calque.

2 commandes dans un fichier

Script-fu n’interdit nullement d’avoir plusieurs définitions dans un seul et même fichier. Vous pouvez utiliser autant d’appel à script-fu-register que vous le souhaitez.

Dans mon cas, j’avais besoin de créer 2 commandes distinctes mais ayant quasiment le même fonctionnement : La différence entre le masque des zones lumineuses et le masque des zones sombres est une inversion du masque de calque. J’ai appelé cette fonction unique masque-luminosite.

Je ne voulais pas d’interface utilisateur. Malheureusement, je n’ai pas trouvé le moyen de rajouter des paramètres à mes fonctions dans script-fu-register sans qu’il les transforme en interface utilisateur. Les seuls paramètres automatiques sont image et drawable (l’image courante et le drawable actif).

Je suis donc passé par 2 fonctions supplémentaires : script-fu-zonessombres et script-fu-zoneslumineuses. Elles font un appel à la fonction masque-luminosite avec une valeur prédéfinie pour le paramètre zonessombres.

Le schéma ci-dessous montre les relations entre script-fu-register et les fonctions :

Arbre des appels

Arbre des appels

Récupération des erreurs : catch

Un script-fu est souvent composé d’un code pris entre un appel à gimp-image-undo-group-start et un appel à gimp-image-undo-group-end afin de n’avoir qu’une seule annulation à faire pour l’utilisateur si l’effet du script ne lui plaît pas.

Oui mais voilà… si une erreur survient à l’intérieur de notre code, l’utilisateur se retrouve avec une pile d’annulation inconsistante puisque l’appel à gimp-image-undo-group-end n’a pas pu se faire. Impossible alors pour lui de remettre cette pile en bon ordre.

C’est là que l’instruction catch se révêle utile.

Son utilisation est très simple :

(catch (fonction à appeler en cas de problème)
  (code à exécuter)
  (code à exécuter)
)

Si tout se passe bien, catch retourne le résultat de la dernière fonction exécutée, sinon il retourne le résultat de la fonction à appeler en cas de problème.

Désormais, quand vous ferez un script-fu, utilisez le gabarit suivant :

  • gimp-image-undo-group-start
  • catch …
  • gimp-image-undo-group-end

Quoi qu’il se passe, vous êtes sûr de laisser la pile d’annulation dans un bon état.

Le seul hic, c’est qu’il ne vous est pas possible d’annuler un groupe démarré. Il n’est pas possible d’appeler la commande “annuler” depuis un script. Ce sera à l’utilisateur de le faire (mais c’est toujours mieux qu’une pile dans un sale état).

Utilisation d’une structure conditionnelle if … then … else

C’est un grand classique de la programmation. Mais on l’utilise peu souvent dans un script-fu.

(if (test)
  (code à exécuter si le test est vérifié)
  (code à exécuter si le test n’est pas vérifié)
)

Il nous manque juste une autre instruction. Vous êtes obligé de faire tenir chacun des 2 codes à exécuter dans une seule liste puisqu’il n’y a pas d’instruction else.

Cette instruction, c’est begin :

(begin
  (code à exécuter)
  (code à exécuter)
)

Création de calque et de masque de calque

On se concentre à nouveau sur Gimp.

La grande subtilité dans la création de calque et de masque de calque ? Après les avoir créés, il faut toujours et avant toute autre opération les rattacher explicitement à l’image ou au calque auquel ils sont destinés.

La création d’un calque ou d’un masque de calque nécessite 2 commandes : la création et l’attachement. Même si lors de la création vous indiquez l’image…

Les fonctions utilisées

En reprenant les différentes étapes du script, voici les fonctions utilisées :

  1. démarre un niveau de undo → gimp-image-undo-group-start,
  2. affiche un message d’erreur en cas de problème → catch et gimp-message,
  3. crée un nouveau calque en copiant l’actuel → gimp-layer-new-from-drawable,
  4. ajoute le nouveau calque à l’image → gimp-image-add-layer,
  5. ajoute un masque au nouveau calque avec une copie en niveau de gris → gimp-layer-create-mask,
  6. ajoute le masque à l’image → gimp-layer-add-mask,
  7. applique un flou gaussien de rayon 200 pixels → plug-in-gauss-iir2,
  8. applique un niveau automatique sur le masque → gimp-levels-stretch,
  9. inversion du masque → gimp-invert,
  10. définit le nom du nouveau masque → gimp-drawable-set-name,
  11. désactive l’édition du masque → gimp-layer-set-edit-mask,
  12. termine le niveau de undo → gimp-image-undo-group-end.

Notes :

  1. -
  2. gimp-message, en plus d’afficher votre message, affichera aussi les messages d’erreur du greffon fautif. Vous pouvez utiliser \n pour faire des retour à la ligne.
  3. -
  4. -
  5. La copie en niveau de gris du calque dans le masque se fait avec la constante ADD-COPY-MASK.
  6. -
  7. La méthode IIR est conseillée pour les photos, cible principale du script.
  8. gimp-levels-stretch permet de garantir que les zones les plus lumineuses seront au maximum et inversement pour les zones sombres.
  9. -
  10. Pas obligatoire, mais plus propre et “user-friendly”
  11. Si on ne désactive pas l’édition du masque, toutes les opérations effectuées par l’utilisateur après l’appel du script seront effectuées sur le masque et non sur le calque.
  12. -

Le source du script

Télécharger le script selective-layer.scm.

(define (masque-luminosite image drawable zonessombres)
  ; Démarre un niveau de undo
  (gimp-image-undo-group-start image)

  (catch (gimp-message "Il y a eu une erreur.\nLe résultat n’est probablement pas celui attendu.\nVous pouvez annuler l’opération")
    (let* (; Crée un nouveau calque en copiant l’actuel
           (base (car (gimp-layer-new-from-drawable drawable image)))
          )

      ; Ajoute le nouveau calque à l’image
      (gimp-image-add-layer image base -1)

      ; Ajoute un masque au nouveau calque avec une copie en niveau de gris
      (let* ((masque (car (gimp-layer-create-mask base ADD-COPY-MASK))))
        ; Ajoute le masque à l’image
        (gimp-layer-add-mask base masque)

        ; Applique un flou gaussien de rayon 200 pixels
        (plug-in-gauss-iir2 RUN-NONINTERACTIVE image masque 200 200)

        ; Applique un niveau automatique sur le masque
        (gimp-levels-stretch masque)

        ; Inverse le masque si on veut avoir les zones sombres
        (if (= zonessombres TRUE)
          (begin
            ; Inversion du masque
            (gimp-invert masque)
            ; Définit le nom du nouveau masque
            (gimp-drawable-set-name base "Zones sombres")
          )
         ; else
          ; Définit le nom du nouveau masque
          (gimp-drawable-set-name base "Zones lumineuses")
        )
      )

      ; Désactive l’édition du masque
      (gimp-layer-set-edit-mask base FALSE)
    )
  )

  ; Termine le niveau de undo
  (gimp-image-undo-group-end image)
)

(define (script-fu-zoneslumineuses image drawable)
  (masque-luminosite image drawable FALSE)
)

(script-fu-register "script-fu-zoneslumineuses"
  "<Image>/Script-Fu/Masque des zones lumineuses"
  "Crée un nouveau calque avec un masque filtrant les zones lumineuses"
  "Frédéric Bisson "
  "Frédéric Bisson"
  "2009-12-19"
  "RGB*, GRAY*"
  SF-IMAGE "Image en entrée" 0
  SF-DRAWABLE "Calque en entrée" 0
)

(define (script-fu-zonessombres image drawable)
  (masque-luminosite image drawable TRUE)
)

(script-fu-register "script-fu-zonessombres"
  "<Image>/Script-Fu/Masque des zones sombres"
  "Crée un nouveau calque avec un masque filtrant les zones sombres"
  "Frédéric Bisson "
  "Frédéric Bisson"
  "2009-12-19"
  "RGB*, GRAY*"
  SF-IMAGE "Image en entrée" 0
  SF-DRAWABLE "Calque en entrée" 0
)

Notes

Il ne faut pas rêver, on peut atténuer les effets du flash mais pas faire des miracles :

  • les zones sombres sont souvent très bruitées même si cela ne se voit pas sur la photo originale, augmenter la luminosité sur ces zones mettra rapidement en évidence le bruit,
  • les zones saturées (flash trop fort ou trop proche) ne contiennent pas les informations nécessaires à leur rattrapage,
  • avoir la main lourde sur la correction peut faire apparaître des halos dans les zones fortement contrastées ; quand on fait les corrections, on travaille généralement avec une image plein écran ou grand format, réduire l’image fera immédiatement apparaître le halo.
About these ads

Actions

Information

3 responses

20 12 2009
Décortiquons un script-fu pour Gimp « Le blog de Zigazou

[…] D’autres techniques et astuces dans le développement de scripts Gimp sont abordées dans le billet Retoucher les zones sombres/lumineuses (script Gimp). […]

23 04 2011
François Collard

Bonjour,
Je tombe sur votre exemple en écrivant un script-fu (on oublie la syntaxe parce qu’on en écrit trop peu;)
En passant, je vous signale qu’on peut, sans qu’il en résulte aucun avantage bien marqué sinon la satisfaction de ne pas changer ses habitudes, une instruction cond, qui accepte else. Voici un exemple tiré d’un script que je n’ai pas diffusé mais qui marche :
(cond ((= inner-border FALSE) (define radius rayon)) (else (define radius (+ inner-width rayon))))

23 04 2011
zigazou

Bonjour,
C’est vrai que cond permet notamment de se débarrasser du bloc begin. Comme je n’en fais pas souvent non plus, j’avais oublié cette partie de mes cours de Lisp.

Merci !

@+

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s




Suivre

Recevez les nouvelles publications par mail.

%d blogueurs aiment cette page :