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 :

Détermination d'une couleur contrastée


Sujet :

Traitement d'images

  1. #21
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 000
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 000
    Points : 15 487
    Points
    15 487
    Par défaut
    Citation Envoyé par wiwaxia Voir le message
    Bravo pour la palette !
    Bravo pour ta formule magique !

    Ce matin j'ai rajouté une 7e colonne (!) noir->blanc, et une option pour avoir des couleurs aléatoires dans les 6 autres.
    Ça donne ce qui suit, ce qui est moche c'est que l'aléatoire n'a pas l'air au mieux de sa forme (colonne 5 zone "vert d'eau", il n'y a que le rouge qui varie, et régulièrement -- bah, si quelqu'un a une idée c'est bien, sinon c'est pas grave du tout) :
    Nom : randomcolors.png
Affichages : 513
Taille : 38,3 Ko

    Le code (les machins qui commencent par jp ou my, c'est mes fonctions perso, vous virez ces préfixes et c'est tout bon -- sous Lazarus) :
    Code pascal : 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
    function CalculeLwithWiwaxia(R,G,B: byte):integer;
    var
      tmp: float;
    begin
      tmp := trunc( ( 0.297 * power((R + 14),2.4))
                  + (         power((G + 14),2.4))
                  + ( 0.101 * power((B + 14),2.4)) );
      Result := round(tmp / 10000);
    end;
     
    procedure TMainForm.rdgDistribColorsSelectionChanged(Sender: TObject);
    begin
      sg7cols.Invalidate;
    end;
     
    procedure TMainForm.sg7colsPrepareCanvas(sender: TObject; aCol, aRow: Integer;
      aState: TGridDrawState);
    begin
      Randomize;
      with sg7cols.Canvas do begin
        case rdgDistribColors.ItemIndex of
        0:
          case aCol of
            0:Brush.Color:=jpRGBtoColor(255, aRow*16, 0);     // rouge -> jaune
            1:Brush.Color:=jpRGBtoColor(255-aRow*16, 255, 0); // jaune -> vert
            2:Brush.Color:=jpRGBtoColor(0, 255, aRow*16);     // vert -> cyan
            3:Brush.Color:=jpRGBtoColor(0, 255-aRow*16, 255); // cyan -> bleu
            4:Brush.Color:=jpRGBtoColor(aRow*16, 0, 255);     // bleu -> magenta
            5:Brush.Color:=jpRGBtoColor(255, 0, 255-aRow*16); // magenta -> rouge
            6:Brush.Color:=jpRGBtoColor(aRow*16, aRow*16, aRow*16);// N->Blanc
          end;
        1:
          case aCol of
            0:Brush.Color:=Random(jpColorToInteger(jpRGBtoColor(255, aRow*16, aCol)));
            1:Brush.Color:=Random(jpColorToInteger(jpRGBtoColor(255-aRow*16, 255, aCol)));
            2:Brush.Color:=Random(jpColorToInteger(jpRGBtoColor(aCol, 255, aRow*16)));
            3:Brush.Color:=Random(jpColorToInteger(jpRGBtoColor(aCol, 255-aRow*16, 255)));
            4:Brush.Color:=Random(jpColorToInteger(jpRGBtoColor(aRow*16, aCol, 255)));
            5:Brush.Color:=Random(jpColorToInteger(jpRGBtoColor(255, aCol, 255-aRow*16)));
            6:Brush.Color:=jpRGBtoColor(aRow*16, aRow*16, aRow*16);// N->Blanc
          end;
        end;
        FillRect(sg7cols.CellRect(aCol, aRow));
      end;
    end;
     
    procedure TMainForm.sg7colsDrawCell(Sender: TObject; aCol, aRow: Integer;
      aRect: TRect; aState: TGridDrawState);
      function ContrastedColor(InColor: TColor): TColor;
      var
        H,S,L, Ltmp: float;
        R,G,B: byte;
      begin
        jpColorToHSL(InColor, H,S,L);
        jpColorToRGB(InColor, R,G,B);
        Ltmp:=CalculeLwithWiwaxia(R,G,B);
        //if (Ltmp <= 25) then L := 1 else L := 0;
        if (Ltmp <= coeff) then L := 1 else L := 0; // avec trackbar
        Result := myHSLtoColor(H,S,L);
      end;
    begin
      with sg7cols do with Canvas do begin
        Font.Color := ContrastedColor(Brush.Color);
        TextOut(CellRect(aCol, aRow).Left+10, CellRect(aCol, aRow).Top+4, 'test');
      end;
    end;
    Enjoy !

    EDIT : j'ai rajouté un trackbar qui va de 0 à 88 pour jouer sur le coeff de basculement Noir/Blanc, ce qui est rigolo c'est qu'à 0 (zéro), les deux cellules les plus sombres ne basculent pas :
    Code pascal : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TMainForm.trkCoefChange(Sender: TObject);
    begin
      coeff := trkCoef.Position;
      sg7cols.Invalidate;
    end;
    Nom : trackbarà0.png
Affichages : 343
Taille : 10,1 Ko
    alors qu'à 88 tout le monde bascule, dans l'autre sens.
    Ça doit être ce dont tu parlais avant-hier, wiwaxia, cette histoire de mauvaise réponse dans les très basses lumières. Bah...

  2. #22
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut Détermination d'une couleur contrastée
    Bonjour,

    Tu t'es apparemment lancé dans des calculs de luminance, sur des couleurs proches de celles des sommets du cube (rvb), en suivant - bonne idée - l'ordre décroissant des grandeurs calculées.
    Citation Envoyé par Jipété Voir le message
    Et la première ligne je lui ai tordue le coup comme ça :
    Code pascal : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // Rouge, Verte et Bleue sont mes variables sur 8 bits
    L1 := ( (0.297 * power((Rouge + 14), 2.4)) 
          + (        power((Verte + 14), 2.4)) 
          + (0.101 * power((Bleue + 14), 2.4)) );
    Au final, en scrutant des patches de couleurs R G B Y C M avec un ColorPicker maison, j'en ai sorti ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    blanc : 948227
    jaune : 879778
    cyan  : 746947
    verte : 678498
    magent: 270516
    rouge : 202067
    bleue :  69236
    noire :    787
    mais je ne sais pas quoi en faire...
    Et d'abord, sont-ce les bonnes valeurs (je veux dire, sont-elles dans les clous, dans ce qu'on est supposé obtenir) ?
    On verra après pour quand Icoul < 10...
    Rien à redire aux résultats, dont les valeurs sont proches des limites que j'ai calculées, à l'exception de la dernière qui devrait être nulle par définition: tu as utilisé la formule simplifiée là où elle est totalement invalide, et trouvé L = 948228*(14/269)2.4 = 787 .

    # D'abord le calcul littéral, qui n'a pas provoqué un enthousiasme irrésistible:
    Citation Envoyé par Jipété Voir le message
    Envoyé par wiwaxia: ... et sa résolution ne pose plus de difficulté.
    Parle pour toi
    On envisage donc les sept couleurs - autres que le noir, sans intérêt - dont les composantes non nulles sont égales et données par la relation: (r, v, b) = (u*x, u*y, u*z) , avec (9 < u <= m = 255) et (x, y) et (z) valant (0) ou (1) à l'exclusion de tout autre valeur.
    Alors (et dans ce cas seulement) la luminance de la couleur considérée admet pour expression:
    L1c = (u + 14)2.4 * F(x, y, z) = s * L1max avec F(x, y, z) = (0.297 * x2.4 + y2.4 + 0.101 * z2.4) et L1max = 948228 (maximum absolu observé pour le blanc).
    La même couleur - caractérisée par le même triplet (x, y, z) - présente à son maximum d'éclat (u = m) la luminance maximale:
    L1cm = (m + 14)2.4 * F(x, y, z) , et l'on obtient par le rapport des quantités correspondantes:

    (s * L1max) / L1cm = (u + 14)2.4 / (m + 14)2.4 , soit encore:

    (u + 14) / 269 = (s * L1max / L1cm)(5/12) , d'où l'expression finale de (u), qui dépend du seuil (s) que l'on s'est donné:

    u = 269 * (s * L1max / L1cm)(5/12) - 14 , et qui doit (rappelons-le) vérifier les conditions: (9 < u <= m = 255).

    # Et c'est là que cela se gâte, lorsqu'on s'avise de passer aux valeurs numériques; j'ai repris tes résultats, et complété le tableau:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
                                    L1cm    u (A)   u (B)
    blanc :     948227	(1,1,1)	948228	10.000	76.003
    jaune :     879778	(1,1,0)	879722	10.762  78.86
    cyan  :     746947	(0,1,1)	746780	12.512	85.42
    verte :     678498      (0,1,0) 678274	13.596	89.487	
    magenta :   270516	(1,0,1)	269953	26.510  137.92
    rouge :     202067	(1,0,0)	201448	31.765	157.62
    bleue :     69236	(0,0,1)	68506	57.732	255.00
    noir :        787	(0,0,0)	0 par def.	
    
    (A): calcul pour s = 0.003028 = (L1cm / L1max)*(10 + 14)2.4/(m + 14)2.4 = (24/269)2.4
    (B): calcul pour s = 68506/948228 = 0.07225
    L'écart entre les luminances extrêmes est si grand (Lmblanc/Lmbleu = 13.8) qu'il est difficile de trouver un seuil accessible à toutes les nuances de couleurs envisageables, définies par les couples (r/(r+v+b) , b/(r+v+b)); le domaine est restreint aux valeurs limites:
    a) s1 = 3.03E-3 correspondant au gris très sombre (10, 10, 10);
    b) s2 = 7.23E-2 correspondant au bleu pur (0, 0, 255).
    Je vois mal comment utiliser en pratique, sur le domaine entier des couleurs, la luminance comme critère de distinction entre teintes claires et sombres, bien qu'elle se rattache à une étude approfondie de la sensibilité de l'oeuil; et l'on comprend la déception de l'auteur du sujet:
    Citation Envoyé par sevyc64 Voir le message
    Il n'y a pas apparemment de formules magiques.
    De ce que j'ai testé, perso, c'est la formule donnée par wiwaxia au post 11 qui est la moins mauvaise, mais elle donne quand même quelques choix de couleurs pas très heureux ...
    Une étude empirique du contraste fournira des résultats plus rapides et plus sûrs - même s'ils sont plus flous.

    PS: fin du texte à reprendre (voir le message suivant).

  3. #23
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut Détermination d'une couleur contrastée
    Après un premier mouvement de déception dû à la lourdeur des calculs, je m'aperçois, en relisant la liste des valeurs maximales, que j'ai fait preuve d'un pessimisme excessif: la médiane L = (1/2)*Lmax = 948228 / 2 = 474114 se situe après tout entre le 4me et le 5me terme, séparant ainsi les 4 couleurs principales les plus brillantes (blanc, jaune, cyan et vert) des 4 autres, ce qui est conforme au bon sens.
    Que le pourpre, le rouge et le bleu restent classés sombres quelle que soit la valeur des indices, cela n'est pas étonnant et l'on n'y peut finalement rien. Je m'accrochais hier à l'idée (fausse) que la surface d'équiluminance médiane (L(r, v, b) = 0.5*Lmax) devait absolument recouper les axes du repère dans l'intervalle [0 ; 255] - il n'en est rien, cela n'est vrai que pour le vert (v = 218).

    J'ai repris les calculs des indices, pour les couleurs principales, dans le cas où le seuil de luminance prend les valeurs:
    1) s = L1m(vert) / L1max = L1cm[4] / L1max = 678274 / 948228 = 0.7153 ;
    2) s / 1 / 2 ;
    3) s = L1m(pourpre) / L1max = L1cm[5] / L1max = 269953 / 948228 = 0.2847 .
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Blanc_ : 219.95 _ 187.52 _ 145.37
    Jaune_ : 227.38 _ 193.92 _ 150.43
    Cyan__ : 244.43 _ 208.61 _ 162.05
    Vert__ : 255.00 _ 217.71 _ 169.25
    Pourpre: 380.88 _ 326.15 _ 255.00
    Rouge_ : 432.10 _ 370.27 _ 289.89
    Bleu__ : 685.23 _ 588.31 _ 462.32
    On dispose ainsi d'un domaine large et raisonnable (de 28.5 à 71.5 %) pour choisir la valeur du seuil (s).

  4. #24
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 000
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 000
    Points : 15 487
    Points
    15 487
    Par défaut
    Citation Envoyé par wiwaxia Voir le message
    On dispose donc d'un domaine large et raisonnable (de 28.5 à 71.5 %) pour choisir la valeur du seuil (s).
    Je me doutais que tu allais encore nous balancer une tripotée de calculs, , alors j'ai suivi mon petit bonhomme de chemin, et ça donne le gif ci-dessous dont les images sont longues à changer, pour avoir le temps de les voir : 3 secondes !
    Et il y a 3 séries qui se suivent :
    - d'abord le fond avec les dégradés déjà présentés et la variation de 0 à 88 grâce à un curseur ;
    - ensuite un fond aléatoire avec la même variation du seuil, de 0 à 88 ;
    - et enfin, des fonds aléatoires pour un seuil qui ne varie pas, calé à 25.

    Nom : master.gif
