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. #1
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 233
    Points : 28 261
    Points
    28 261
    Par défaut Détermination d'une couleur contrastée
    Bonjour,

    Je poste ici même si c'est pas le forum le plus dédié, c'est pas du traitement d'image à proprement parlé.
    En fait tous les forums pourraient être concernés.

    Dans un logiciel, j'ai un contrôle où l'utilisateur peut librement définir la couleur de fond (background). Comment et sur quels critères je peux automatiquement déterminer une couleur contrastée pour le text (Foreground) qui sera affiché dans ce contrôle.
    Je n'ai la couleur de fond que sous la forme RGB. Je me limiterais à 2, éventuellement 3 si nécessaire, couleurs de texte, à savoir Noir ou Blanc (3ème à déterminer si besoin).
    Ex : Si j'ai un bleu sombre, je prend blanc, mais si j'ai un bleu clair, je prend noir, rouge donne blanc, etc ....

    Existe-il des méthodes, des formules, quelque chose ?

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

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 233
    Points : 28 261
    Points
    28 261
    Par défaut
    Un lien m'a été donné sur le chat : https://www.w3.org/TR/WCAG20-TECHS/G17.html

    Çà ne donne pas la formule magique, mais ça donne quand même des explications. Je vais voir ce que je peux en tirer.

  3. #3
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 171
    Points : 9 662
    Points
    9 662
    Par défaut
    Bêtement, je ferais ça, c'est simple, et ça marche pas trop mal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    def fct_opposite(R,V,B):
      Si R < 128 alors R2 = 0 sinon R2=255
      Si V < 128 alors V2 = 0 sinon V2=255
      Si B < 128 alors B2 = 0 sinon B2=255
    Renvoyer (R2,V2,B2)
    Dans les faits, les échelles R V B ne sont pas perçues ""linéairement"" par l'oeil humain. Je m'explique : Si je remplace une couleur (R,V,B) par (R,V,B+10), l'oeil humain ne verra quasiment aucune différence si on est dans des couleurs sombres, alors qu'il verra une différence si on est dans des couleurs claires (en tout cas, j'ai l'impression que mon oeil réagit comme ça). Et l'oeil humain serait plus sensible à une différence V --> V+10 qu'à une différence B --> B+10 ... d'où l'intérêt des fonctions plus complexes exposées dans le lien en question.

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 050
    Points : 14 489
    Points
    14 489
    Par défaut
    Salut,
    Citation Envoyé par tbc92 Voir le message
    Bêtement, je ferais ça, c'est simple, et ça marche pas trop mal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    def fct_opposite(R,V,B):
      Si R < 128 alors R2 = 0 sinon R2=255
      Si V < 128 alors V2 = 0 sinon V2=255
      Si B < 128 alors B2 = 0 sinon B2=255
    Renvoyer (R2,V2,B2)
    Euh, ça serait pas l'inverse, plutôt ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    def fct_opposite(R,V,B):
      Si R > 128 alors R2 = 0 sinon R2=255
      Si V > 128 alors V2 = 0 sinon V2=255
      Si B > 128 alors B2 = 0 sinon B2=255
    Renvoyer (R2,V2,B2)
    Si rouge tend vers full alors rouge_opposé tend vers noir sinon tend vers full.

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

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 233
    Points : 28 261
    Points
    28 261
    Par défaut
    Le problème est que moi je vais me limiter à seulement 2 couleurs pour le texte, noir, et blanc.

    D'après les premiers tests, très très rapides, que j'ai fait par rapport au lien donné, j'obtiens pas toujours des résultats joyeux.

    J'ai pas encore regarder les autres propositions.

  6. #6
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 171
    Points : 9 662
    Points
    9 662
    Par défaut
    Dans ce cas, une solution 'basique' :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    def fct_opposite(R,V,B):
      Si R+V+B > 128*3 alors C2=Noir  sinon C2=Blanc 
      Renvoyer (C2)
    Si on veut rester très simple, mais se rapprocher de ce qui est dit sur ton lien, on peut faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Si R*0.2126+V*0.7152+B*0.0722 >  117 alors C2=Noir sinon C2=Blanc
    Mais ce qu'on peut noter, c'est que quand la couleur de fond est proche du gris (disons R entre 110 et 130, et idem pour G ; B a peu d'impact) alors ni le blanc ni le noir ne conviennent selon ton lien ; dans les 2 cas, l'écart de luminosité entre le fond et la police sont insuffisants.

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

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 233
    Points : 28 261
    Points
    28 261
    Par défaut
    Citation Envoyé par tbc92 Voir le message
    Dans ce cas, une solution 'basique' :
    Idem, ta formule ne marche pas pour toutes les couleurs. Par exemple, pour les couleurs RGB(1,247,89) et RGB(7,221,101), ça me donne du blanc alors que c'est des couleurs claires. De même pour la couleur RGB(137,61,189), ça me donne noir alors que c'est une couleur sombre.

    Plus je fais de tests et plus j'ai l'impression qu'il n'y a pas de formule magique pour trouver automatiquement la meilleure couleur de texte par rapport à celle du fond.


    EDIT : La dernière formule serait peut-être la moins mauvaise, mais elle fait pas de miracle non plus, pour certaines couleurs cça pas forcément la bonne couleur de text qui est choisie

  8. #8
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 171
    Points : 9 662
    Points
    9 662
    Par défaut
    Effectivement, sur les 2 premiers jeux de données proposées, ma formule 'basique' donne du blanc, alors que la 2ème formule donne du noir.
    Pourquoi n'utilises-tu pas cette 2ème formule ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Si R*0.2126+V*0.7152+B*0.0722 >  117 alors C2=Noir sinon C2=Blanc
    Ma formule archi-basique donne la même importance au bleu et au vert. Ton site donne en gros 10 fois plus d'importance au Vert qu'au bleu ; ça fait une différence énorme.

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

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 233
    Points : 28 261
    Points
    28 261
    Par défaut
    c'est ce que je dis dans l'édit, la seconde formule semble un peu moins mauvaise, elle corrige les 3 exemples mauvais avec ta formule basique, mais il y a d'autres jeux de couleur qui ne sont pas non plus joyeux. Certains d'ailleurs étaient, eux, correct avec ta formule basique.

    C'est pour ça que je commence à me dire que la formule magique n'existe pas, qu'il y aura toujours des couples malheureux, car je ne trouve aucune relation évidente, que ce soit dans l'évolution des valeurs RVB ou des valeurs HSB pour déterminer le seuil à partir duquel changer de couleur de texte.

  10. #10
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 171
    Points : 9 662
    Points
    9 662
    Par défaut
    Ce que veut Sevyx, c'est choisir soit noir, soit blanc. Et donc déterminer si la couleur en entrée est claire ou foncée.


    Si on se réfère au site donné, et qu'on l'applique à la lettre, ça va donner :

    Code : 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
     
    fonction opposite ( R,G,B)  // R,G,B sont entre 0 et 255
       R0 = R/255
       G0 = G/255
       B0 = B/255
     
       si R0 < 0.03928 alors R1 = R0/12.92 sinon R1 = ((R0+0.055)/1.055 ) ^2.4
       si G0 < 0.03928 alors G1 = G0/12.92 sinon R1 = ((G0+0.055)/1.055 ) ^2.4
       si B0 < 0.03928 alors B1 = B0/12.92 sinon R1 = ((B0+0.055)/1.055 ) ^2.4
     
       L = 0.2126 * R1 + 0.7152 * G1 + 0.0722 * B1
     
       L_Blanc = 1 
       L_Noir = 0
     
       Si (L_Blanc+0.05) /(L+0.05) > 7.1 alors Renvoyer Blanc   // Couleur franchement Sombre, on prend BLANC
       Si (L+0.05) /(L_Noir+0.05) > 7.1 alors Renvoyer Noir       // Couleur franchement Claire, on prend NOIR.
     
       // On est dans le cas où la couleur est intermédiaire, pas franchement claire, pas franchement foncée ; par défaut, on va choisir la couleur la moins mauvaise
     
       Si (L_Blanc+0.05) /(L+0.05) > (L+0.05) /(L_Noir+0.05) alors Renvoyer Blanc sinon Renvoyer Noir

  11. #11
    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
    Bonjour,

    Il y a plusieurs questions en cause:

    1°) Comment associer entre elles deux couleurs quelconques et suffisamment contrastées ? des fonctions discontinues telles que:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    IF (x<a) THEN y:= x + 255 - a          // avec 100 < a < 155 environ
             ELSE y:= x - a
    dont le graphe ne présente aucun point d'intersection sur [0 ; 255] avec la 1re bissectrice (y = x), donc aucun point stationnaire (F(x) = x) , devraient conduire à un contraste suffisamment marqué, puisque l'on aurait pour chacun des indices de couleur (r, v, b):
    |y - x| = a ou (255 - a) selon le domaine où l'on se trouve, donc |y - x| >= Min(a, (255 - a)) .
    Des perfectionnements sont possibles, mis ce n'est pas ici le sujet.

    2°) Si le résultat attendu se restreint aux extrêmes (blanc ou noir), les 2 droites précédentes seront remplacées par des paliers horizontaux:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    IF (x<a) THEN y:= 255         // avec 100 < a < 155 environ
             ELSE y:= 0
    C'est ce qui a déjà été proposé, mais reste à ce stade encore insuffisant parce que l'on obtiendrait selon la teinte de départ l'une des 8 couleurs simples correspondant aux 8 sommets du domaine cubique des indices (r, v, b); il faut donc caractériser la couleur initiale par une donnée unique, la "luminance relative" (je ne suis pas sûr que ma traduction soit correcte, mais peu importe).

    3°) Il faut alors se coltiner l'expression normalisée de cette fonction F(r, v, b), qui a impérativement besoin d'une cure d'amaigrissement.
    a) On remarque que la partie linéaire se restreint au domaine: IsRGB <= 0.03928 , soit encore:
    I8bit <= 255 * 0.03928 = 10.0164 ~ 10 ,
    limite en-dessous de laquelle la couleur devient indiscernable (et même bien au-dessus !); comme de plus on s'intéresse à les luminances moyennes, pour lesquelles le seuil critique est beaucoup plus élevé, nul besoin de cette expression conditionnelle; on vire donc l'alternative <IF ... THEN ... ELSE ...> .

    b) 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 .
    La luminance relative maximale (Lmax) est par définition égale à l'unité, et correspond au blanc le plus brillant (255, 255, 255).

    c) Enfin nul besoin de calculer l'expression complète, puisque l'on se contentera de la comparer au seuil arbitraire séparant les teintes sombres des claires; d'où la nouvelle grandeur proportionnelle à la précédente:
    L1 = (L / K) = (0.29726 * (R8bit + m)2.4 + (G8bit + m)2.4 + 0.10095 * (B8bit + m)2.4) ,
    qui admet pour valeur maximale: L1max = L1(255, 255, 255) = 948582 = (Lmax / K) = (1 / K) .

    Il suffira donc de reprendre l'algorithme initial en posant x = L1 et a ~ 500000 (limite à choisir).

    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) .

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Février 2011
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Février 2011
    Messages : 147
    Points : 180
    Points
    180
    Par défaut
    Bonjour,

    J'arrive un peu a la bourre, mais pourquoi ne pas passer par le system HSV ?
    Je n'ai pas fais de test, mais je dirais un truc du genre.
    1) RGV -> HSV
    2) On prend H' = H + 180 (la roue chromatique done des couleurs oppose tres contrastées)
    S' = 1.0 - S
    V' = 1.0 - V
    3) H'S'V' -> RGB pour avoir la couleur de fond.

    [Edit]
    Je viens de coder le truc sous opencv. Apres plusieurs test voici les resultats:
    Quand on est en HSV, il n'est pas utile de modifier le S. Le V ne doit etre modifier que si le V du texte est trop faible (< 0.5).

    Avec une image contenant des resultat pris au hasard
    Nom : contrast.png
