Ce script utilise différentes méthodes de seuillage d'histogramme dans le but de détecter l'ombre d'images aériennes 8 ou 16 bits. L'algorithme utilisé a besoin d'au moins les 3 bandes couleurs RVB (rouge, verte et bleue) dans le visible, une bande en proche-infrarouge (PIR) de plus serait encore mieux.
shadow_mask.py
combine les différentes méthodes de détection d'ombre pour construire un processus robuste. L'idée principale est d'appliquer un seuillage global sur un groupe d'images qui présente les différentes scènes de payage d'un chantier. Le seuil déterminé peut être appliqué sur l'ensemble d'images aérienne du même chantier.
Inspiré par l'article [Adeline13], dans le cas d'images RVB, la méthode de couleur invariante [Tsai06] est appliquée. Il s'agit d'abord de convertir l'espace couleur RVB en HSI (Hue Saturation Intensity) puis d'appliquer le seuillage d'histogramme [Otsu79] sur le ratio entre H et I. Dans le cas d'images RVB-PIR, la méthode [Tsai06] est conservée, avec une autre option: la méthode [Nagao79]. Il s'agit d'un seuillage d'histogramme de "première vallée" sur la luminosité pondérée d'image. En fin, les seuillages d'histogramme sur les cartes de NDWI (Normalized Difference Water Index) et NDVI (Normalized difference Vegetaion Index) permettent de détecter des surfaces d'eau et de végétation qui risquent d'être confondues avec l'ombre.
- Adeline, K.R.M., Chen, M., Briottet, X., Pang, S.K., Paparoditis, N., 2013. Shadow detection in very high spatial resolution aerial images: A comparative study. ISPRS Journal of Photogrammetry and Remote Sensing 80, 21–38.
- Otsu, N., 1979. A threshold selection method from gray-level histograms. IEEE transactions on systems, man, and cybernetics 9, 62–66.
- Nagao, M., Matsuyama, T., Ikeda, Y., 1979. Region extraction and shape analysis in aerial photographs. Computer Graphics and Image Processing 10, 195–223.
- Tsai, V.J.D., 2006. A comparative study on shadow compensation of color aerial images in invariant color models. IEEE Transactions on Geoscience and Remote Sensing 44, 1661–1671.
Les codes de fonctionnement sont dans shadow_mask.py
, pour faciliter l'utilisation, je vous propose 2 scripts comme exemples: shadow_mask_rgb.py
et shadow_mask_rgb_nir.py
.
Pour utiliser le script, désigner un répertoire d'entrée contenant des images ainsi qu'un répertoire de sortie. A défaut de répertoire de sortie, le script ne fait que de seuillage global.
shadow_mask_rgb.py
: le script pour traiter les images RVB
python .\shadow_mask_rgb.py input=\InputImage threshold_input=\ThresholdInputImage pref_rgb=PrefixKey ext=.jp2 bits=8 jump=2 sub=10 hsteq=False output=\OutputResults masked_image=True th=th_shadow
input
= nom du répertoire d'entrée.threshold_input
= nom du répertoire d'entrée pour le seuillage global. A défaut,threshold_input=input
pref_rgb
= prefixe du jeu de données à utiliserext
= extension des images dans le répertoire d'entrée, défaut=.*bits
= profondeur de couleur, 8 ou 16, défaut=8jump
= intervalle pour la création de list d'image pour le seuillage global. Le seuillage global n'a pas besoin de lire toutes les images, donner un intervalle>1 permet de gagner du temps. défaut=1sub
= un autre intervalle pour le seuillage global. Le seuillage global n'a pas besoin de lire tous les pixels d'une image, donner un intervalle>1 permet de gagner du temps. défaut=10hsteq
= option pour le seuillage global. Certaines images en 16bits brute ont une plage de dynamique restreinte,hsteq=True
applique une égalisation histogramme sur la luminositéI
afin d'améliorer le résultat de seuillage d'histogramme. défaut=Falseoutput
= nom du répertoire de sortie. A défaut de répertoire de sortie, le script ne fait que de seuillage global.masked_image
=True, enregistrer l'image d'entrée en 8 bits avec les ombres marquées en rouge.défaut=False
.th=th_shadow
, valeur de seuil définie par utilisateur.Ce paramètre désactive le seuillage global
shadow_mask_rgb_nir.py
: le script pour traiter les images RVB + PIR
python .\shadow_mask_rgb_nir.py input=\InputImage threshold_input=\ThresholdInputImage pref_rgb=PrefixKeyRgb pref_rgb=PrefixKeyPir ext_rgb=-RVB.jp2 ext_nir=-PIR.jp2 bits=8 jump=2 sub=10 hsteq=False method=nagao output=\OutputResults masked_image=True th=[th_shadow,th_wat,th_veg]
input
= nom du répertoire d'entrée. Les images RVB sont stockés dans le sous-répertoire\RVB
et les images PIR sont stockés dans le sous-répertoire\IR
threshold_input
=nom du répertoire d'entrée pour le seuillage global. Les images RVB sont stockés dans le sous-répertoire\RVB
et les images PIR sont stockés dans le sous-répertoire\IR
. A défaut,threshold_input=input
pref_rgb
= prefixe du jeu de données RGB à utiliser.pref_nir
= prefixe du jeu de données PIR à utiliser.ext_rgb
etext_nir
= extension des images RVB et PIR, Attention les noms d'image RVB et PIR doivent être identiques sauf leur extension, par exemplenom-RVB.jp2
dans le répertoire\InputImage\RVB\
etnom-PIR.jp2
dans le répertoire\InputImage\PIR\
. Cela permet au programme de repérer le couple d'images RVB/PIR. défaut=.*bits
= profondeur de couleur, 8 ou 16, défaut=8jump
= intervalle pour la création de list d'image pour le seuillage global. Le seuillage global n'a pas besoin de lire toutes les images, donner un intervalle>1 permet de gagner du temps. Sithreshold_input
est donné,jump
est forcé à 1. défaut=1sub
= un autre intervalle pour le seuillage global. Le seuillage global n'a pas besoin de lire tous les pixels d'une image, donner un intervalle>1 permet de gagner du temps. default=10hsteq
= option pour le seuillage global. Certaines images en 16bits brute ont une plage de dynamique restreinte,hsteq=True
applique une égalisation histogramme sur la luminositéI
afin d'améliorer le résultat de seuillage d'histogramme. défaut=Falsemethod
= option pour sélectionner la méthode de seuillage global. Il dispose les optionsnagao
ettsai
, défaut=nagaooutput
= nom du répertoire de sortie. A défaut de répertoire de sortie, le script ne fait que de seuillage global.masked_image
=True, enregistrer l'image d'entrée en 8 bits avec les ombres marquées en rouge.défaut=False
.th=[th_shadow,th_wat,th_veg]
, valeur de seuil définie par utilisateur.Ce paramètre désactive le seuillage global
Dans le répertoire de sortie, vous trouverez:
- mask_nom.tif: Masque d'ombre binaire obtenu, les pixels d'ombre ont la valeur 0 et les restes ont la valeur 255.
- masked_nom.jpg: L'image d'entrée en 8 bits avec les ombres marquées en rouge.
Pour comparer la précision des différents masques d'ombre, le script DifferenceMask.py
compare deux masques issus d'une même image.
Ce script donne des statistiques sur la précision d'un masque d'ombre par rapport à un masque dit de référence, en évaluant par rapport à la référence, quels pixels sont correctement détéctés à l'ombre ou non.
python .\DifferenceMask.py .\MasqueDeReference .\MasqueATester
Il y'a également deux masques de référence où l'ombre a été sélectionnée à la main dans les dossiers 35Reference et 75Reference Ces dossiers contiennent l'image de base, le masque de référence (réalisé manuellement via Gimp) et un masque à tester, créé via l'algorithme de seuillage.
Cependant, même à l'oeil nu il est difficile dans certains cas de déterminer si certains pixels sont à l'ombre ou non, c'est pourquoi ces références ont un intêret pour comparer mais ne sont pas une vérité absolue.
Le seuillage global avec une liste d'images construite par jump n'est peut être pas la méthode la plus efficace, surtout s'il existe de scènes seulement présentées dans 1 ou 2 images. Dans le cas de seuillage global RVB+PIR, il faut penser à construire une liste d'images sélectionnées par l'utilisateur pour le seuillage global.
La détermination des seuils pour l'eau et pour la végétation peut utiliser différents jeux de données.
Manchun Lei - https://www.umr-lastig.fr/manchun-lei/