Affichages : 978
Taille : 881,4 Ko

    Vous voulez le code ? Toujours en Lazarus :
    Code pascal : 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
    uses types, math, unit4colors;
     
    { TForm1 }
     
    //// http://www.festra.com/wwwboard/messages/12892.html ////
    var
      FG: array of array of TColor;
      BG: array of array of TColor;
      FG2: array of array of TColor;
      RDM: array of array of TColor;
     
    procedure TForm1.FormCreate(Sender: TObject);
    var
      Col, Row: integer;
    begin
      // Set the sizes of the arrays
      SetLength(FG, Grid.ColCount, Grid.RowCount);
      SetLength(BG, Grid.ColCount, Grid.RowCount);
      // Initialize with default colors
      for Col := 0 to Grid.ColCount - 1 do begin
        for Row := 0 to Grid.RowCount - 1 do begin
          FG[Col, Row] := clBlack;
          BG[Col, Row] := clWhite;
        end;
      end;
      // original dessus
      // mes ajouts dessous
      coeff := trkbCoeff.Position;
     
      grid2.RowCount:=16;
      // Set the sizes of the arrays
      SetLength(FG2, Grid2.ColCount, Grid2.RowCount);
      SetLength(RDM, Grid2.ColCount, Grid2.RowCount);
      // Initialize with default colors
      for Col := 0 to Grid2.ColCount - 1 do
        for Row := 0 to Grid2.RowCount - 1 do
          case Col of
            0:FG2[Col, Row] := jpRGBtoColor(255, Row*16, 0);     // rouge -> jaune
            1:FG2[Col, Row] := jpRGBtoColor(255-Row*16, 255, 0); // jaune -> vert
            2:FG2[Col, Row] := jpRGBtoColor(0, 255, Row*16);     // vert -> cyan
            3:FG2[Col, Row] := jpRGBtoColor(0, 255-Row*16, 255); // cyan -> bleu
            4:FG2[Col, Row] := jpRGBtoColor(Row*16, 0, 255);     // bleu -> magenta
            5:FG2[Col, Row] := jpRGBtoColor(255, 0, 255-Row*16); // magenta -> rouge
            6:FG2[Col, Row] := jpRGBtoColor(Row*16, Row*16, Row*16);// N->Blanc
          end;
      PrepareRandom;
    end;
     
    procedure TForm1.gridDrawCell(Sender: TObject; aCol, aRow: Integer;
      aRect: TRect; aState: TGridDrawState);
    var
      S: string;
    begin
      S := Grid.Cells[ACol, ARow];
      // Fill rectangle with colour
      Grid.Canvas.Brush.Color := BG[ACol, ARow];
      Grid.Canvas.FillRect(aRect);
      // Next, draw the text in the rectangle
      Grid.Canvas.Font.Color := FG[ACol, ARow];
      Grid.Canvas.TextOut(aRect.Left + 2, aRect.Top + 2, S);
    end;
     
    procedure TForm1.gridClick(Sender: TObject);
    var
      Col, Row: integer;
      Color1, Color2, Color3: byte;
    begin
      Col := Grid.Col;
      Row := Grid.Row;
      // Calculate contrasting random colours
      Color1 := 200 + Random(56);
      Color2 := 200 + Random(56);
      Color3 := 100 + Random(156);
      BG[Col, Row] := RGBtoColor(Color1, Color2, Color3);
      FG[Col, Row] := RGBtoColor(255 - Color3, 255 - Color1, 255 - Color2);
      // Set the text to be displayed
      Grid.Cells[Col, Row] := 'clicked';
    end;
    //// http://www.festra.com/wwwboard/messages/12892.html ////
    ////////////////////////////////////////////////////////////////////////////////
     
    procedure TForm1.PrepareRandom;
    var
      Col, Row: integer;
    begin
      Randomize;
      SetLength(RDM, Grid2.ColCount, Grid2.RowCount);
      // Initialize with default colors
      for Col := 0 to Grid2.ColCount - 1 do
        for Row := 0 to Grid2.RowCount - 1 do
          RDM[Col, Row] := random(16777216);
    end;
     
    procedure TForm1.grid2PrepareCanvas(sender: TObject; aCol, aRow: Integer;
      aState: TGridDrawState);
    begin
      with grid2 do with Canvas do
        case rdgMode.ItemIndex of
          0: begin Brush.Color := FG2[aCol, aRow]; FillRect(CellRect(aCol, aRow)); end;
          1: begin Brush.Color := RDM[aCol, aRow]; FillRect(CellRect(aCol, aRow)); end;
        end;
    end;
     
    procedure TForm1.rdgModeClick(Sender: TObject);
    begin
      grid2.Repaint;
    end;
     
    procedure TForm1.trkbCoeffChange(Sender: TObject);
    begin
      coeff := trkbCoeff.Position;  grid2.Repaint;
    end;
     
    procedure TForm1.btnNewRndClick(Sender: TObject);
    begin
      SetLength(RDM, 0, 0);  PrepareRandom;  grid2.Repaint;
    end;
     
    function CalculeLwithWiwaxia(R,G,B: byte):integer;
    var
      tmp: float;
    begin
      tmp := trunc( ( 0.297 * power((R + 14),2.4))
                  + (         power((G + 14),2.4))
                  + ( 0.101 * power((B + 14),2.4)) );
      Result := round(tmp / 10000);
    end;
     
    procedure TForm1.grid2DrawCell(Sender: TObject; aCol, aRow: Integer;
      aRect: TRect; aState: TGridDrawState);
      function ContrastedColor(InColor: TColor): TColor;
      var
        H,S,L, Ltmp: float;
        R,G,B: byte;
      begin
        jpColorToHSL(InColor, H,S,L);
        jpColorToRGB(InColor, R,G,B);
        Ltmp:=CalculeLwithWiwaxia(R,G,B);
        if (Ltmp <= coeff) then L := 1 else L := 0;
        Result := myHSLtoColor(H,S,L);
      end;
    begin
      with grid2.Canvas do begin
        Font.Color := ContrastedColor(Brush.Color);
        TextOut(grid2.CellRect(aCol, aRow).Left+10, grid2.CellRect(aCol, aRow).Top+4, 'test');
      end;
    end;
    Toujours le même topo avec les préfixes jp et my à virer, et ceux qui mettront ça dans du Delphi auront un poil d'adaptation à faire (genre remplacer aRect par Rect).

  5. #25
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut
    Vraiment bien, l'image aléatoire !
    Il faut que je me mette à Lazarus.
    Quel seuil as-tu pris pour le changement blanc/noir ?

  6. #26
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 000
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 000
    Points : 15 487
    Points
    15 487
    Par défaut
    Citation Envoyé par wiwaxia Voir le message
    Vraiment bien, l'image aléatoire !
    Merci merci

    Citation Envoyé par wiwaxia Voir le message
    Il faut que je me mette à Lazarus.
    'tention, c't'une bestiole capricieuse, avec des sautes d'humeur et un caractère parfois un peu tatillon...

    Citation Envoyé par wiwaxia Voir le message
    Quel seuil as-tu pris pour le changement blanc/noir ?
    Euh, j'ai utilisé le curseur qu'on voit en bas de l'image, variant de 0 à 88 pour les deux premières séries et fixé à 25 pour la troisième :
    quelque part dans la procédure de calcul : if (Ltmp <= coeff) then L := 1 else L := 0; et positionné par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TForm1.trkbCoeffChange(Sender: TObject);
    begin
      coeff := trkbCoeff.Position;  
      grid2.Repaint;
    end;
    Bon dimanche (et encore merci pour la "formule magique" )

  7. #27
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 000
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 000
    Points : 15 487
    Points
    15 487
    Par défaut
    Bonjour,

    J'ai un souci...
    Je me suis attaqué à ce qui n'était pas demandé, à savoir le texte dans la couleur opposée à la couleur de son contenant (je suis intéressé).

    En mode bourrin rapide, j'ai fait ça :
    Code pascal : 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
    procedure TForm1.grid2Click(Sender: TObject);
      function ContrastedColor(InColor: TColor): TColor;
      var
        H,S,L, Htmp,Stmp,Ltmp: float; // H varie de 0 à 1 pour 0° à 360°
        R,G,B: byte;
      begin
        jpColorToHSL(InColor, H,S,L);
        jpColorToRGB(InColor, R,G,B);
    caption := floattostr(H)+' - '+floattostr(S)+' - '+floattostr(L);
        case rdgColorMode.ItemIndex of
          0: begin 
              Ltmp:=CalculeLwithWiwaxia(R,G,B); if Ltmp <= coeff then L:=1 else L:=0; 
          end;
          1: begin
              Htmp:=H+0.5; if Htmp > 1 then H:=Htmp-1 else H:=Htmp;
              Stmp:=S+0.5; if Stmp > 1 then S:=Stmp-1 else S:=Stmp;
              Ltmp:=L+0.5; if Ltmp > 1 then L:=Ltmp-1 else L:=Ltmp;
          end;
        end;
    panel1.caption := floattostr(H)+' - '+floattostr(S)+' - '+floattostr(L);
        Result := myHSLtoColor2(H,S,L);
      end;
    begin
      with Grid2 do case rdgMode.ItemIndex of
        0: mmoTest.Color := FG2[Col, Row];
        1: mmoTest.Color := RDM[Col, Row];
      end;
      mmoTest.Font.Color := ContrastedColor(mmoTest.Color);
    end;

    qui fonctionne dans 80 % (à la louche) des cas, mais il y a des résultats curieux, parfois, comme par exemple sur cette image qui représente la bas de la grille en mode "random" et le texte en mode B/W grâce à la formule magique.
    J'ai rajouté en bas un mémo (mmoTest) pour faire office de zone de test et deux boutons-radio pour choisir.
    Nom : soucicouleur.png
