IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Traitement d'images Discussion :

création d'image HDR


Sujet :

Traitement d'images

  1. #21
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Citation Envoyé par Valentin33 Voir le message
    Merci pseudo code, je regarde ca demain
    Jack, si tu passes par la, n'hésites pas a nous faire part de ton algo.

    Bonne soirée

    Edit : ca m'etonnes toujours qu'il n'y ait pas plus d'informations que ca sur ce type d'images, c'est vraiment dommage parce que fort intéressant..
    Jack n'a pas d'algo pour la fusion HDR vu qu'il se basait sur la première partie sur Photomatix.

    Ensuite, il utilisait l'amélioration de contraste que l'on trouve ici :
    http://subversion.developpez.com/pro...entPlugin.java (mais qui permet de donner un effet HDR à une image LDR sous exposée)

    Dont le principe est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    /**
     * 
     * Amélioration du contraste en simulant un effet HDR
     *  
     *   - Création d'un masque 
     *        - Niveau de gris de l'input
     *        - Floutage gaussien
     *        - Inversion
     *        - Augmentation du contraste + correction gamma
     *   - Fusion par Lumière Tamisée
     * @author florent
     *
     */
    La fusion par lumière tamisée est ici : http://subversion.developpez.com/pro...Operators.java


    Ensuite, il applique un filtre "Bleach by pass" qui désature l'image et augmente un peu le contraste
    http://subversion.developpez.com/pro...assPlugin.java

    Avec une lookup table définie ici :
    http://subversion.developpez.com/pro...ion.properties

  2. #22
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    468
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 468
    Points : 689
    Points
    689
    Par défaut
    Citation Envoyé par yan Voir le message
    Si tu as du RAW, c'est déjà du HDR. Tu peux déjà faire pas mal de chose.
    tu passe de 8 bits par pixel à 12 ou 14 bits.
    La comparaison est loin d'être aussi évidente que tu l'indiques.

    En 8 bits, l'intensité est enregistrée avec une correction gamma 0.45. Ce qui est bien plus riche en infirmation qu'un simple codage linéaire... sur le même nombre de bits.

    Citation Envoyé par millie Voir le message
    J'ai une question. Si les images ont la même vitesse d'obturation mais des ouvertures différentes. Quelqu'un a une idée de comment faire ? (en général, ça reste une idée à la con vu que la profondeur de champs est différente)
    L'ouverture... c'est un trou... une surface.

    La valeur donnée par l'ouverture est proportionnelle au rayon du diaphragme (trou).

    Donc la différence d'intensité lumineuse perçue est égale au carré de la différence des ouvertures.

    Par exemple pour F3 et F5 on a une différence d'intensité de 25/9 = 2,7777 soit 1,474 EV (log2(2,777))

    note : évidement c'est en supposant que le diaphragme est une figure parfaite ne se modifiant pas avec l'ouverture

  3. #23
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par ijk-ref Voir le message
    En 8 bits, l'intensité est enregistrée avec une correction gamma 0.45. Ce qui est bien plus riche en infirmation qu'un simple codage linéaire... sur le même nombre de bits.
    Pas forcement, tous dépend la ou tu as besoin d'information. Soit dans le claire, soit dans le sombre.

    Entre avoir la version 8 bits et le raw, je préfère le raw.
    Tu as beaucoup plus d'information. Par exemple les partie saturée en jpeg ne le sont pas forcément en raw. Pour transformer le raw en 8bit, l'appareil fait bien plus qu'un simple gamma. Il fait déjà un tone mapping complexe et la transformation est en générale locale et non globale.

    Y as de forte chance qu'avec un seule RAW tu as presque autant d'info que la fusion de trois jpeg.

    Pour fusionner plusieurs images pour augmenter la dynamique, y as de meilleurs résultats si tu linéarise la réponse du capteur.

  4. #24
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    468
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 468
    Points : 689
    Points
    689
    Par défaut
    Citation Envoyé par yan Voir le message
    Pas forcement, tous dépend la ou tu as besoin d'information. Soit dans le claire, soit dans le sombre.

    Entre avoir la version 8 bits et le raw, je préfère le raw.
    Ne me fais pas dire ce que je n'ai jamais dit !

    Bien sûr que le RAW est mieux ! Je dis juste que les 8 bits ne sont pas de simples 8 bits comparables aux 12/14 bits d'un Raw !
    Citation Envoyé par yan Voir le message
    Pour fusionner plusieurs images pour augmenter la dynamique, y as de meilleurs résultats si tu linéarise la réponse du capteur.
    Le comble ! C'est ce que je dis depuis le début !

    Mais reste un peu les pieds sur terre Si tu travailles avec un bridge/compact ordinaire faisant du Raw... t'auras besoin dans la plus part des cas d plusieurs pauses.

    Il n'y a pas de miracle, les petits capteurs "bruites" assez vites et pour avoir des ombres bien définies faudra bien une seconde photo.

  5. #25
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par ijk-ref Voir le message
    Ne me fais pas dire ce que je n'ai jamais dit !
    Dsl, on s'est pas compris. C'est juste une précision par rapport à la discutions :
    Tant que je n'aurais pas trouvé un bon moyen de faire du recalage d'image ... cela ne vaut pas trop le coup pour moi que j'implémente une technique d'algo HDR vu que je ne pourrais pas l'utiliser pour mes photos

    Citation Envoyé par ijk-ref Voir le message
    Je dis juste que le 8 bits n'est pas un simple 8 bits comparable aux 12/14 bits d'un Raw !
    Pour moi si. Que tu fasse n'importe quel transfo de 12/14 vers 8 bits, tu perd de l'info. Et un gamma ne va pas forcement te permettre d'avoir une information plus riche. Par exemple deux photos, on va dire deux extrêmes:
    1- une pièce sombre avec une petite fenêtre
    2- des nuages dans le ciel

    le même gamma ne te permet pas d'avoir la même richesse d'information dans l'image jpeg.

  6. #26
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    468
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 468
    Points : 689
    Points
    689
    Par défaut
    Citation Envoyé par yan Voir le message
    Pour moi si. Que tu fasse n'importe quel transfo de 12/14 vers 8 bits, tu perd de l'info. Et un gamma ne va pas forcement te permettre d'avoir une information plus riche.
    Evidement tu ne vas pas gagner de l'info ! Plus "riche" que sans corrections : c'est sûr et certains !!!

    Nous percevons la lumière de façon logarithmique et la correction gamma 0.45 en est une très bonne approximation.

    La correction permet justement de conserver le même rapport de détail dans les tons foncés et clairs. Là où une simple transformation linéaire détruirait toutes infos dans les ombres.

  7. #27
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par ijk-ref Voir le message
    Bien sûr que 8 bits en correction gamma 0.45 sont bien meilleurs que 8 bits sans correction !!!
    Pour afficher une images oui. Pour faire du tone mapping, pas pour moi.

    Nous percevons la lumière de façon logarithmique et la correction gamma en est une très bonne approximation.
    Justement ceci est une sorte de tone mapping.

    La correction permet justement de conserver le même rapport de détail dans les tons foncés et clairs. Là où une simple transformation linéaire détruirait les ombres.
    De manière globale. Pas locale.

    La plus part des algo de tone mapping son locale et/ou globale. Car l'oeil adapte de manière locale et globale. Sans parler de la chromatique qui n'est pas la même dans un endroit sombre et à la lumière. Et c'est de toutes cette information perdu que je parle. Et pour moi, rien ne dit que l'information perdu ne contenais pas plus de détailles que l'information gardée par cette transformation RAW -> JPEG.

    D'ailleurs (dit moi si je me trompe) le but de fusionner plusieurs images jpeg c'est surtout pour retrouver cette information perdu.

  8. #28
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    468
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 468
    Points : 689
    Points
    689
    Par défaut
    Citation Envoyé par yan Voir le message
    Pour afficher une images oui. Pour faire du tone mapping, pas pour moi.
    Fais un test et tu verras bien !

    - Convertis ton 14 bits linéaire en 8 bits linéaire et applique ton tone-mapping
    - Convertis ton 14 bits linéaire en 8 bits correction gamma 0.45 et applique ton tone-mapping - en re-linéarisant évidement la sortie.

    Il n'y a pas photo... tu seras rapidement fixé
    Citation Envoyé par yan Voir le message
    (...) Et pour moi, rien ne dit que l'information perdu ne contenais pas plus de détailles que l'information gardée par cette transformation RAW -> JPEG.
    Parce que je viens et tu viens aussi de l'expliquer ! L'information utile est liée à notre perception. Et celle-ci perçoit le rapport (non la différence) d'intensités. C'est pourquoi une correction logarithmique est forcement la meilleure des corrections ! La correction gamma en est une très bonne approximation et même meilleur pour les valeurs proches de zero.
    Citation Envoyé par yan Voir le message
    D'ailleurs (dit moi si je me trompe) le but de fusionner plusieurs images jpeg c'est surtout pour retrouver cette information perdu.
    Tu te trompes. La fusion c'est surtout pour retrouver des informations jamais enregistré dans un Raw.

    Par exemple si tu regardes un 400 Iso d'un bridge/compact, tu constateras sur un Jpeg que les zones foncées restent assez bruités... la Raw n'aurait rien amélioré de ce coté là.

    Ensuite c'est sûr le Jpeg est plus que limite et ne permet absolument pas de conserver toutes les valeurs utiles des bons appareils... et ceci avec le temps devrait être de plus en plus vrai pour beaucoup d'appareil...

    Cependant j'ai toujours comparé ce qui est comparable. J'ai seulement comparé du 8bits avec du 8bits. Et le Raw d'origine 14 bits reste évidement plus approprié pour ce genre de traitement !

  9. #29
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par ijk-ref Voir le message
    Parce que je viens et tu viens aussi de l'expliquer ! L'information utile est liée à notre perception. Et celle-ci perçoit le rapport (non la différence) d'intensités. C'est pourquoi une correction logarithmique est forcement la meilleure des corrections ! La correction gamma en est une très bonne approximation et même meilleur pour les valeurs proches de zero.
    c'est peut là où y as un truc que je ne comprend pas. C'est la volonté de préserver le sombre par rapport au claire. Par exemple pour une photo de nuage, je pense que cela devrais être l'inverse.
    Bien-sure je parle pour faire du tone mapping. Pour la visualisation de l'image cela est très bien.
    L'utilisation du jpeg c'est faire du tone mapping sur des données déjà tone-mappé.

    Tu te trompes. La fusion c'est surtout pour retrouver des informations jamais enregistré dans un Raw.
    je parlé de la fusion de jpeg. Pour la fusion de raw je suis tout à fait d'accord.

    Ce que je comprend c'est
    • la fusion de jpeg = reconstitution du raw (suppression du tone mapping de l'appareil photo)
    • la fusion de raw = reconstitution des détails dans le sombre et le claire

  10. #30
    Membre actif
    Inscrit en
    Juin 2008
    Messages
    189
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 189
    Points : 268
    Points
    268
    Par défaut
    Citation Envoyé par pseudocode Voir le message
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    				float slope0 = Math.abs(hsb0[2]-0)/(t0-0); 
    				float slope1 = Math.abs(hsb1[2]-hsb0[2])/(t1-t0); 
    				float slope2 = Math.abs(hsb2[2]-hsb1[2])/(t2-t1);
    Je viens de tilter. Mais c'est linéaire par rapport à la vitesse d'obturation (avec du sRGB) ?

    En gros, si on passe de 1/60 à 1/30. Si on a par exemple le canal rouge à 20/255 à 1/60, ça deviendrait 40/255 à 1/30 ? (au bruit près)

  11. #31
    Membre actif
    Inscrit en
    Juin 2008
    Messages
    189
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 189
    Points : 268
    Points
    268
    Par défaut
    Citation Envoyé par ijk-ref Voir le message
    Par exemple pour F3 et F5 on a une différence d'intensité de 25/9 = 2,7777 soit 1,474 EV (log2(2,777))

    note : évidement c'est en supposant que le diaphragme est une figure parfaite ne se modifiant pas avec l'ouverture
    Effectivement, je viens de voir la formule suivante : [ame]http://fr.wikipedia.org/wiki/Indice_de_lumination[/ame] que je ne connaissais pas.

  12. #32
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    468
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 468
    Points : 689
    Points
    689
    Par défaut
    Citation Envoyé par Jack Sparrow Voir le message
    En gros, si on passe de 1/60 à 1/30. Si on a par exemple le canal rouge à 20/255 à 1/60, ça deviendrait 40/255 à 1/30 ? (au bruit près)
    Non, non et non ! Je vais finir par vous punir !

    (((20/255)^(1/g))*2)^g = 27/255

    avec g = 1/2.2222222;

    L'espace sRGB n'est pas là pour seulement faire de la figuration !

    c'est le signal linéaire qui doit être multiplié par 2. Donc il faut linéariser l'entrée avant de pouvoir le multiplier par 2. Ensuite tu re-transformes le signal dans l'espace sRGB.

    Note : Dans le cas présenté on peut aussi écrire directement :

    20 * (2^g) = 27

  13. #33
    Membre actif
    Inscrit en
    Juin 2008
    Messages
    189
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 189
    Points : 268
    Points
    268
    Par défaut
    Citation Envoyé par ijk-ref Voir le message
    Non, non et non ! Je vais finir par vous punir !
    Je me disais bien que c'était trop suspect pour être linéaire.

    Avec cette discussion, je me suis rendu compte de plein de trucs essentiels en photographie. Voilà un avantage de glandouiller sur les forums dvp

  14. #34
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    468
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 468
    Points : 689
    Points
    689
    Par défaut
    Citation Envoyé par Jack Sparrow Voir le message
    Je me disais bien que c'était trop suspect pour être linéaire.

    Avec cette discussion, je me suis rendu compte de plein de trucs essentiels en photographie. Voilà un avantage de glandouiller sur les forums dvp
    En fait il y a aussi d'autres facteurs qui rentrent en compte... comme la saturation des couleurs...modifiant le résultat suivant la façon dont elle est appliquée sur tel ou tel appareil et suivant telle ou telle intensité... mais franchement il y a pas vraiment beaucoup de détails dessus.

    Déjà que pour la correction gamma ce n'est pas gagné...

  15. #35
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 084
    Points
    16 084
    Par défaut
    Citation Envoyé par Jack Sparrow Voir le message
    Je viens de tilter. Mais c'est linéaire par rapport à la vitesse d'obturation (avec du sRGB) ?

    En gros, si on passe de 1/60 à 1/30. Si on a par exemple le canal rouge à 20/255 à 1/60, ça deviendrait 40/255 à 1/30 ? (au bruit près)
    Non, comme ca a été dit ce n'est pas linéaire. Ce calcul me sert juste a trouver quelle image est la moins saturée (under/over), afin de pouvoir extrapoler les valeurs de la source lumineuse dans de bonnes conditions.

    Les valeurs s0, s1, s2 sont donc de simples indicateurs de saturation du capteur photo. On peut d'ailleurs s'en servir comme poids pour faire une moyenne pondérée des valeurs r/g/b.

    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    // if (s0+s1+s2) is not zero
    float r = (r0*s0+r1*s1+r2*s2)/(s0+s1+s2);
    float g = (g0*s0+g1*s1+g2*s2)/(s0+s1+s2);
    float b = (b0*s0+b1*s1+b2*s2)/(s0+s1+s2);
    Color.RGBtoHSB((int)r, (int)g, (int)b, image[x][y]);




    Dans l'idéal, il faudrait effectivement linéariser les valeurs RGB, puis repasser en sRGB à la fin. Mais comme je termine la conversion par une égalisation d'histogramme, ca n'a pas beaucoup d'influence au final.

  16. #36
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Bon, j'ai une meilleure version suite aux différentes remarques de cette discussion

    Les zones clairs mais non cramées dans l'image surexposée paraissent un peu fade.





    Le code est encore en mode carnage pour ainsi dire
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
     
    /**
     * 
     */
    package millie.plugins.core.hdr;
     
    import java.awt.Color;
    import java.awt.image.BufferedImage;
     
    import millie.plugins.PluginInfo;
    import millie.plugins.appimage.GenericAppImagePlugin;
    import millie.plugins.parameters.CheckBoxParameter;
    import millie.plugins.parameters.ImageParameter;
    import millie.plugins.parameters.IntSliderParameter;
    import millie.se.image.ImageProcessor;
    import millie.se.operator.FastGaussianBlurOperator;
    import millie.se.operator.GrayOperator;
    import millie.se.operator.GrayOperator.SelectedColor;
    import millie.se.operator.lut.LookupOperator;
    import millie.se.operator.lut.PredefinedLUT;
    import millie.util.ColorUtils;
     
    /**
     * @author millie
     *
     */
    @PluginInfo(name="HDR", category="Divers", description="HDR et tone mapping")
    public class HDRPlugin extends GenericAppImagePlugin {
    	public HDRPlugin() {
    		//setRefreshable(true);
    		setLongProcessing(true);
     
    		addParameter(new ImageParameter("mean", "Image Normal"));
    		addParameter(new ImageParameter("high", "Image surexposée"));
    		addParameter(new IntSliderParameter("rayon", "Rayon", 1, 100, 10));
    		addParameter(new IntSliderParameter("marge", "Marge", 0, 50, 10));
    		addParameter(new IntSliderParameter("force", "Force", -150, 150,0));
    		addParameter(new IntSliderParameter("highlight", "Ton Clair", -100, 100,0));
    		addParameter(new IntSliderParameter("gamma", "Gamma", -100, 100,0));
    		//addParameter(new IntSliderParameter("shadow", "Ton Foncé",    -100, 100,0));
    		addParameter(new CheckBoxParameter("pregamma", "Pregamma", false));
    		addParameter(new CheckBoxParameter("mask", "Voir le masque", false));
    	}
     
     
    	private double getGamma(int tGamma) {
    		double gamma = 0;
    		if(tGamma>=0) {
    			gamma = - tGamma / 100.0 + 1;
    		}
    		else {
    			gamma = -tGamma / 25.0 + 1;
    		}
    		return gamma;
    	}
     
    	/**
             * Compute an array of HSB colors
             *   [position][h/s/b position]
             * @param image
             * @return
             */
    	float[][] computeHSB(BufferedImage image) {
    		ImageProcessor proc = new ImageProcessor(image);
     
    		float[][] out = new float[image.getWidth()*image.getHeight()][3];
    		int[] pixels = proc.getPixels();
    		int[] rgbT = new int[3];
     
    		for(int pos = 0;pos<pixels.length;pos++)  {
    			int rgb = pixels[pos];
    			ColorUtils.getRGB(rgb, rgbT);
    			out[pos] = Color.RGBtoHSB(rgbT[0], rgbT[1], rgbT[2], null);
    		}
    		return out;
    	}
     
    	/**
             * Calcul le facteur tel que : 
             *    brightness1 ^ factor * 2^(-ev1) = brightness2 ^ factor * 2^(-ev2)
             *    
             *     => on prend une moyenne sur les valeurs ni cramées, ni sous exposées)
             */
    	double computeFactor(float[][] image1, float[][] image2, float ev1, float ev2, int marge) {
    		double factor = 0;
    		int count = 0;
    		marge+=10;
    		float margeInf = marge/255.0f;
    		float margeSup = 1-margeInf;
    		for(int pos = 0; pos<image1.length; pos++) {
    			float b1 = image1[pos][2];
    			float b2 = image2[pos][2];
    			//si l'une des couleurs est cramées ou sous exposés, on passe à la suite
    			if(b1>margeInf&&b1<margeSup&&b2>margeInf&&b2<margeSup&&Math.abs(b2-b1)>marge/255) {
    				count++;
    				factor+= 1.0/(Math.log(b1/b2));
    			}
    		}
    		if(factor!=0) {
    			factor = (-ev2+ev1) * Math.log(2) * factor;
    			factor/=count;
    		}
    		else {
    			factor = 0.45;
    		}
    		return factor;
    	}
    	float[][] computeHDR(BufferedImage low, BufferedImage mean, BufferedImage high, float evl, float evm, float evh, int marge) {
    		float[][] lowHSB = computeHSB(low);
    		float[][] meanHSB = computeHSB(mean);
    		float[][] highHSB = computeHSB(high);
    		int length = lowHSB.length;
     
    		//compute factor 
    		double factorLM = computeFactor(lowHSB, meanHSB, evl, evm, marge);
    		double factorMH = computeFactor(meanHSB, highHSB, evm, evh, marge);
    		double factorLMInv = 1.0/factorLM;
    		double factorMHInv = 1.0/factorMH;
     
    		double min=Double.MAX_VALUE, max=0;
     
    		//linearisation of brightness
    		float[][] out = new float[length][3];
    		for(int pos = 0;pos<length;pos++) {
    			double b1 = lowHSB[pos][2];
    			double b2 = meanHSB[pos][2];
    			double b3 = highHSB[pos][2];
     
    			b1 = Math.pow(Math.pow(b1, factorLM) * Math.pow(2, -evl), factorLMInv);
    			b3 = Math.pow(Math.pow(b3, factorMH) * Math.pow(2, -evh), factorMHInv);
     
    			double bmax = Math.max(Math.max(b1, b2),b3);
    			out[pos][2] = (float) bmax;
    			if(b1==bmax) {
    				out[pos][0] = lowHSB[pos][0];
    				out[pos][1] = lowHSB[pos][1];
    			}
    			if(b2==bmax) {
    				out[pos][0] = meanHSB[pos][0];
    				out[pos][1] = meanHSB[pos][1];
    			}
    			if(b3==bmax) {
    				out[pos][0] = highHSB[pos][0];
    				out[pos][1] = highHSB[pos][1];
    			}
    			// save min/max value
    			if (bmax>max) max=bmax;
    			if (bmax<min) min=bmax;
    		}
     
    		// stretch brightness in range [0,1]
    		for(int pos = 0;pos<length;pos++) 
    			out[pos][2] = (float) ((out[pos][2]-min)/(max-min));
     
    		return out;
    	}
     
    	@Override
    	public BufferedImage filter() throws Exception {
    		BufferedImage low = getInputImage();
    		double highlight = getGamma(getIntValue("highlight"));
    		//double shadow = getGamma(getIntValue("shadow"));
    		int marge = getIntValue("marge");
    		boolean seemask = getBooleanValue("mask");
    		boolean pregamma = getBooleanValue("pregamma");
     
    		BufferedImage mean = getImageValue("mean");
    		BufferedImage high = getImageValue("high");
     
    		if(high.getWidth()!=low.getWidth() || high.getHeight()!=low.getHeight())
    			throw new IllegalArgumentException("Images de tailles différentes");
    		if(mean.getWidth()!=low.getWidth() || mean.getHeight()!=low.getHeight())
    			throw new IllegalArgumentException("Images de tailles différentes");
     
    		float[][] hdr = computeHDR(low, mean, high, -1, 0, 1, marge);
     
     
     
    		//recompute brightness
    		BufferedImage out = new BufferedImage(mean.getWidth(), mean.getHeight(), mean.getType());
    		ImageProcessor proc = new ImageProcessor(out);
    		int[] pixels = proc.getPixels();
    		float[] mask = getMask(low, getIntValue("rayon"), getIntValue("force"), highlight);
    		double gamma = getGamma(getIntValue("gamma"));
    		double inv = 1.0/gamma;
    		for(int pos = 0;pos<hdr.length;pos++) {
    			double b = hdr[pos][2];
    			double pmask = mask[pos];
    			if(!seemask) {
    				if(pregamma)
    					b = Math.pow(b, inv);
    				b = softLight(b, pmask);
    				if(!pregamma)
    					b = Math.pow(b, inv);
    			}
    			else 
    				b = pmask;
    			if(b<0) b=0;
    			if(b>1) b=1;
     
    			pixels[pos] = Color.HSBtoRGB(hdr[pos][0], hdr[pos][1], (float) b);
    		}
    		proc.commit();
    		return out;
    	}
     
    	private float[] getMask(BufferedImage low, int rayon, int force, double highlight) {
    		BufferedImage mask = new GrayOperator(SelectedColor.ALL).compute(low);
    		//Blur mask
    		BufferedImage blur = new FastGaussianBlurOperator(rayon).compute(mask);
    		short[] contrastLut = PredefinedLUT.getContrastLUT(force);
    		short[] highlightLut = PredefinedLUT.getGammaLUT(highlight);
     
    		short[] enhancementLut = new short[256]; //build the new LUT
    		for(int color = 0; color<enhancementLut.length;color++)
    			enhancementLut[color] = contrastLut[highlightLut[255-color]]; //inversion + sigmoide
     
    		LookupOperator op = new LookupOperator(enhancementLut);
    		blur = op.compute(blur);
    		ImageProcessor proc = new ImageProcessor(blur);
    		int[] pixels = proc.getPixels();
     
    		float[] ret = new float[blur.getWidth()*blur.getHeight()];
    		for(int pos=0;pos<ret.length;pos++) 
    			ret[pos] = (pixels[pos]&0xFF)/255.0f;
    		return ret;
    	}
     
    	/**
             * compute a softLight fusion for 2 brightness entre 0 et 1 
             * 
             * @param f1
             * @param f2
             * @return
             */
    	static public double softLight(double f1, double f2) {
     
    		double out = 0;
    		if(f2<0.5)
    			out= f1-(1-2*f2)*f1*(1-f1);
    		else 
    			out = f1+(-1+2*f2)*(softLightD(f1)-f1);
    		return out;
    	}
     
     
    	static private double softLightD(double x) {
    		if(x<0.25) return ((16*x-12)*x+4)*x;
    		else return Math.sqrt(x);
    	}
     
    }

    En retouchant rapidement au piqué et au contraste local, on a ça :;

    Puis en forçant


    Ici, ça fait suspect, mais avec l'autre image, ça reste pas mal

Discussions similaires

  1. [ImageMagick] Optimisation lors de la création d'images ?
    Par dark_vidor dans le forum Bibliothèques et frameworks
    Réponses: 3
    Dernier message: 26/11/2005, 23h05
  2. [ImageMagick] Création d'image à la volée
    Par gdawirs dans le forum Bibliothèques et frameworks
    Réponses: 4
    Dernier message: 21/11/2005, 15h53
  3. [GD] recherche fonction de création d'images miniatures
    Par digger dans le forum Bibliothèques et frameworks
    Réponses: 3
    Dernier message: 18/11/2005, 21h12
  4. Création d'images 3d
    Par smyley dans le forum Autres Logiciels
    Réponses: 8
    Dernier message: 08/10/2005, 16h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo