I need to pass from RGB color space to HSV .. I searched in internet and found two different implementations, but those give me different results:
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); }
Do you know which is the correct implementation?
Convert RGB Image to HSV Image Convert the image to the HSV color space. HSV = rgb2hsv(RGB); Process the HSV image. This example increases the saturation of the image by multiplying the S channel by a scale factor.
R, G, B in RGB are all co-related to the color luminance( what we loosely call intensity),i.e., We cannot separate color information from luminance. HSV or Hue Saturation Value is used to separate image luminance from color information. This makes it easier when we are working on or need luminance of the image/frame.
HSV is a cylindrical color model that remaps the RGB primary colors into dimensions that are easier for humans to understand. Like the Munsell Color System, these dimensions are hue, saturation, and value. Hue specifies the angle of the color on the RGB color circle.
I am the author of the second implementation. It has always behaved correctly for me, but you wrote 2.9 / 6.9
instead of 2.0 / 6.0
.
Since you target GLSL, you should use conversion routines that are written with the GPU in mind:
// 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); }
Taken from http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl.
Edit: code is licensed under the WTFPL.
I don't have a development environment to check, but you can use wolframAlpha to build up some asserts.
For Instance: rgb(1,0,0)(pure red) to hsv is 0, 100%, 100% in hsv.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With