Affichages : 408
Taille : 37,6 Ko

    Et comme on peut le voir, le texte est blanc avec la formule magique en mode B/W et très foncé (rgb 22 34 31, hsl 165 21 11) en mode couleur inverse du fond (rgb 225 89 115, hsl 347 70 61).
    Avec cette couleur de fond ce n'est pas trop gênant, mais j'ai eu d'autres cas plus problématiques...
    Par exemple ce couple avec le fond à rgb 74 8 254 hsl 256 99 51 et le texte à rgb 4 5 2 hsl 80 43 1.
    Nom : pas_glop.png
Affichages : 328
Taille : 2,7 Ko

    Comment améliorer ces rendus ?
    Le fond est très bleu (rgb 254, hsl 256), l'inversion a fonctionné (hsl 80 c'est jaune) mais le L à 1 plombe tout...

    Par ailleurs, le seuil de basculement B/W est très sensible, regardez (images réduites), à gauche réglé à 31 et à droite à 32, 1 point de plus et 3 textes noirs ont basculé, je les ai repérés à droite par des ronds rouges et je trouve que le basculement n'est pas très heureux pour la cellule orange (celle du bas) :
    Nom : compar3132.png
Affichages : 345
Taille : 20,7 Ko

  8. #28
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut Détermination d'une couleur contrastée
    Bonsoir,

    Quelques observations concernant les nombreuses informations que tu as données:

    1°) À propos de l'expression approchée de la luminance L(r, v, b): la première troncature est rendue inutile par la réduction importante du nombre de chiffres significatifs qui intervient ensuite; le codage de la fonction concernée
    Code pascal : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    function CalculeLwithWiwaxia(R,G,B: byte):integer;
    var tmp: float;
    begin
      tmp := trunc( ( 0.297 * power((R + 14),2.4))
                  + (         power((G + 14),2.4))
                  + ( 0.101 * power((B + 14),2.4)) );
      Result := round(tmp / 10000);
    end;
    pourrait se réduire à:
    Code pascal : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    begin
      tmp := ( 0.297 * power((R + 14),2.4))
             + (         power((G + 14),2.4))
             + ( 0.101 * power((B + 14),2.4));
      Result := round(tmp * 0.0001);
    end;
    et admet pour limite supérieure Round(94.8228) = 95; elle représente donc approximativement le seuil (s), exprimé en pourcentage.

    2°)
    Je me doutais que tu allais encore nous balancer une tripotée de calculs,
    Sans malice aucune. J'avais au départ beaucoup de mal à saisir la forme et l'emplacement des surfaces d'équation L(r, v, b) = Cte, d'où les premiers tâtonnements numériques. J'indiquerai plus loin (si j'en ai le temps) une mesure à prendre dans une telle situation.

    3°)
    ce qui est rigolo c'est qu'à 0 (zéro), les deux cellules les plus sombres ne basculent pas ... alors qu'à 88 tout le monde bascule, dans l'autre sens.
    Le problème, c'est le cas de l'égalité à la limite:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        if (Ltmp <= 25) then L := 1; // noir --> blanc -- 25 un peu au pif, à tuner mieux...
        if (Ltmp > 25) then L := 0; // blanc --> noir
    dont la probabilité n'est pas du tout négligeable dans le cas de ta fonction; et la faible sensibilité de cette dernière (au plus égale à 95) aggrave encore la situation; on trouve ainsi dans le cas des noirs les plus sombres (x, x, x):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Result := round( 787a * 0.0001) = 0          // pour (0, 0, 0)
    Result := round( 929a * 0.0001) = 0          // pour (1, 1, 1)
    Result := round(1085a * 0.0001) = 0          // pour (2, 2, 2)
              // ... / ...
    Result := round(2592a * 0.0001) = 0          // pour (9, 9, 9)
    Result := round(2871 * 0.0001)  = 0          // pour (10, 10, 10)
              // ... / ...
    Result := round(4905 * 0.0001)  = 0          // pour (16, 16, 16)
    Result := round(5306 * 0.0001)  = 1          // pour (17, 17,17)
    (a) valeur fausse, la relation ne s'appliquant pas aux faibles indices, inférieurs à (10); mais l'arrondi fait ici disparaître l'erreur.
    À seuil nul, tes instructions classent les 16 premiers noirs sombres, et tous les autres clairs.
    Pour la fonction initialement proposée L1(r, v, b), qui peut atteindre 948228, l'éventualité d'une égalité devient négligeable.

    4°)
    ... En mode bourrin rapide, j'ai fait ça :
    ... qui fonctionne dans 80 % (à la louche) des cas, mais il y a des résultats curieux, parfois, comme par exemple sur cette image ...
    ... mais j'ai eu d'autres cas plus problématiques ...
    ... Par ailleurs, le seuil de basculement B/W est très sensible ...
    Lorsque l'on déplace un tant soit peu une frontière (ici la luminance) départageant un ensemble de couleurs aléatoirement définies, un petit nombre d'entre elles se retrouve de l'autre côté, et d'une manière imprévisible: il n'y a là aucun dysfonctionnement du logiciel, j'ai testé les indices pour quelques exemples cités.
    Je reprendrai plus loin les détails.

  9. #29
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 000
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 000
    Points : 15 487
    Points
    15 487
    Par défaut
    Bonjour,

    (je réponds sans utiliser "Répondre avec citation", cette fonction ne fonctionne plus ce matin...)

    Concernant le 1er point, j'ai mis en application ta simplification, et de mon côté, ayant trouvé de la lecture
    https://imagej.nih.gov/ij/docs/menus/edit.html#memory
    The default weighting factors (0.299,0.587,0.114), which are based on human perception, are the ones used to convert from RGB to YUV, the color encoding system used for analog television

    https://fr.wikipedia.org/wiki/Couleur
    Dans ce modèle, utilisé en télévision, le blanc est composé de 29.9 % de rouge, 58,7 % de vert et 11,4 % de bleu.
    , j'ai voulu faire un test comme ça, en rajoutant une case à cocher (ckbxYUV) :
    Code pascal : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function CalculeLwithWiwaxia(R,G,B: byte):integer;
    var
      tmp: float;
    begin
      if Form1.ckbxYUV.Checked then // mode YUV
      tmp := ( 0.299 * power((R + 14),2.4))
           + ( 0.587 * power((G + 14),2.4))
           + ( 0.114 * power((B + 14),2.4))
      else // mode wiwaxia
      tmp := ( 0.297 * power((R + 14),2.4))
           + (         power((G + 14),2.4))
           + ( 0.101 * power((B + 14),2.4));
      Result := round(tmp * 0.0001);
    end;

    Il en ressort qu'avec le curseur de seuil à 0 toutes les cases ont le texte noir, et à 63 le dernier texte noir bascule à blanc : l'échelle est plus petite (0-63 vs 0-88) mais elle est complète.

    La grande question, c'est : d'où sors-tu ces nombres (0.297, 1, 0.101) ? J'ai fouillé le web, je trouve une page en rapport avec POVRay pour calculer le gris d'une couleur RGB, qui mélange les deux formules :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Try this macro:
    #macro Grayscale(Color)
        (0.297*Color.red + 0.589*Color.green + 0.114*Color.blue)
    #end
    Voilà (fouhhh, l'ergonomie du forum me fait souffrir, ça laggue depuis ce week-end c'est une horreur...)

  10. #30
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut
    1°)
    Citation Envoyé par Jipété Voir le message
    ... Il en ressort qu'avec le curseur de seuil à 0 toutes les cases ont le texte noir, et à 63 le dernier texte noir bascule à blanc : l'échelle est plus petite (0-63 vs 0-88) mais elle est complète ...
    J'ai déjà parlé de l'inconvénient d'une échelle trop réduite de valeurs entières.

    2°)
    Citation Envoyé par Jipété Voir le message
    ... La grande question, c'est : d'où sors-tu ces nombres (0.297, 1, 0.101) ?
    Tout simplement de la factorisation du plus fort coefficient (0.7152) attaché à la composante verte, afin que celle-ci se retrouve affecté du facteur (1) dans la fonction simplifiée servant de test. Voir le message #11 (14/01/2017, 13h43):
    Citation Envoyé par wiwaxia Voir le message
    ... Cette luminance relative est donnée par la combinaison linéaire: L = 0.2126 * R + 0.7152 * G + 0.0722 * B
    que l'on peut numériquement présenter sous la forme: L = 0.7152*(0.29726 * R + G + 0.10095 * B)
    et qui compte tenu de la simplification précédente deviendra:
    L = (0.7152/1.0552.4)*(0.29726 * (RsRGB + 0.055)2.4 + (GsRGB + 0.055)2.4 + 0.10095 * (BsRGB + 0.055)2.4) ,
    soit encore:
    L = K*(0.29726 * (R8bit + m)2.4 + (G8bit + m)2.4 + 0.10095 * (B8bit + m)2.4)
    avec m = 0.055 * 255 = 14.025 et K = (0.7152/1.0552.4/2552.4) = 1.0542E-6 ...
    ... On peut, à ce stade, se contenter d'une relation numérique raisonnablement allégée:
    L1 = (0.297 * (R8bit + 14)2.4 + (G8bit + 14)2.4 + 0.101 * (B8bit + 14)2.4) .
    3°)
    Citation Envoyé par Jipété Voir le message
    ... J'ai fouillé le web, je trouve une page en rapport avec POVRay pour calculer le gris d'une couleur RGB, qui mélange les deux formules :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Try this macro:
    #macro Grayscale(Color)
        (0.297*Color.red + 0.589*Color.green + 0.114*Color.blue)
    #end
    Référence curieuse, à creuser en amont. Mais ce bricolage qui bazarde les exposants (2.4), et donc la non-linéarité, ne me plaît pas beaucoup.

  11. #31
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 000
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 000
    Points : 15 487
    Points
    15 487
    Par défaut
    (ah, ça refonctionne...)
    Citation Envoyé par wiwaxia Voir le message
    3°)
    Référence curieuse, à creuser en amont. Mais ce bricolage qui bazarde les exposants (2.4), et donc la non-linéarité, ne me plaît pas beaucoup.
    Si on considère qu'un doigt s'est fait des nœuds entre le 9 et le 7 ((0.299, 0.587, 0.114) vs (0.297,0.589, 0.114)) chez POVRay en recopiant la formule, alors c'est celle de wikipédia, qui a peut-être été recopiée aussi par les gens d'ImageJ (qui n'ont pas l'air d'être des gamins), et si j'ai bien compris, ça vient des ingénieurs pour la conversion vers YUV.

    Mais j'ai le souvenir d'avoir vu/lu d'autres formules, que je n'arrive pas à retrouver...

  12. #32
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 000
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 000
    Points : 15 487
    Points
    15 487
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Il en ressort qu'avec le curseur de seuil à 0 toutes les cases ont le texte noir, et à 63 le dernier texte noir bascule à blanc : l'échelle est plus petite (0-63 vs 0-88) mais elle est complète.
    Je ne sais pas ce que j'ai changé (quand je regarde le code, je répondrais volontiers "rien !"), il n'empêche qu'à 0 maintenant j'ai encore 2 cases avec le texte noir, et que la bascule complète à blanc se fait à 60.
    Go figure...

  13. #33
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par Jipété Voir le message
    ... Si on considère qu'un doigt s'est fait des nœuds entre le 9 et le 7 ((0.299, 0.587, 0.114) vs (0.297,0.589, 0.114)) chez POVRay en recopiant la formule, alors c'est celle de wikipédia, qui a peut-être été recopiée aussi par les gens d'ImageJ (qui n'ont pas l'air d'être des gamins) ...
    Je n'irai pas jusque là, et je ne prétend pas qu'on ait affaire à des débiles ! Encore que parfois...
    Au fait, quel est lien concernant POV Ray ?

    Citation Envoyé par Jipété Voir le message
    ... et si j'ai bien compris, ça vient des ingénieurs pour la conversion vers YUV ...
    Bonne remarque, justement: il faudrait s'assurer du type de coordonnées en cause ... mais là, je n'en ai vraiment pas le temps.

    L'essentiel, c'est que l'expression de la luminance sur laquelle on échange dans cette discussion est la meilleure de toutes, du point de vue de la photométrie visuelle, et qu'après s'être donné la peine d'étudier et de coder la fonction, ce serait du gâchis que de la troquer contre une formule plus rudimentaire.

  14. #34
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 000
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 000
    Points : 15 487
    Points
    15 487
    Par défaut
    Citation Envoyé par wiwaxia Voir le message
    Au fait, quel est lien concernant POV Ray ?
    C'est là où j'ai trouvé cette macro de conversion RGB2Gray :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #macro Grayscale(Color)
        (0.297*Color.red + 0.589*Color.green + 0.114*Color.blue)
    #end
    EDIT : je viens de chercher un peu.
    Ici, Matlab utilise 0.2989 * R + 0.5870 * G + 0.1140 * B

    Là, Intel roule (moins précis que la précédente) avec Y' = 0.299 * R' + 0.587 * G' + 0.114 * B'

    Un Français (c'est reposant, fais une recherche dans la page sur NTSC) utilise la précédente et deux autres : Y = 0.2126 * rouge + 0.7152 * vert + 0.0722 * bleu (les valeurs utilisées par OpenCV sont Rouge : 0.212671, Vert : 0.715160, et Bleu : 0.072169) et luminosité = 0.34 * rouge + 0.5 * vert + 0.16 * bleu

    Et enfin là, avec les mêmes formules, il y a des images et des histogrammes, pour comparer

    Avec tout ça y a de quoi faire,

    EDITEDIT : et je ne résiste pas à poster l'aide de The Gimp à propos de l'outil de désaturation (c'est là qu'il y avait cette autre formule que je cherchais... Cette du milieu !) :

    Nom : gimphelp.jpg
Affichages : 335
Taille : 56,2 Ko

    Maintenant, la différence entre Lightness, Luminosity et Average Brightness, je crois qu'on n'est pas rendu...

  15. #35
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 000
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 000
    Points : 15 487
    Points
    15 487
    Par défaut
    Yep !

    Je suis parti des formules trouvées, j'ai pondu un truc viteuf, ça donne ça :
    Nom : compar5grayformulas.jpg
Affichages : 325
Taille : 33,2 Ko

    Légende :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    en haut à gauche <span style="font-family: monospace; padding: 2px; background: #ddd; display: inline-block">aGray := <span class="br0">(</span>Ri+Gi+Bi<span class="br0">)</span> <span style="color: #0080ff;">div</span> <span style="color: #cc66cc;">3</span>;</span>.
    en haut à droite <span style="font-family: monospace; padding: 2px; background: #ddd; display: inline-block">aGray := <span style="color: #0080ff;">round</span><span class="br0">(</span><span style="color: #cc66cc;">0.3</span>*Ri<span class="br0">)</span> + <span style="color: #0080ff;">round</span><span class="br0">(</span><span style="color: #cc66cc;">0.59</span>*Gi<span class="br0">)</span> + <span style="color: #0080ff;">round</span><span class="br0">(</span><span style="color: #cc66cc;">0.11</span>*Bi<span class="br0">)</span>;</span>.
    au milieu gauche <span style="font-family: monospace; padding: 2px; background: #ddd; display: inline-block">aGray := <span style="color: #0080ff;">round</span><span class="br0">(</span><span style="color: #cc66cc;">0.2126</span>*Ri<span class="br0">)</span> + <span style="color: #0080ff;">round</span><span class="br0">(</span><span style="color: #cc66cc;">0.7152</span>*Gi<span class="br0">)</span> + <span style="color: #0080ff;">round</span><span class="br0">(</span><span style="color: #cc66cc;">0.</span><span style="color: #cc66cc;">07</span><span style="color: #cc66cc;">22</span>*Bi<span class="br0">)</span>;</span>.
    au milieu droite<span style="font-family: monospace; padding: 2px; background: #ddd; display: inline-block"> aGray := <span style="color: #0080ff;">round</span><span class="br0">(</span><span style="color: #cc66cc;">0.299</span>*Ri<span class="br0">)</span> + <span style="color: #0080ff;">round</span><span class="br0">(</span><span style="color: #cc66cc;">0.587</span>*Gi<span class="br0">)</span> + <span style="color: #0080ff;">round</span><span class="br0">(</span><span style="color: #cc66cc;">0.114</span>*Bi<span class="br0">)</span>;</span>.
    en bas  wiwaxia, <span style="font-family: monospace; padding: 2px; background: #ddd; display: inline-block">aGray := <span style="color: #0080ff;">round</span><span class="br0">(</span> <span class="br0">(</span><span style="color: #cc66cc;">0.297</span>*power<span class="br0">(</span><span class="br0">(</span>Ri + <span style="color: #cc66cc;">14</span><span class="br0">)</span>,<span style="color: #cc66cc;">2.4</span><span class="br0">)</span> + power<span class="br0">(</span><span class="br0">(</span>Gi + <span style="color: #cc66cc;">14</span><span class="br0">)</span>,<span style="color: #cc66cc;">2.4</span><span class="br0">)</span> + <span style="color: #cc66cc;">0.101</span>*power<span class="br0">(</span><span class="br0">(</span>Bi + <span style="color: #cc66cc;">14</span><span class="br0">)</span>,<span style="color: #cc66cc;">2.4</span><span class="br0">)</span> <span class="br0">)</span>* <span style="color: #cc66cc;">0.</span><span style="color: #cc66cc;">00</span><span style="color: #cc66cc;">01</span><span class="br0">)</span>;</span>.
    Et si j'enlève le " * 0.0001 " dans la formule "magique" ça donne une image toute merdique avec des défauts, un vrai bazar non présentable.

  16. #36
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut
    Merci pour l'info sur POV Ray. L'ancienneté de la référence ( 30 Mar 2001) devrait cependant inciter à la prudence (cette remarque concerne d'ailleurs la plus grande partie de la littérature sur POV Ray).

    La documentation rassemblée est impressionnante, mais concerne un autre sujet: la conversion des couleurs en niveaux de gris. Cela ne concerne plus la luminance, mais n'est pas sans rapport avec cette notion.

    Je constate que les meilleurs résultats proviennent de la formule dont les coefficients respectent la préséance:
    Cvert > Crouge > Cbleu .

    Et si j'enlève le " * 0.0001 " dans la formule "magique" ça donne une image toute merdique avec des défauts, un vrai bazar non présentable.
    Je crois deviner ce que tu as voulu faire: arrange-toi pour que ta nouvelle fonction L(r, v, b) culmine à 255 en posant par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    CONST K = 255 / 948228;
    ...
    begin
      tmp := ( 0.297 * power((R + 14),2.4))
             + (         power((G + 14),2.4))
             + ( 0.101 * power((B + 14),2.4));
      Result := round(tmp * K);
    end;
    avant de poser r' = v' = b' = g = CalculeLwithWiwaxia(r, g, b) pour passer au gris.

    Je crois me rappeler la définition du niveau gris se fonde sur l'égalité des luminances: L(g, g, g) = L(r, v, b); il suffit donc d'inverser la fonction F(g) = L(g, g, g) pour obtenir le niveau de gris correspondant: g = F-1(L) .

  17. #37
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 227
    Points : 28 228
    Points
    28 228
    Par défaut
    Alors, comment dire, lorsque j'ai ouvert ce sujet, j'étais loin de me douter qu'il susciterait autant d’intérêts. Je m'attendais même à n'avoir aucune réponse concrete.
    D'autant plus que je pense que ce sujet doit se poser assez régulièrement à plusieurs développeurs. Ils trouveront ici nombre de réponses.

    Ne m'en voulez pas, je ne peux dire qui de l'un ou de l'autre à raison. Je vous suis, de loin, en survol, j'ai énormément de retard dans les tests de vos solutions. Ce que je retiens, c'est qu'effectivement la formule magique fantasmée n'existe pas. Mais vous vous êtes quand même pas mal rapproché d'un résultat proche de l'idéal.

    Continuez à faire avancer le schmilblick, je suis sur que ça servira à plus d'un.

    Quant à moi, lorsque je pourrais dégager une petite pause dans les projets en cours, faudra que je revienne par ici, pour tester et implanter une de vos solutions dans mes projets.


  18. #38
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 000
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 000
    Points : 15 487
    Points
    15 487
    Par défaut
    Yop !
    Citation Envoyé par sevyc64 Voir le message
    Alors, comment dire, lorsque j'ai ouvert ce sujet, j'étais loin de me douter qu'il susciterait autant d’intérêts. Je m'attendais même à n'avoir aucune réponse concrete.
    D'autant plus que je pense que ce sujet doit se poser assez régulièrement à plusieurs développeurs. Ils trouveront ici nombre de réponses.

    Ne m'en voulez pas, je ne peux dire qui de l'un ou de l'autre à raison. Je vous suis, de loin, en survol, j'ai énormément de retard dans les tests de vos solutions. Ce que je retiens, c'est qu'effectivement la formule magique fantasmée n'existe pas. Mais vous vous êtes quand même pas mal rapproché d'un résultat proche de l'idéal.

    Continuez à faire avancer le schmilblick, je suis sur que ça servira à plus d'un.
    T'imquiètes, il y a des sujets comme ça (l'ami wiwaxia en sait quelque chose ) qui font marcher les neurones, c'est excellent pour ne pas vieillir et il se trouve qu'en ce moment je bricole un document avec beaucoup d'images NB sur lesquelles je dois appliquer des textes, un peu l'inverse de ton histoire, mais les principes restent les mêmes : lisibilité maximum donc contraste à fond.

    Mais sur un fond plein de gris variables, va le trouver ! M'en suis sorti en utilisant deux calques du même texte, un en couleur claire l'autre en couleur foncée et décalés en hauteur et en largeur de 1 px et ma foi, ça le fait pas mal :
    Nom : restaurant.png
Affichages : 317
Taille : 11,6 Ko

    Quant au reste, au gros morceau, voici une belle image :
    Nom : compar9patches.png
Affichages : 331
Taille : 35,4 Ko

    Citation Envoyé par wiwaxia Voir le message
    Merci pour l'info sur POV Ray. L'ancienneté de la référence ( 30 Mar 2001) devrait cependant inciter à la prudence.
    Pour comparer, j'ai mis côte à côte 0.299 0.587 et 0.297 0.589 sur la deuxième rangée, images 2 et 3 : il n'y a pas une énorme différence, je n'ai trouvé que deux patches différents (ou alors il aurait fallu écrire une moulinette pour analyser tous les patches un par un, un peu la flemme, là, donc sondages par ColorPicker) :
    1re colonne 1re rangée, 2e image 75 3e image 76
    5e colonne dernière rangée, 2e image 100 3e image 101

    Citation Envoyé par wiwaxia Voir le message
    Je constate que les meilleurs résultats proviennent de la formule dont les coefficients respectent la préséance:
    Cvert > Crouge > Cbleu .
    Et donc les images à jeter sont les deux de la 1re ligne et les deux... tiennes (dernière ligne),
    2 tiennes car il y en a une dont j'ai trafiqué la formule (celle de droite, en lui rajoutant du vert) ce qui, curieusement, n'impacte pas les résultats lus au ColorPicker.

    J'avais déjà signalé que les 96 patches de départ ont tous la même valeur de L quand ils sont lus en mode HSL : ceci impacte sans doute ce qui précède.

    Faudrait maintenant que je me trouve une image "réelle", de la vraie vie, pour la passer dans ces moulinettes.

    D'un autre côté, il y a plein de gens très pointus (les ingé. de la télévision NB) qui se sont pris la tête avec tout ça il y a déjà longtemps, je me demande si on ne perd pas notre temps à réinventer la roue...

    'fin bon, si certains veulent en savoir plus, c'est très simple : un nouveau projet, un bouton, un TOpenPictureDialog, 10 TImage et roule ma poule :
    Code pascal : 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
    procedure TForm1.btnGraycompareClick(Sender: TObject);
    var
      i: integer;
      Ri,Gi,Bi: byte;
      aGray: byte;
      bmp: TBitmap;
      // les TImage's sur la fiche :
      // src 8 1
      //   3 6 4
      //   2 7
      //   5 9
      function ReturnGray(index: integer): byte; // les formules
      CONST
        K = 255 / 948228; // 0.000268922664169
      begin
        case index of  // à adapter en fonction du nombre de formules à tester
          8: Result := round(0.5*(max(max(Ri,Gi),Bi)+min(min(Ri,Gi),Bi))); // Lightness Gimp
          1: Result := (Ri+Gi+Bi) div 3; // Average Gimp
          3: Result := round(0.2127*Ri) + round(0.7152*Gi) + round(0.0722*Bi); // Luminosity Gimp (CIE 1931)
          6: Result := round(0.297 *Ri) + round(0.589 *Gi) + round(0.114 *Bi); // povray
          4: Result := round(0.299 *Ri) + round(0.587 *Gi) + round(0.114 *Bi); // matlab, télévision analogique
          2: Result := round(0.3   *Ri) + round(0.59  *Gi) + round(0.11  *Bi); // intel
          7: Result := round(0.34  *Ri) + round(0.5   *Gi) + round(0.16  *Bi); // utilisé par http://podeplace.blogspot.fr/
          5: Result := round( (0.297*power((Ri + 14),2.4) +       power((Gi + 14),2.4) + 0.101*power((Bi + 14),2.4) )* K);  // wiwaxia
          9: Result := round( (0.297*power((Ri + 14),2.4) + 0.589*power((Gi + 14),2.4) + 0.114*power((Bi + 14),2.4) )* K); // test jipété
        end;
      end;
     
      procedure ChangeToGray(idx: integer);
      var
        h,w: Integer;
        {$IFDEF WINDOWS}
        dst   :  pRGBTriple; // assumes pf24bit scanlines
        src   :  pRGBTriple; // assumes pf24bit scanlines
        {$ELSE}
        dst   :  pRGBQuad;   // assumes pf24bit scanlines
        src   :  pRGBQuad;   // assumes pf24bit scanlines
        {$ENDIF}
        FUNCTION RGBtoRGBTriple(CONST red, green, blue:  BYTE):  TRGBTriple;
        BEGIN
          WITH RESULT DO
          BEGIN
            rgbtRed   := red;
            rgbtGreen := green;
            rgbtBlue  := blue
          END
        END {RGBtoRGBTriple};
     
        FUNCTION RGBAtoRGBAQuad(CONST red, green, blue, reserved: BYTE): TRGBQuad;
        BEGIN
          WITH RESULT DO BEGIN
            rgbRed   := red;
            rgbGreen := green;
            rgbBlue  := blue;
            rgbReserved := reserved;
          END
        END {RGBAtoRGBAQuad};
      begin
        bmp.BeginUpdate();
        for h := 0 to ImageSrc.Height-1 do begin
          {$IFDEF WINDOWS}
          src := pRGBTriple(ImageSrc.Picture.Bitmap.RawImage.GetLineStart(h));
          dst := pRGBTriple(RawImage.GetLineStart(h));
          for w := 0 to ImageSrc.Width-1 do begin
            Ri := src[w].rgbtRed;
            Gi := src[w].rgbtGreen;
            Bi := src[w].rgbtBlue;
            aGray := ReturnGray(idx);
            dst[w] := RGBtoRGBTriple(aGray, aGray, aGray);
          end;
          {$ELSE}
          src := pRGBQuad(ImageSrc.Picture.Bitmap.RawImage.GetLineStart(h));
          dst := pRGBQuad(bmp.RawImage.GetLineStart(h));
          for w := 0 to ImageSrc.Width-1 do begin
            Ri := src[w].rgbRed;
            Gi := src[w].rgbGreen;
            Bi := src[w].rgbBlue;
            aGray := ReturnGray(idx);
            dst[w] := RGBAtoRGBAQuad(aGray, aGray, aGray, 255);
          end;
          {$ENDIF}
        end;
        bmp.EndUpdate();
        (Findcomponent('Image'+IntToStr(idx)) as TImage).Canvas.Draw(0,0,bmp);
      end;
     
      function LoadImageFromAnyFile(const aFilename: string): boolean;
      var
        pic: TPicture;
      begin
        Assert(FileExists(aFilename),'LoadImageFromAnyFile: non-existent file');
        pic := TPicture.Create;
        try
          pic.LoadFromFile(aFilename);
          imageSrc.Picture.Assign(pic);
          Result := not imageSrc.Picture.Bitmap.Empty;
        finally
          pic.Free;
        end;
      end;
     
    begin
      if opd.Execute then
        if LoadImageFromAnyFile(opd.FileName) then begin
          bmp:= TBitmap.Create;
          with bmp do begin
            PixelFormat := pf24bit;
            SetSize(ImageSrc.Width, ImageSrc.Height);
            for i := 1 to 9 do ChangeToGray(i); // à adapter en fonction du nombre de formules à tester
            Free;
          end;
        end;
    end;

    Les numéros du case dans la fonction ReturnGray sont un peu en désordre, c'est juste pour pouvoir comparer visuellement d'une manière trop cool

  19. #39
    Membre émérite

    Homme Profil pro
    Formation: Chimie et Physique (structure de la matière)
    Inscrit en
    Décembre 2010
    Messages
    1 333
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Formation: Chimie et Physique (structure de la matière)
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 333
    Points : 2 570
    Points
    2 570
    Billets dans le blog
    9
    Par défaut Détermination d'une couleur contrastée
    J'ai fait un peu de recherches sur la Toile, et la pelletée de formules récoltées en divers endroits ne m'a pas convaincu; entre autres ce que donne le lien donné par Jipété:
    Vous pouvez trouver en ligne plusieurs méthodes pour définir ce mélange des trois valeurs RGB. Par exemple, avec
    le format PAL/NTSC (utilisé par la télévision analogique), le niveau de luminance est défini comme ceci :
    Mélange RGB vers Gris (plus proche de la perception humaine)
    lum = 0.299 * rouge + 0.587 * vert + 0.114 * bleu

    La luminance est définie dans la norme CIE 1931 comme suit :
    Y = 0.2126 * rouge + 0.7152 * vert + 0.0722 * bleu

    (Les valeurs utilisées par OpenCV sont Rouge : 0.212671, Vert : 0.715160, et Bleu : 0.072169).
    Comme pour d'autres exemples accessibles sur internet, j'ai utilisé les valeurs suivantes :
    luminosité = 0.34 * rouge + 0.5 * vert + 0.16 * bleu

    Tous ces modèles prennent en compte la sensibilité de l’œil humain pour le vert.
    Qu'il existe des relations approchées pour certains logiciels, ou liées au fonctionnement de certains appareils (caméras, appareils photo, télévisions ...) soit.
    Mais une lecture attentive montre qu'un bon nombre de recettes du genre:
    Lum (luminance, luminosité, brillance ... ?) = Coeff1 * "Rouge" + Coeff2 * "Vert" + Coeff3 * "Bleu"
    résulte d'un confusion aussi euphorique que complète entre indices (r, v, b), grandeurs colorimétriques (x, y, z) et termes exponentiels comme le sympathique (IsRGB + 0.055)2.4 déjà rencontré.

    Donc veiller, là comme ailleurs, à rechercher des sites fiables, pour obtenir des informations de première main, ou tout au moins bien référencées. Je cite en vrac (la lecture n'est pas facile):
    https://fr.wikipedia.org/wiki/CIE_XYZ
    http://www.profil-couleur.com/ec/106b-espace-rvb.php
    https://fr.wikipedia.org/wiki/Niveau_de_gris
    https://en.wikipedia.org/wiki/Relative_luminance
    https://en.wikipedia.org/wiki/SRGB#T...transformation
    https://www.w3.org/WAI/GL/wiki/Relative_luminance

    Le dernier site est d'ailleurs celui qu'indiquait sevyc64, par le lien qu'il avait cité en début de forum; on y trouve la description la plus claire du calcul de la luminance relative.

    Nous avons d'ailleurs négligé la fin du texte, qui donne le critère d'un contraste suffisamment fort entre deux couleurs:
    Calculate the contrast ratio using the following formula: (L1 + 0.05) / (L2 + 0.05), where

    # L1 is the relative luminance of the lighter of the foreground or background colors, and

    # L2 is the relative luminance of the darker of the foreground or background colors.

    Check that the contrast ratio is equal to or greater than 7:1

  20. #40
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 000
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 000
    Points : 15 487
    Points
    15 487
    Par défaut
    Bonsoir,
    Citation Envoyé par wiwaxia Voir le message
    J'ai fait un peu de recherches sur la Toile, et la pelletée de formules récoltées en divers endroits ne m'a pas convaincu;
    C'est rigolo, mais c'est ce que je me disais aussi, en voyant la quantité de formules récoltées (j'ai trouvé un autre logiciel pointu de développement et de traitement d'images numériques, RawTherapee, qui utilise, lui aussi, 0.299*R + 0.587*G + 0.114*B -- est-ce que [presque] tout le monde se copie, ou est-ce vraiment la bonne formule ?), suite à moi aussi farfouillage webistique + avancement du Delmas et essais divers :
    Nom : compar_désatur_gimp.jpg
Affichages : 321
Taille : 73,9 Ko
    L'image n'est sans doute pas tip-top pour comparer des trucs et des machins, il n'empêche que je vois bien que les joues rondes de Titi sont plus sympathiques en mode "Luminosité" (c'est avec The Gimp et ses options que j'ai généré les trois images NB).

    Citation Envoyé par wiwaxia Voir le message
    Donc veiller, là comme ailleurs, à rechercher des sites fiables, pour obtenir des informations de première main, ou tout au moins bien référencées. Je cite en vrac (la lecture n'est pas facile):
    https://fr.wikipedia.org/wiki/CIE_XYZ
    http://www.profil-couleur.com/ec/106b-espace-rvb.php
    https://fr.wikipedia.org/wiki/Niveau_de_gris
    https://en.wikipedia.org/wiki/Relative_luminance
    https://en.wikipedia.org/wiki/SRGB#T...transformation
    https://www.w3.org/WAI/GL/wiki/Relative_luminance

    Le dernier site est d'ailleurs celui qu'indiquait sevyc64, par le lien qu'il avait cité en début de forum; on y trouve la description la plus claire du calcul de la luminance relative.
    Merci pour ces lectures, ça va m'occuper le week-end, je sens

    Citation Envoyé par wiwaxia Voir le message
    Nous avons d'ailleurs négligé la fin du texte, qui donne le critère d'un contraste suffisamment fort entre deux couleurs:
    Non non, juste que je considère qu'il me faut maîtriser les choses simples avant d'attaquer les compliquées, et comme j'ai d'autres chantiers sur le gaz en même temps et que les journées ne sont pas extensibles...

    À l'œil, dans ces petites images, c'est ta formule (en bas à gauche) qui donne le contraste max, on dirait :
    Nom : compar_titi.jpg
Affichages : 318
Taille : 45,1 Ko
    Revoir mon dernier post avec les formules relatives aux emplacements des résultats pour savoir qui fait quoi.

Discussions similaires

  1. Réponses: 2
    Dernier message: 08/06/2015, 14h03
  2. Calculer un bon contraste d'une couleur
    Par Cypselos dans le forum Traitement d'images
    Réponses: 11
    Dernier message: 20/11/2009, 18h16
  3. déterminer la "tonalité" d'une couleur.
    Par Alexdezark dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 17/10/2009, 11h24
  4. Déterminer si une image est en couleur
    Par ImagingAllthe dans le forum Images
    Réponses: 2
    Dernier message: 26/02/2008, 16h48
  5. String Grid et choix d'une couleur pour une ligne
    Par Gigottine dans le forum C++Builder
    Réponses: 12
    Dernier message: 17/05/2002, 16h23

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