|
Post by scalion on Mar 3, 2021 18:06:04 GMT 1
Excellent ! Ca fonctionne, j'ai enfin une fonction sous la main pour utiliser HSL, Merci JMM ! Je pense que je vais bien m'amuser avec ça !
|
|
|
Post by scalion on Mar 3, 2021 23:10:17 GMT 1
Excellent travail ! J'ai passé près de 2 heures a décortiquer tout ton code. Visiblement tu as potassé à fond. j'ai bien aimé les valeurs de compensations, le "poids" lumineux pour chaque composante RGB dans la fonction de conversion F_HSL2RGB , c'est extrêmement astucieux, félicitations ! J'ose à peine apporter ces petites remarques : - quand à la valeur de FF je pense qu'elle devrait être 256 et non 255 (sinon tu as une plage de valeur absente comprise entre 255 et 255.9999...). - les valeurs HSL doivent être normalisées (0 à 1) en début de fonction. - intuitivement (je ne saurais l'expliquer) (H0 <= H) And (H <= H1) devrait être remplacé par (H>=0 AND H<H1) - tu peux encore l'améliorer au niveau rapidité (en ajoutant notemment des ELSE IF) Oh j'ai honte de critiquer... je n'avais jamais réussi à faire du HSL (j'en avais besoin dans mes test de compression d'image)
|
|
|
Post by scalion on Mar 5, 2021 9:34:16 GMT 1
La fonction RGB2HSL est performante, cependant elle fournit une approximation de HSL et non une valeur exacte (comme dans la plupart des logiciel de DAO même Photoshop). J'ai fait un test en utilisant HSL2RGB puis RGB2HSL et de nouveau HSL2RGB. Visuellement c'est réussi, cependant dans les valeurs (de saturation basse particulièrement) on a de grandes marge d'erreur qui sont visibles à l'oeil nu :
Je n'ai toujours pas réussi à calculer RAPIDEMENT la valeur exacte. Je me suis fais une fonction qui recherche dans une boucle de HSL aléatoires la valeur qui permet de retrouver les valeurs RGB générées. Ca fonctionne mais c'est monstrueusement lent. Je vais faire une fonction avec une table prédéfinie 8x8x8 des valeurs HSL exactes correspondantes, j'utiliserais ensuite une courbe de Bezier pour interpoler et je vais voir ce que ça donne. Je reviens plus tard avec mes résultat...
EDIT: Je n'ai pas de résultat car je n'ai même pas réussi à établir une table de base EXACTE de valeur HSL correpondant aux valeurs RGB. Je me penche maintenant sur une autre approche : HSL et RGB peuvent être aisémment représentés dans un espace tridimensionnel. A partir de là, théoriquement, le point HSL correspondant au point RGB peut être liée par un vecteur. Par exemple je peut partir du point HSL (0.5,0.5,0.5) , centre du cube espace HSL et chercher par dichotomie le vecteur qui permette d'approcher de la valeur RGB. Je vais essayer de réécrire une fonction HSL2RGB en utilisant un algorythme différent et de pourquoi pas mesurer l'entropie des valeurs RGB obtenues (est-ce que la fonction couvre un maximum de valeurs). To be continued...
Pour info ta fonction à une entropie ~= 0.826 (ce qui est pas mal) Si on supprime le compensateur luminosité pour la saturation par m=(HR+HG+HB)/3 l'entropie grimpe à 850
Si en remplace les pentes pour HUE (dec1,inc1,etc...) par des courbes et idem pour la luminosité on atteins 872.
EDIT2:
Je vais faire des tests avec ma version modifiée :
Function HSL2RGB(H#, S#, L#) As Long ' Based on Jean-Marie MELANSSON work ' Modifications : ' - use double value for higher precision ' - use curves for colors transitions ' - use Bezier curve to apply luminosity ' - Saturation without brightness correction to increase entropy Local Double r, g, b, m H = Max(0, Min(6, H * 6)) If H < 1 r = 1 g = Iif(h < 0.5, 2 * h * h, -2 * (h - 2) * h - 1) ' <- double curve power 2 b = 0 Else If H < 2 H = 2 - H r = Iif(H < 0.5, 2 * H * H, -2 * (H - 2) * H - 1) g = 1 b = 0 Else If H < 3 r = 0 g = 1 H -= 2 b = Iif(H < 0.5, 2 * H * H, -2 * (H - 2) * H - 1) Else If H < 4 r = 0 H = 4 - H g = Iif(H < 0.5, 2 * H * H, -2 * (H - 2) * H - 1) b = 1 Else If H < 5 H -= 4 r = Iif(H < 0.5, 2 * H * H, -2 * (H - 2) * H - 1) g = 0 b = 1 Else r = 1 g = 0 H = 6 - H b = Iif(H < 0.5, 2 * H * H, -2 * (H - 2) * H - 1) EndIf S = Max(0, Min(1, S)) ' m = r * 0.29 + g * 0.58 + b * 0.13 m = (r + g + b) / 3 ' <- loss visual pertinance but increase entropy r = m + S * (r - m) g = m + S * (g - m) b = m + S * (b - m) L = Max(0, Min(1, L)) If L < 0.5 L *= 2 r = l * r + l * (r - l * r) ' <- Bezier curve : 0 to value to value g = L * g + L * (g - L * g) b = L * b + L * (b - L * b) Else L = 2 * (L - 0.5) r = r + l * (l - l * r) ' <- Bezier curve : value to value to 1 g = g + L * (L - L * g) b = b + L * (L - L * b) EndIf Return RGB(Int(r * 255.999999999), Int(g * 255.999999999), Int(b * 255.999999999)) EndFunc
|
|
|
Post by scalion on Mar 6, 2021 18:50:08 GMT 1
RGB to HSL !!! Oh!, Quelle bête! J'ai rêvé à ça toute la nuit!
En somme, il faut réaliser qu'une conversion 1:1 n'est pas possible. C'est pas grave, ça peut encore servir, par exemple pour faire du 'Green Screen'. Ça deviens plus facile si on nous donne une ou deux astuces H, S ou L pour commencer.
RGB to HSL !!! Oh !, What a beast! I dreamt about this all night!
In short, it must be realized that a 1:1 conversion is not possible. It's okay, it can still be useful, for example to make 'Green Screen'. It gets a lot easier if we're given one or two H, S, or L tips to start.
C'est un peu le mouvement perpétuel ou la pierre philosophale, c'est pas possible mais on cherche quand même parce-qu'il ya toujours une petite voix qui dit "Mais si, peut-être...". Normalement les valeur obtenues avec HSL2RGB doivent pouvoir être retrouvées quand même ! J'ai fais un calcul de fou furieux hier que j'ai lancé avant de sortir de chez moi. j'ai subdivisé l'espace HSL à l'infini (mais contrairement à Chuck Norris je me suis arrêté avant) et ta fonction non modifiée F_HSL2RGB couvre 99.999% des couleurs et je suis certains que le 150 dernières valeurs RGB à trouver n'ont pas été atteintes parce-que j'ai arrêté le programme avant. Oui Jean-Marie, le saint Graâl existe, il est là, tout près !
|
|
|
Post by scalion on Mar 6, 2021 19:02:45 GMT 1
J'ai fait des tests avec le vecteur dans un espace tridimensionnel c'est assez concluant mais pas encore satisfaisant, maintenant je vais essayer des subdivisions dichotomiques de l'espace HSL....
EDIT :
J'ai fait un 1er essai en divisant l'espace HSL en 48x48x48 (=110 592 secteurs) J'ai calculé HSL2RGB avec la valeur HSL du centre de chaque secteur et gardé la valeur la plus proche de RGB. Les valeurs RGB caclulées par ma fonction HSL2RGB modifiée sont au format double et vont de 0 à 1 pour un maximum de précision. La différence entre la valeur calculée et la valeur RGB cible est une distance dans l'espace RGB entre les 2 points RGB. Ensuite j'ai effectué une subdivision du meilleur secteur contenant donc la valeur la plus proche en 4x4x4 (=64 sous-secteurs) J'ai répété 2 fois l'opération mais en divisant la taille de l'espace autour du meilleur sous-secteur par 2
Résultat décevant :
Bon j'ai encore une autre idée... on peut imaginer que la luminosité ou la saturation d'une couleur est calculable. Admettons je calcule une luminosité L et je postule qu'elle est exacte. Je me retouve avec un espace 2D avec HS sur lequel je peut glisser un curseur d'une façon ou d'une autre... à suivre...
EDIT2 : J'ai finalement réussi à créer une table exacte des valeurs HSL 8x8x8 avec une fonction utilisant la valeur HUE et une réduction /2 sectorielle à 100 itérations dans SL. Elle ne fonctionne qu'avec ma version modifiée (voir post précédent).
Les valeurs RGB sont des multiples de 36, donc 0,36,72,108,144,180,216,252.
J'ai sauvegardé les valeurs HSL au format double on a donc un fichier qui fait 8 x 8 x 8 x 3 x 8 = 12288 octets
J'ai découvert un petit problème dans ta fonction F_RGB2SHL au niveau de passage du violet au rouge (valeurs 5/6 à 1) je vais essayer de voir ça, il y a aussi parfois des valeurs de sortie négatives je n'ai pas compris pourquoi.
Pour info j'ai pu développer la fonction inverse pour la valeur hue, j'en profite pour vous indiquer le site que j'utilise pour résoudre des équations et qui est très efficace.
Function RGB2Hue(r#, g#, b#) As Double Local Long i Local Double s, vmin ' Normalisation vmin = Min(r, g, b) s = Max(r, g, b) - vmin If s = 0 r = 1 g = 1 b = 1 Else r = (r - vmin) / s g = (g - vmin) / s b = (b - vmin) / s EndIf ' Resolving If r = 1 And g = 1 And b = 1 Return 0 Else If r = 1 And g = 1 And b = 0 Return 1 / 6 Else If r = 1 And g = 0 And b = 1 Return 5 / 6 Else If r = 1 And g = 0 And b = 0 Return 0 Else If r = 0 And g = 1 And b = 1 Return 3 / 6 Else If r = 0 And g = 1 And b = 0 Return 2 / 6 Else If r = 0 And g = 0 And b = 1 Return 4 / 6 Else If r = 1 And g > 0 And b = 0 Return Iif(g < 0.5, Sqr(g) / Sqr(2), 1 - Sqr(1 - g) / Sqr(2)) / 6 Else If r = 1 And g = 0 And b > 0 Return 1 - Iif(b < 0.5, Sqr(b) / Sqr(2), 1 - Sqr(1 - b) / Sqr(2)) / 6 Else If r > 0 And g = 1 And b = 0 Return 2 / 6 - Iif(r < 0.5, Sqr(r) / Sqr(2), 1 - Sqr(1 - r) / Sqr(2)) / 6 Else If r = 0 And g = 1 And b > 0 Return 2 / 6 + Iif(b < 0.5, Sqr(b) / Sqr(2), 1 - Sqr(1 - b) / Sqr(2)) / 6 Else If r > 0 And g = 0 And b = 1 Return 4 / 6 + Iif(r < 0.5, Sqr(r) / Sqr(2), 1 - Sqr(1 - r) / Sqr(2)) / 6 Else If r = 0 And g > 0 And b = 1 Return 4 / 6 - Iif(g < 0.5, Sqr(g) / Sqr(2), 1 - Sqr(1 - g) / Sqr(2)) / 6 EndIf EndFunc Proc Hue2RGB(H#, ByRef r#, ByRef g#, ByRef b#) If H < 0 H = 1 + Frac(H) If H > 1 H = Frac(H) H = Max(0, Min(6, H * 6)) If H < 1 r = 1 g = Iif(H < 0.5, 2 * H * H, -2 * (H - 2) * H - 1) ' <- double curve power 2 b = 0 Else If H < 2 H = 2 - H r = Iif(H < 0.5, 2 * H * H, -2 * (H - 2) * H - 1) g = 1 b = 0 Else If H < 3 r = 0 g = 1 H -= 2 b = Iif(H < 0.5, 2 * H * H, -2 * (H - 2) * H - 1) Else If H < 4 r = 0 H = 4 - H g = Iif(H < 0.5, 2 * H * H, -2 * (H - 2) * H - 1) b = 1 Else If H < 5 H -= 4 r = Iif(H < 0.5, 2 * H * H, -2 * (H - 2) * H - 1) g = 0 b = 1 Else r = 1 g = 0 H = 6 - H b = Iif(H < 0.5, 2 * H * H, -2 * (H - 2) * H - 1) EndIf EndProc
|
|
|
Post by scalion on Feb 20, 2024 16:09:50 GMT 1
En faisant des recherche sur les réseaux convolutifs ,j'ai implémenté une version rétroactive (bi-directionnelle) de conversion RGB to SLT / SLT to RGB. Aucune perte avec RGB to SLT (SLT donne bien le RGB original)! Plutot que de calculer Hue en premier je commence par la saturation , ce qui me donne un nombre précis de combinaisons possibles, ensuite la Teinte (Hue) est l'index de la combinaison des valeurs.
US : By doing research on convolutional networks, I implemented a retroactive (bi-directional) version of RGB to SLT / SLT to RGB conversion. No loss with RGB to SLT (SLT gives the original RGB)! Rather than calculating Hue first I start with saturation, which gives me a precise number of possible combinations, then Hue is the index of the combination of values.
|
|
|
Post by (X) on Feb 20, 2024 16:13:33 GMT 1
Dans ton demo, ne serait-ce pas la "Chat"uration?
|
|
|
Post by (X) on Feb 20, 2024 18:54:06 GMT 1
J'ai de dôles de résultats...
Les couleurs ne sont pas reproduites exactement pareilles.
|
|
|
Post by (X) on Feb 21, 2024 13:37:04 GMT 1
I asked Bing...
"Is it possible in theory to convert rgb to HSL and back losslessly?"
Bing:
Yes, it is theoretically possible to convert RGB (Red, Green, Blue) to HSL (Hue, Saturation, Lightness) and back without any loss of information. The conversion process involves mathematical transformations that do not inherently cause loss of data. However, in practice, the precision of the conversion can be affected by factors such as rounding errors or the precision of the programming language's floating-point arithmetic. Here is a high-level overview of the conversion process: **RGB to HSL:** 1. Normalize the RGB values to the range 0-1. 2. Find the minimum and maximum values among R, G, and B. These are used to calculate Lightness (L) and Saturation (S). 3. Calculate Lightness: `L = (Max + Min) / 2`. 4. If Max equals Min, the color is grayscale, so set Hue (H) and Saturation (S) to 0. 5. Otherwise, calculate Saturation: if Lightness is less than 0.5, `S = (Max - Min) / (Max + Min)`. If Lightness is greater than or equal to 0.5, `S = (Max - Min) / (2.0 - Max - Min)`. 6. Calculate Hue: the formula differs depending on whether R, G, or B is the maximum value. **HSL to RGB:** 1. If Saturation is 0, the color is grayscale, so set R, G, and B to Lightness. 2. Otherwise, calculate temporary values based on Lightness and Saturation, and use these to calculate R, G, and B. The formulas differ depending on the value of Hue. Remember, these are high-level overviews and the actual formulas involve more specific calculations. Also, the resulting RGB values need to be denormalized (multiplied by 255 and rounded to integers) to get back to the standard 0-255 range used in most applications. It's also worth noting that while this conversion is theoretically lossless, different software may handle the edge cases or rounding differently, which could potentially result in minor discrepancies. Source: Conversation with Bing, 2024-02-21 (1) undefined. docs.gl/gl3/glAl.
|
|
|
Post by (X) on Feb 21, 2024 14:02:31 GMT 1
Si Bing le dit, ça doit être vrai. :)
|
|