7yl4r 7yl4r - 3 months ago 24
C++ Question

Trouble with HSI->RGB conversion

I have some strange issue when trying to apply a conversion from HSI to RGB which I am trying to do as part of a homework assignment. To start off, here is my original image:

original image (sorry about the links, I don't have the rep to post images)

I am converting from an image with H,S,I values (0-255). Here is a display of that image in RGB colorspace (Hue=red, sat=green, inten=blue):

HSI src image

To me it looks about right... the white flowers (high intensity) are blue, the hues (red) seem to change with the different colored flowers.

So now I do some equalization on the intensity channel (blue in display) in some boxes, resulting in this:

HSI equalized image:

http://i.imgur.com/hgk9K.png

((you must copypasta these 'cause I don't have rep for >2 hyperlinks))

No big deal there. It doesn't look exactly right, but it's hard to say and everything outside the region-of-interest boxes is the same.

Now here comes the problem. After converting this back to RGB I get this result:

converted image:
http://i.imgur.com/6wEyw.png


No idea what the problem is here, the green looks okay, but some red/blue pixels seem to be maxed. The three boxes are there as expected, and they're contents seem pretty messed, but that's not the bigger issue here since that could be from my equalization function. Everything outside of those boxes should now be nearly identical to the original image, but somehow it has been jumbled.

I've gone over my code many times and added extra parentheses and data type casts just to be sure, but still can't find the issue. I am confident my formulas are correct, but I must be missing some problem in the way the pixel values are being calculated.

Here is the code I am using to convert from HSI to RGB. It is possible the error is outside of this method, but all the functions used here have been tested elsewhere and seem to work fine.

void colorSpace::HSItoRGB(image &src, image &tgt){
cout<<"HSI->RGB\n";
tgt.resize(src.getNumberOfRows(),src.getNumberOfColumns());
float pi = 3.14159265358979f;
for (int i=0; i<src.getNumberOfRows(); i++){ //for each pixel
for (int j=0; j<src.getNumberOfColumns(); j++){
//re-normalize h,s,i
float h = ((float)src.getPixel(i,j,H))*pi*2.0f/255.0f;//255/2 instead of 180
float s = ((float)src.getPixel(i,j,S))/255.0f;//255 instead of 100
float in= ((float)src.getPixel(i,j,I))/255.0f;
//compute x y z
float x = in*(1.0f-s);
float y = in*( 1.0f + (s*cos(h) / cos(pi/3.0f-h)) );
float z = 3.0f*in-(x+y);
float r,g,b; //set rgb
if(h<(2.0f*pi/3.0f)){
b = x;
r = y;
g = z;
}else if(h<(4.0f*pi/3.0f)){//&&2pi/3<=h
r = x;
g = y;
b = z;
}else{ //less than 2pi && 4pi/3<=h
g = x;
b = y;
r = z;
}
//convert normalized rgb to 0-255 range
int rr = (int)round(r*255.0f);
int gg = (int)round(g*255.0f);
int bb = (int)round(b*255.0f);
tgt.setPixel(i,j,RED,rr);
tgt.setPixel(i,j,GREEN,gg);
tgt.setPixel(i,j,BLUE,bb);
}
}
}


Does anybody see any trouble in the code or have any insights from looking at the images?

Answer

The h values need to be adjusted for the three cases prior to calculating the cos values dependent on them. i.e.:

        if(h<(2.0f*pi/3.0f)){
            y = in*( 1.0f + (s*cos(h) / cos(pi/3.0f-h)) );
            b = x;
            r = y;
            g = z;
        }else if(h<(4.0f*pi/3.0f)){//&&2pi/3<=h
            h -= 2*pi/3;
            y = in*( 1.0f + (s*cos(h) / cos(pi/3.0f-h)) );
            r = x; 
            g = y;
            b = z;
        }else{  //less than 2pi && 4pi/3<=h
            h -= 4*pi/3;
            y = in*( 1.0f + (s*cos(h) / cos(pi/3.0f-h)) );
            g = x;
            b = y;
            r = z;
        }

You will also need to make sure that none of the rr,gg,bb values end up outside the 0..255 interval:

if (rr < 0) rr = 0;
if (rr > 255) rr = 255;

... etc

Comments