Affichages : 525
Taille : 69,5 Ko

    Et voici le code utilisé pour générer l'image

    Code c++ : 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
     
    void test_rapide(){
     
        Mat image(600,600,CV_8UC3);
     
        rgb fond, text;
        hsv temp;
        Scalar couleur_fond, couleur_text;
     
        for (int y = 0; y < 10; y++){
            for (int x = 0; x < 4; x++){
                text.r = (rand()%256)/255.0;
                text.g = (rand()%256)/255.0;
                text.b = (rand()%256)/255.0;
     
                temp = rgb2hsv(text);
                temp.h = temp.h + 180; if (temp.h > 360) temp.h -= 360;
                if (temp.v < 0.50) temp.v = 1.0 - temp.v;
                fond = hsv2rgb(temp);
     
                couleur_fond[0] = fond.b*255.0; couleur_fond[1] = fond.g*255.0; couleur_fond[2] = fond.r*255.0;
                couleur_text[0] = text.b*255.0; couleur_text[1] = text.g*255.0; couleur_text[2] = text.r*255.0;
     
                rectangle(image,Point(150*x,60*y),Point(150*(x+1),60*(y+1)),couleur_fond,-1);
                putText(image,"Contrast",Point(150*x+5,60*y+35),FONT_HERSHEY_COMPLEX,.9,couleur_text,2);
            }
        }
     
        imshow("image",image);
        waitKey();
        imwrite("./contrast.png",image);
    }

    Les conversion RGB-> HSV viennent de stack overflow : Code pour convertir.

  13. #13
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 171
    Points : 9 662
    Points
    9 662
    Par défaut
    A l'origine, la question était : Choisir une couleur (Soit NOIR, soit BLANC, uniquement 2 options), qui donne un contraste suffisant. Donc pas la couleur obtenue par ta formule.

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 050
    Points : 14 489
    Points
    14 489
    Par défaut
    Salut,

    Quelque chose comme ça, alors ? :

    Nom : contrast.png
