От RGB к HSV в OpenGL GLSL

Мне нужно перейти из цветового пространства RGB в HSV. Я искал в Интернете и нашел две разные реализации, но они дают разные результаты:

A:

precision mediump float;
 vec3 rgb2hsv(float r, float g, float b) {

     float h = 0.0;
     float s = 0.0;
     float v = 0.0;

     float min = min( min(r, g), b );
     float max = max( max(r, g), b );
     v = max;               // v

     float delta = max - min;

     if( max != 0.0 )
         s = delta / max;       // s
     else {
         // r = g = b = 0       // s = 0, v is undefined
         s = 0.0;
         h = -1.0;
         return vec3(h, s, v);
     }
     if( r == max )
         h = ( g - b ) / delta;     // between yellow & magenta
     else if( g == max )
         h = 2.0 + ( b - r ) / delta;   // between cyan & yellow
     else
         h = 4.0 + ( r - g ) / delta;   // between magenta & cyan

     h = h * 60.0;              // degrees

     if( h < 0.0 )
         h += 360.0;

     return vec3(h, s, v);
 }

B:

 precision mediump float;
 vec3 rgb2hsv(float r, float g, float b) {

     float K = 0.0;
     float tmp;

     if (g < b)
     {
         tmp = g;
         g=b;
         b=tmp;

         K = -1.0;
     }

     if (r < g)
     {
         tmp = r;
         r=g;
         g=tmp;

         K = -2.9 / 6.9 - K;
     }

     float chroma = r - min(g, b);

     float h = abs(K + (g - b) / (6.0 * chroma + 1e-20));
     float s = chroma / (r + 1e-20);
     float v = r;

     return vec3(h, s, v);
 }

Вы знаете, что является правильной реализацией?


person BQuadra    schedule 26.02.2013    source источник


Ответы (2)


Я автор второй реализации. У меня всегда вела себя корректно, но вы написали 2.9 / 6.9 вместо 2.0 / 6.0.

Поскольку вы ориентируетесь на GLSL, вам следует использовать подпрограммы преобразования, написанные с учетом GPU:

// All components are in the range [0…1], including hue.
vec3 rgb2hsv(vec3 c)
{
    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

    float d = q.x - min(q.w, q.y);
    float e = 1.0e-10;
    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

 

// All components are in the range [0…1], including hue.
vec3 hsv2rgb(vec3 c)
{
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

Взято с сайта http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl.

Изменить: код находится под лицензией WTFPL.

person sam hocevar    schedule 27.07.2013
comment
я попробовал это на веб-сайте shapertoy, и он сказал, что не найдено подходящей перегруженной функции, не может преобразовать из mediump в Vector3 - person DeltaEnfieldWaid; 03.11.2013
comment
Хороший! У вас уже есть такие же функции для цветового пространства HSL? - person wip; 20.02.2014
comment
Я только что реализовал hsv2rgb() с аппаратным смешиванием. Совершенно глупо, но я все еще слегка горжусь собой. - person jozxyqk; 06.03.2015
comment
Еще несколько интересных функций шейдера цветового пространства можно найти здесь и здесь. - person gman; 08.12.2015
comment
Любой, кто использует этот код, должен знать, что угол оттенка выражается в виде значения между 0,0-1,0 (а не в радианах или градусах)... надеюсь, это сэкономит кому-то девяносто минут разочарования... :-) - person WaveformDelta; 01.10.2018
comment
@WaveformDelta извините, что не сделал это более очевидным; Я добавил комментарии к этим функциям, чтобы другие люди не теряли время… - person sam hocevar; 01.10.2018
comment
Просто хотел сказать, что я часто нахожу большое применение этим функциям! отличная работа. - person Just another metaprogrammer; 09.08.2020
comment
@samhocevar Можете ли вы опубликовать свой код в MIT в репозитории git (Github, Gitlab или т. д.). Есть лицензированный MIT проект, который хотел бы использовать это, но не может из-за лицензирования SO. - person WSLUser; 08.09.2020
comment
Вы меня поймали на том, что я автор второй реализации. - person John Miller; 25.06.2021

У меня нет среды разработки для проверки, но вы можете использовать wolframAlpha для создания некоторых утверждений.

Например: rgb(1,0,0 )(чисто красный) в hsv 0, 100%, 100% в hsv.

person MrLeap    schedule 26.02.2013