У меня возникла странная проблема при попытке применить преобразование из HSI в RGB, которое я пытаюсь выполнить как часть домашнего задания. Для начала вот мое оригинальное изображение:
исходное изображение (извините за ссылки, у меня нет представителя для публикации изображений)
Я конвертирую из изображения со значениями H, S, I (0-255). Вот отображение этого изображения в цветовом пространстве RGB (оттенок = красный, насыщенный = зеленый, интенсивный = синий):
Для меня это выглядит правильно … белые цветы (высокой интенсивности) голубые, оттенки (красные), кажется, меняются с цветами разных цветов.
Так что теперь я делаю некоторое выравнивание на канале интенсивности (синий на дисплее) в некоторых полях, что приводит к следующему:
HSI выровненное изображение:
http://i.imgur.com/hgk9K.png
((Вы должны скопировать их, потому что у меня нет представителя для> 2 гиперссылок))
Ничего страшного там нет. Это выглядит не совсем правильно, но трудно сказать, и все, что находится за пределами области интересов, одинаково.
Теперь здесь возникает проблема. После преобразования этого обратно в RGB я получаю такой результат:
преобразованное изображение:
http://i.imgur.com/6wEyw.png
Понятия не имею, в чем здесь проблема, зеленый выглядит хорошо, но некоторые красные / синие пиксели выглядят максимально. Три поля там, как и ожидалось, и их содержимое кажется довольно запутанным, но это не самая большая проблема, так как это может быть из моей функции выравнивания. Все, что находится вне этих полей, теперь должно быть почти идентично исходному изображению, но каким-то образом оно перемешано.
Я много раз просматривал свой код и добавил дополнительные скобки и приведение типов данных просто для уверенности, но все еще не могу найти проблему. Я уверен, что мои формулы верны, но я, должно быть, упускаю некоторую проблему в способе вычисления значений пикселей.
Вот код, который я использую для преобразования из HSI в RGB. Возможно, ошибка не в этом методе, но все функции, использованные здесь, были протестированы в другом месте и, кажется, работают нормально.
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);
}
}
}
Кто-нибудь видит какие-либо проблемы в коде или есть понимание взгляда на изображения?
Значения h необходимо скорректировать для трех случаев, прежде чем рассчитывать значения cos, зависящие от них. т.е .:
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;
}
Вам также необходимо убедиться, что ни одно из значений rr, gg, bb не выходит за пределы интервала 0..255:
if (rr < 0) rr = 0;
if (rr > 255) rr = 255;
… так далее
Основная идея здесь — это сдвиг от 0 до 360 по значению оттенка, что приведет к значениям rgb. У нас также есть насыщенность, которая составляет от 0,00 до 1,00 или что-то среднее между ними, а также интенсивность, которая также составляет от 0,00 до 1,00.
///I use this
// the function result will be the values of the array rgb[3] and will be the rgb values 0-255
///float H is values 0-360 because there are 360 degrees of color in hsi colorspace
///float S is 0.00 - 1.00 and aything in between
///float I is 0.00 - 1.00 and aything in between
///The input to our function is going to be hsi_to_rgb (Hue, Saturation, Intensity(brightness))
int rgb[3]; ///number of channels rgb = 3
void hsi_to_rgb(float H, float S, float I) {
int r, g, b;
if (H > 360) {
H = H - 360;
}
H = fmod(H, 360); // cycle H around to 0-360 degrees
H = 3.14159 * H / (float)180; // Convert to radians.
S = S > 0 ? (S < 1 ? S : 1) : 0; // clamp S and I to interval [0,1]
I = I > 0 ? (I < 1 ? I : 1) : 0;
if (H < 2.09439) {
r = 255 * I / 3 * (1 + S * cos(H) / cos(1.047196667 - H));
g = 255 * I / 3 * (1 + S * (1 - cos(H) / cos(1.047196667 - H)));
b = 255 * I / 3 * (1 - S);
} else if (H < 4.188787) {
H = H - 2.09439;
g = 255 * I / 3 * (1 + S * cos(H) / cos(1.047196667 - H));
b = 255 * I / 3 * (1 + S * (1 - cos(H) / cos(1.047196667 - H)));
r = 255 * I / 3 * (1 - S);
} else {
H = H - 4.188787;
b = 255 * I / 3 * (1 + S * cos(H) / cos(1.047196667 - H));
r = 255 * I / 3 * (1 + S * (1 - cos(H) / cos(1.047196667 - H)));
g = 255 * I / 3 * (1 - S);
}
//set the output to the array
rgb[0] = r;
rgb[1] = g;
rgb[2] = b;
}