Python : callback à paramètre unique et passage d'options
Le besoin m'est venu de la bibliothèque pims permettant de charger séquentiellement des images. Typiquement, on fait
frames = pims.ImageSequence('../sample_data/bulk_water/*.png')
Mais si on veut appliquer une fonction appliquant un pré-traitement, on peut ajouter une callback
from skimage.color import rgb2grey
def preprocess(im):
"""
callback prenant une image im
"""
return rgb2grey(im)
frames = pims.ImageSequence('../sample_data/bulk_water/*.png', process_func=preprocess)
Ce qui a pour effet que les images soient en niveau de gris plutôt qu'en RGB. Maintenant, imaginons que ce soit un seuil que je souhaite appliquer
def preprocess(im):
threshold = 0.8
grey_im = rgb2grey(im)
# selectionne les indices satisfaisant la condition
idx = grey_im < grey_im.max() * threshold
# applique une transformation
grey_im[idx] = 0
return grey_im
L'exemple fonctionne toujours, mais on a un paramètre threshold définit dans la fonction, ce qui n'est pas très flexible si on veut placer cette fonction dans une petite bibliothèque maison. Je préfèrerais la signature suivante :
def preprocess(im, threshold=0.8):
Je vais donc définir dans ma bibliothèque la fonction suivante :
# Je definie une fonction qui prend une fonction et des arguments optionels
def all_args(func, **params):
# Je definie une fonction qui prend une image
def wrapper(im):
# Je retourne ma fonction func avec les bons arguments
return func(im, **params)
# je retourne une fonction
return wrapper
# Je definie ma fonction comme je le souhaite
def preprocess(im, threshold=0.8):
grey_im = rgb2grey(im)
idx = grey_im < grey_im.max() * threshold
grey_im[idx] = 0
return grey_im
Ainsi je peux faire dans mon code principal
from mabiblio import all_args, preprocess
mythreshold = .36
# je crée une fonction new_preprocess à partir de preprocess, auquel je cache
# le parametre threshold
new_preprocess = all_args(preprocess, threshold=mythreshold)
frames = pims.ImageSequence('../sample_data/bulk_water/*.png', process_func=new_preprocess)
Ici, je peux donc utiliser la fonction preprocess, de manière compacte, un peu partout dans mes codes, sans me soucier de son détail.
Je crois que je dois cette astuce à Thomas Caswell que je remercie.
Liens utiles de sametmax :
- http://sametmax.com/quest-ce-quun-callback/
- http://sametmax.com/comprendre-les-decorateurs-python-pas-a-pas-partie-1/ (une fonction est un objet)