Affichages : 491
Taille : 14,8 Ko

    Me suis basé sur HSL (L varie de blanc à noir) plutôt que HSV, et voilà le code en Pascal, qui utilise une TStringGrid nommée "sg" :
    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
    procedure TMainForm.sgDrawCell(Sender: TObject; aCol, aRow: Integer;
      aRect: TRect; aState: TGridDrawState);
    var
      aCanvas: TCanvas;
      function ContrastColor(InColor: TColor): TColor;
      var
        H, S, L, Ltmp: float;
      begin
        myColorToHSL(InColor, H, S, L);
        if (L <= 0.5) then Ltmp := 1; // noir --> blanc
        if (L > 0.5) then Ltmp := 0; // blanc --> noir
        Result := myHSLtoColor(H, S, Ltmp);
      end;
    begin
      Randomize;
      aCanvas := sg.Canvas;
      for aCol := 0 to sg.ColCount-1 do
        for aRow := 0 to sg.RowCount-1 do begin
          aCanvas.Brush.Color := random(16777216);
          aCanvas.FillRect(sg.CellRect(aCol, aRow));
          aCanvas.Font.Color:=ContrastColor(aCanvas.Brush.Color);
          aCanvas.TextOut(sg.CellRect(aCol, aRow).Left+10, sg.CellRect(aCol, aRow).Top+4, 'test');
        end;
    end;
    Les procédures myHSLtoColor et myColorToHSL s'appuient sur les formules qu'on peut trouver là.

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

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 233
    Points : 28 261
    Points
    28 261
    Par défaut
    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.(je n'ai pas retester d'autres choses depuis)

    De ce que tu montre Jipété, il en va de même. Colonne 2 ligne 5, et colonne 3 ligne 2 c'est un peu limite. Colonne 3, ligne 8, ça passe pas.
    Ça peut paraitre acceptable dans des petits carrés de tests comme ça, mais lorsque c'est dans une grille d'une 20ène de colonnes et jusqu'à 1000 lignes voire plus, ça peut se révéler assez vite fatiguant.

    Pour le moment l'application va finalement partir avec un texte noir imposé, l'utilisateur choisira sa couleur de fond, à lui de voir ce qui contraste le mieux ou pas (avec 16 millions de couleurs possible quand même).
    On prévoie finalement ça pour une version 2, qui ne verra probablement jamais le jour car l'utilisateur, une fois qu'il aura choisi ses couleurs, ne va pas en changer tous les 4 matins.

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 050
    Points : 14 489
    Points
    14 489
    Par défaut
    Citation Envoyé par sevyc64 Voir le message
    Colonne 3, ligne 8, ça passe pas.
    D'accord.
    Il faudrait surement moduler le premier test (
    Code pascal : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        if (L <= 0.5) then Ltmp := 1; // noir --> blanc
        if (L > 0.5) then Ltmp := 0; // blanc --> noir
    ) par des adaptations liées à la valeur de H : si (L = blanc) and (H = couleur_claire [jaune, rose, vert pâle, bleu ciel]) alors L := noir.
    Mais là ça devient du tuning pointu pointu et je n'ai pas eu trop le temps de finasser.

  17. #17
    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
    Jipété a vu l'essentiel
    Citation Envoyé par Jipété Voir le message
    ...
    Il faudrait surement moduler le premier test (
    Code pascal : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        if (L <= 0.5) then Ltmp := 1; // noir --> blanc
        if (L > 0.5) then Ltmp := 0; // blanc --> noir
    mais il reste à choisir la valeur du seuil de luminance (L = s ou L1 = s * L1max = s * 948582), au voisinage duquel se produit le basculement du noir au blanc. Ce choix expérimental n'est pas du tout évident:
    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. ...
    Bien que l'expression de la luminance tienne compte de la sensibilité de la rétine humaine aux diverses composantes (r, v, b), il faut s'assurer pour un seuil donné (s) du meilleur contraste possible (noir/blanc), pour toutes les teintes abordables - et il y en a une infinité (à luminance fixe) dépendant de deux paramètres - par ex. (r/v) et (b/v).
    En conséquence tester une série de valeurs du seuil (s = 0.55, 0.50, 0.45, ... ?) pour 7 couleurs principales:
    # rouge, vert, bleu: _ _ _ (u, 0, 0), (0, u, 0), (0, 0, u)
    # cyan, pourpre, jaune et gris: _ _ _ (0, u, u), (u, 0, u), (u, u, 0) et (u, u, u).

    L'entier (u) dépend du seuil (s), ainsi que de la teinte choisie, d'où sept calculs en vue, pas difficiles mais fort indigestes, et qui ne réjouissent personne.
    Un programme s'en chargera, et pourrait conduire à une série de 14 images (comportant une chaîne de caractères en noir ou blanc) semblables à celles que deux d'entre vous ont déjà données.

    Un calcul unique est envisageable en introduisant 3 grandeurs bivaluées (x, y, z), dont chacune peut être égale à (0) ou (1), et en posant:
    R8bit = u * x ; G8bit = u * y ; B8bit = u * z ;
    (u) vérifie alors l'équation: L1 = (0.297 * (u * x + 14 * x)2.4 + (u * y + 14 * y)2.4 + 0.101 * (u * z + 14 * z)2.4) .

    La bizarrerie du résultat vient de ce que la formule générale :
    L1 = (0.297 * (R8bit + 14)2.4 + (G8bit + 14)2.4 + 0.101 * (B8bit + 14)2.4)
    ne s'applique plus aux faibles indices (Icoul < 10), et que le terme correspondant s'annulle en même temps que (x, y) ou (z).
    L'expression L1 = F(u) est à prendre comme relation algorithmique, et non algébrique; elle peut se simplifier considérablement:
    L1 = (u + 14)2.4 * (0.297 * x2.4 + y2.4 + 0.101 * z2.4) = s * L1max , et sa résolution ne pose plus de difficulté.

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 050
    Points : 14 489
    Points
    14 489
    Par défaut
    Salut salut
    Citation Envoyé par wiwaxia Voir le message
    Jipété a vu l'essentiel
    Tu es trop bon.
    Je me suis juste souvenu que le système HSL fait varier L de blanc à noir, mais tout comme sevyc64 le remontait et comme tu l'as expliqué aussi, le système ne fonctionne pas avec certaines couleurs pour lesquelles il faudrait inverser la règle.
    Une misère...

    Citation Envoyé par wiwaxia Voir le message
    La bizarrerie du résultat vient de ce que la formule générale : L1 = (0.297 * (R8bit + 14)2.4 + (G8bit + 14)2.4 + 0.101 * (B8bit + 14)2.4)
    ne s'applique plus aux faibles indices (Icoul < 10)
    La dernière ligne me parle (suis en train de lire "La gestion des couleurs pour les photographes, les graphistes et le prépresse" de J. Delmas chez Eyrolles, excellent pour s'endormir ! )
    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...

    Citation Envoyé par wiwaxia Voir le message
    --snip-- et sa résolution ne pose plus de difficulté.
    Parle pour toi

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 050
    Points : 14 489
    Points
    14 489
    Par défaut
    Bon, je ne résiste pas au plaisir de vous poster cette première victoire (qu'il faudra sans doute améliorer, mais à chaque jour suffit sa peine, et les résultats encourageants incitent à progresser. Nan ?)

    Et donc :
    Nom : colorspluscontrast.png
Affichages : 469
Taille : 25,0 Ko

    Le rouge en haut à gauche est à 255,1,1 ; dessous le vert augmente de 16 : 255,17,1 et ainsi de suite.
    À côté le jaune est classiquement à 255,255,1, le vert à 1,255,1, le cyan à 1,255,255 et cette colonne est très intéressante car au voit au milieu le basculement du texte de noir à blanc, très exactement à 1,128,255, et c'est + ou - pareil pour les autres colonnes, chacune en ce qui la concerne, particulièrement la 1 et la 6, or, verticalement, l'écart d'une ligne à la suivante est de 16, régulièrement.
    C'est pas mal du tout, wiwaxia !

    D'autant plus qu'un premier test avait lamentablement foiré pour la bonne et simple raison que sur cette grid, incroyable mais vrai, un ColorPicker me montre que la valeur de L (si j'extrais HSL de la couleur de la cellule) est partout la même, aussi bien sur le jaune le plus clair que le bleu le plus sombre ! Très surprenant...

    Comment j'ai fait :
    1- une fonction avec la formule magique
    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;
    2- son utilisation
    Code pascal : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      function ContrastedColor(InColor: TColor): TColor;
      var
        H, S, L, Ltmp: float;
        R,G,B: byte;
      begin
        myColorToHSL(InColor, H, S, L); // extraction H S L, on va en avoir besoin
        myColorToRGB(InColor, R,G,B); // extraction R G B pour calcul
        Ltmp:=CalculeLwithWiwaxia(R,G,B); // appel de la formule magique
        if (Ltmp <= 25) then L := 1; // noir --> blanc -- 25 un peu au pif, à tuner mieux...
        if (Ltmp > 25) then L := 0; // blanc --> noir
        Result := myHSLtoColor(H, S, L);
      end;

    J'ai déterminé 25 en regardant un premier résultat basé sur 50 et sur ces données (valeurs brutes -- arrondies -- raccourcies -- encore un point) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
      blanc : 948227 950000 950 95
      jaune : 879778 880000 880 88
      cyan  : 746947 750000 750 75
      verte : 678498 680000 680 68
      magent: 270516 270000 270 27
      rouge : 202067 200000 200 20
      bleue :  69236  70000  70  7
      noire :    787   1000   1  0
    Les 3 dernières lignes sont "sombres" et nécessitent donc du texte blanc.
    Faudra voir ce que ça va donner avec un fond de grid plus randomized, comme mon premier essai, mais ça va bien comme ça pour ce soir.
    That's all, folks !

  20. #20
    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
    Bravo pour la palette !

    Très flatté par l'identificateur de fonction ...
    ... Comment j'ai fait :
    1- une fonction avec la formule magique
    Code pascal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function CalculeLwithWiwaxia(R,G,B: byte):integer;
    ... je ne me savais pas doté de super-pouvoirs, lesquels me seraient bien utiles depuis tout à l'heure, où je me suis lancé dans l'exploration numérique de la fonction en question.

    Je posterai les calculs demain.

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