1

宿題の一部としてHSIからRGBに変換しようとすると、奇妙な問題が発生します。まず、私の元の画像は次のとおりです。

元の画像(リンクについては申し訳ありませんが、画像を投稿する担当者がいません)

H、S、I値(0〜255)の画像から変換しています。これは、RGB色空間(色相=赤、sat =緑、inten =青)でのその画像の表示です。

HSIsrcイメージ

私にはそれはほぼ正しいように見えます...白い花(高輝度)は青で、色相(赤)は異なる色の花で変化しているように見えます。

だから今、私はいくつかのボックスで強度チャンネル(ディスプレイの青)でいくつかの等化を行い、これをもたらします:

HSIイコライズされた画像: http://i.imgur.com/hgk9K.png ((2つ以上のハイパーリンクの担当者がいないため、これらをコピーパスタする必要があります))

大したことはありません。正確には見えませんが、言うのは難しく、関心領域ボックス以外はすべて同じです。

ここに問題があります。これをRGBに変換し直した後、次の結果が得られます。

変換された画像: http://i.imgur.com/6wEyw.png

ここで何が問題なのかわかりません。緑は問題ないように見えますが、一部の赤/青のピクセルは最大になっているようです。3つのボックスは期待どおりにあり、内容はかなり混乱しているように見えますが、それは私の等化関数からのものである可能性があるため、ここでは大きな問題ではありません。これらのボックスの外側はすべて元の画像とほぼ同じになっているはずですが、どういうわけかごちゃ混ぜになっています。

念のため、コードを何度も調べて、括弧とデータ型のキャストを追加しましたが、それでも問題を見つけることができません。数式は正しいと確信していますが、ピクセル値の計算方法に問題がないはずです。

これが私が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);
        }
    }
}

誰かがコードに問題を見つけたり、画像を見て何か洞察を持っていますか?

4

2 に答える 2

2

ここでの基本的な考え方は、色相値を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;

}
于 2016-08-22T14:40:48.967 に答える
1

h値は、それらに依存するcos値を計算する前に、3つのケースについて調整する必要があります。すなわち:

        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;

...など

于 2012-10-08T20:10:05.137 に答える