【问题标题】:Trouble with HSI->RGB conversionHSI->RGB 转换出现问题
【发布时间】:2012-10-08 19:47:27
【问题描述】:

在尝试应用从 HSI 到 RGB 的转换时,我遇到了一些奇怪的问题,我正在尝试将其作为家庭作业的一部分。首先,这是我的原始图像:

original image(抱歉链接,我没有发布图片的代表)

我正在从具有 H、S、I 值 (0-255) 的图像转换。这是该图像在 RGB 颜色空间中的显示(Hue=red,sat=green,inten=blue):

HSI src image

在我看来,它看起来差不多……白色的花朵(高强度)是蓝色的,色调(红色)似乎随着不同颜色的花朵而变化。

所以现在我在某些框中对强度通道(显示为蓝色)进行了一些均衡,结果如下:

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);
        }
    }
}

有没有人发现代码中有任何问题或通过查看图像有任何见解?

【问题讨论】:

    标签: c++ image-processing rgb


    【解决方案1】:

    这里的基本思想是色调值从 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;
    
    }
    

    【讨论】:

      【解决方案2】:

      在计算依赖于它们的 cos 值之前,需要针对这三种情况调整 h 值。即:

              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;
      

      ...等

      【讨论】:

      • 非常感谢!我没有给出任何迹象表明这是必要的,所以我持怀疑态度,但它就像一个魅力!你帮了我很大的忙。也感谢关于检查最终值的建议,但我在 SetPixel() 方法中处理了这个问题;四舍五入到 256 的值(或可能会弹出的超出范围的值)被设置为最大值。
      • 还值得注意的是,需要重新排列其他一些语句才能获得正确的值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-27
      • 1970-01-01
      • 1970-01-01
      • 2018-02-25
      • 1970-01-01
      相关资源
      最近更新 更多