Convert RGB to HSV and back with a micro controller
It took me a while to find code examples how to convert an RGB color value into the equivalent HSV color space and back. Also it took me quite a while to adapt the code for my micro controller.
For the reference, here the examples, written in ANSI C. First of all I created some useful structs to store the values:
struct RGB_set { unsigned char r; unsigned char g; unsigned char b; } RGB_set; struct HSV_set { signed int h; unsigned char s; unsigned char v; } HSV_set;
Here the first function:
/******************************************************************************* * Function RGB2HSV * Description: Converts an RGB color value into its equivalen in the HSV color space. * Copyright 2010 by George Ruinelli * The code I used as a source is from http://www.cs.rit.edu/~ncs/color/t_convert.html * Parameters: * 1. struct with RGB color (source) * 2. pointer to struct HSV color (target) * Notes: * - r, g, b values are from 0..255 * - h = [0,360], s = [0,255], v = [0,255] * - NB: if s == 0, then h = 0 (undefined) ******************************************************************************/ void RGB2HSV(struct RGB_set RGB, struct HSV_set *HSV){ unsigned char min, max, delta; if(RGB.r<RGB.g)min=RGB.r; else min=RGB.g; if(RGB.b<min)min=RGB.b; if(RGB.r>RGB.g)max=RGB.r; else max=RGB.g; if(RGB.b>max)max=RGB.b; HSV->v = max; // v, 0..255 delta = max - min; // 0..255, < v if( max != 0 ) HSV->s = (int)(delta)*255 / max; // s, 0..255 else { // r = g = b = 0 // s = 0, v is undefined HSV->s = 0; HSV->h = 0; return; } if( RGB.r == max ) HSV->h = (RGB.g - RGB.b)*60/delta; // between yellow & magenta else if( RGB.g == max ) HSV->h = 120 + (RGB.b - RGB.r)*60/delta; // between cyan & yellow else HSV->h = 240 + (RGB.r - RGB.g)*60/delta; // between magenta & cyan if( HSV->h < 0 ) HSV->h += 360; }
And its contrary function:
/******************************************************************************* * Function HSV2RGB * Description: Converts an HSV color value into its equivalen in the RGB color space. * Copyright 2010 by George Ruinelli * The code I used as a source is from http://www.cs.rit.edu/~ncs/color/t_convert.html * Parameters: * 1. struct with HSV color (source) * 2. pointer to struct RGB color (target) * Notes: * - r, g, b values are from 0..255 * - h = [0,360], s = [0,255], v = [0,255] * - NB: if s == 0, then h = 0 (undefined) ******************************************************************************/ void HSV2RGB(struct HSV_set HSV, struct RGB_set *RGB){ int i; float f, p, q, t, h, s, v; h=(float)HSV.h; s=(float)HSV.s; v=(float)HSV.v; s /=255; if( s == 0 ) { // achromatic (grey) RGB->r = RGB->g = RGB->b = v; return; } h /= 60; // sector 0 to 5 i = floor( h ); f = h - i; // factorial part of h p = (unsigned char)(v * ( 1 - s )); q = (unsigned char)(v * ( 1 - s * f )); t = (unsigned char)(v * ( 1 - s * ( 1 - f ) )); switch( i ) { case 0: RGB->r = v; RGB->g = t; RGB->b = p; break; case 1: RGB->r = q; RGB->g = v; RGB->b = p; break; case 2: RGB->r = p; RGB->g = v; RGB->b = t; break; case 3: RGB->r = p; RGB->g = q; RGB->b = v; break; case 4: RGB->r = t; RGB->g = p; RGB->b = v; break; default: // case 5: RGB->r = v; RGB->g = p; RGB->b = q; break; } }
Also I wrote a function to split a color string (like they are used in HTML) into its individual RGB color parts:
/******************************************************************************* * Function RGB_string2RGB_struct * Description: Converts an RGB color tring into the individual color values. * Copyright 2010 by George Ruinelli * Parameters: * 1. pointer string with RGB color (source) without leading # i.e. FF0000 for red. * 2. pointer tu struct RGB color struct (target) * Notes: * - r, g, b values are from 0..255 ******************************************************************************/ void RGB_string2RGB_struct(char *tuple, struct RGB_set *RGB){ char tmp[3]; strncpy(tmp, tuple, 2); tmp[2]= '\0'; RGB->r=(unsigned char)(strtoul(tmp, NULL, 16)); strncpy(tmp, &tuple[2], 2); tmp[2]= '\0'; RGB->g=(unsigned char)(strtoul(tmp, NULL, 16)); strncpy(tmp, &tuple[4], 2); tmp[2]= '\0'; RGB->b=(unsigned char)(strtoul(tmp, NULL, 16)); }
And a little application to test it:
int main (void){ struct RGB_set RGB; struct HSV_set HSV; RGB.r=0xFF; RGB.g=0xFF, RGB.b=0x0; //define color "yellow" printf ("Yellow in RGB: %X, %X, %X\n", RGB.r, RGB.g, RGB.b); RGB2HSV(RGB, &HSV); printf ("converted to HSV: %X, %X, %X\n", HSV.h, HSV.s, HSV.v); HSV2RGB(HSV, &RGB); printf ("converted back to RGB: %X, %X, %X\n", RGB.r, RGB.g, RGB.b); char HTML_color[]="FF8000"; //orange RGB_string2RGB_struct(HTML_color, &RGB); printf ("convert HTML color #FF8000 (orange) to its parts (RGB): %X, %X, %X\n", RGB.r, RGB.g, RGB.b); return 0; }
Some notes:
The functions are written to run on a micro controller. Because of that, RGB2HSV does not use any floating point functions. This can lead to some rounding errors but can usually be ignored. The contrary function HSV2RGB still uses floating point operations. Here some optimizations are possible.
Since this is one of the popular search results, I’ll provide some informations on opencv. The images are internaly stored as arrays. For regular image, it’s RGB format, RGBA or some more exotic. To extract regular RGB, you can use this code:
Mat image = imread(„input.jpg“, CV_LOAD_IMAGE_COLOR); // Or whatever settings
if (!image.data) { // Valid image
byte[] data = image.data; // Pixel array
unsigned int totalPixels = image.rows*image.cols;
struct RGB_set RGB; // RGB structure
struct HSV_set HSV; // HSV structure
for(int i=0;i<totalPixels;i++) { // For every pixel in image
RGB.r = input_data[(i * 3) + 2];
RGB.g = input_data[(i * 3) + 1];
RGB.b = input_data[(i * 3) ];
printf ("Yellow in RGB: %X, %X, %X\n", RGB.r, RGB.g, RGB.b);
RGB2HSV(RGB, &HSV);
printf ("converted to HSV: %X, %X, %X\n", HSV.h, HSV.s, HSV.v);
}
}
I was searching for a simple, straightforward function to convert RGB vales to HSV, and you provided it.
The code worked faultlessly without any modification in the Arduino IDE. Just what I was looking for, Thank You!
If I end up using your code in a project I plan on sharing in a YouTube video, I will definitely be crediting you, and providing a link to this page.
dear sir
i need help how to convert rgb to hsv in opencv,tell me sir what are the changes have to made for the above code
I am sorry, but I don’t have or use the opencv library! I would expect it already has functions for this very trivial conversions. Else make your own function with your code.