7yl4r - 4 months ago 36

C++ Question

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