HSI颜色空间和RGB颜色空间之间的相互转换

HSI-->RGB

具体的数学公式参照冈萨雷斯版《数字图像处理(第三版)》432-434页,中译版的260-261页。

下面贴代码:

复制代码
  1 #include "opencv_libs.h"
  2 #include <highgui.h>
  3 #include <cv.h>
  4 #include <math.h>
  5 
  6 /*
  7  * 描述:实现RGB颜色模型到HSI颜色模型之间的相互转换
  8  * 作者:qdsclove([email protected])
  9  * 时间:16:01 4/17 星期三 2013
 10  */
 11 
 12 // 将HSI颜色空间的三个分量组合起来,便于显示
 13 IplImage* catHSImage(CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I)
 14 {
 15     IplImage* HSI_Image = cvCreateImage( cvGetSize( HSI_H ), IPL_DEPTH_8U, 3 );
 16 
 17     for(int i = 0; i < HSI_Image->height; i++)
 18     {
 19         for(int j = 0; j < HSI_Image->width; j++)
 20         {
 21             double d = cvmGet( HSI_H, i, j );
 22             int b = (int)(d * 255/360);
 23             d = cvmGet( HSI_S, i, j );
 24             int g = (int)( d * 255 );
 25             d = cvmGet( HSI_I, i, j );
 26             int r = (int)( d * 255 );
 27 
 28             cvSet2D( HSI_Image, i, j, cvScalar( b, g, r ) );
 29         }
 30     }
 31 
 32     return HSI_Image;
 33 }
 34 
 35 // 将HSI颜色模型的数据转换为RGB颜色模型的图像
 36 IplImage* HSI2RGBImage(CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I)
 37 {
 38     IplImage * RGB_Image = cvCreateImage(cvGetSize(HSI_H), IPL_DEPTH_8U, 3 );
 39 
 40     int iB, iG, iR;
 41     for(int i = 0; i < RGB_Image->height; i++)
 42     {
 43         for(int j = 0; j < RGB_Image->width; j++)
 44         {
 45             // 该点的色度H
 46             double dH = cvmGet( HSI_H, i, j );
 47             // 该点的色饱和度S
 48             double dS = cvmGet( HSI_S, i, j );
 49             // 该点的亮度
 50             double dI = cvmGet( HSI_I, i, j );
 51 
 52             double dTempB, dTempG, dTempR;
 53             // RG扇区
 54             if(dH < 120 && dH >= 0)
 55             {
 56                 // 将H转为弧度表示
 57                 dH = dH * 3.1415926 / 180;
 58                 dTempB = dI * (1 - dS);
 59                 dTempR = dI * ( 1 + (dS * cos(dH))/cos(3.1415926/3 - dH) );
 60                 dTempG = (3 * dI - (dTempR + dTempB)); 
 61             }
 62             // GB扇区
 63             else if(dH < 240 && dH >= 120)
 64             {
 65                 dH -= 120;
 66                                 
 67                 // 将H转为弧度表示
 68                 dH = dH * 3.1415926 / 180;
 69 
 70                 dTempR = dI * (1 - dS);
 71                 dTempG = dI * (1 + dS * cos(dH)/cos(3.1415926/3 - dH));
 72                 dTempB = (3 * dI - (dTempR + dTempG));
 73             }
 74             // BR扇区
 75             else 
 76             {
 77                 dH -= 240;
 78 
 79                 // 将H转为弧度表示
 80                 dH = dH * 3.1415926 / 180;
 81 
 82                 dTempG = dI * (1 - dS);
 83                 dTempB = dI * (1 + (dS * cos(dH))/cos(3.1415926/3 - dH));
 84                 dTempR = (3* dI - (dTempG + dTempB));
 85             }
 86 
 87             iB = dTempB * 255;
 88             iG = dTempG * 255;
 89             iR = dTempR * 255;
 90 
 91             cvSet2D( RGB_Image, i, j, cvScalar( iB, iG, iR ) );
 92         }
 93     }
 94 
 95     return RGB_Image;
 96 }
 97 
 98 
 99 int main()
100 {
101     IplImage* img = cvLoadImage("lena.bmp");
102 
103     // 三个HSI空间数据矩阵
104     CvMat* HSI_H = cvCreateMat( img->height, img->width, CV_32FC1 );
105     CvMat* HSI_S = cvCreateMat( img->height, img->width, CV_32FC1 );
106     CvMat* HSI_I = cvCreateMat( img->height, img->width, CV_32FC1 );
107 
108     // 原始图像数据指针, HSI矩阵数据指针
109     uchar* data;
110 
111     // rgb分量
112     byte img_r, img_g, img_b;
113     byte min_rgb;  // rgb分量中的最小值
114     // HSI分量
115     float fHue, fSaturation, fIntensity; 
116 
117     for(int i = 0; i < img->height; i++)
118     {
119         for(int j = 0; j < img->width; j++)
120         {
121              data = cvPtr2D(img, i, j, 0);  
122              img_b = *data;
123              data++;
124              img_g = *data;
125              data++;
126              img_r = *data;
127 
128              // Intensity分量[0, 1]
129              fIntensity = (float)((img_b + img_g + img_r)/3)/255;
130 
131              // 得到RGB分量中的最小值
132              float fTemp = img_r < img_g ? img_r : img_g;
133              min_rgb = fTemp < img_b ? fTemp : img_b;
134              // Saturation分量[0, 1]
135              fSaturation = 1 - (float)(3 * min_rgb)/(img_r + img_g + img_b);
136 
137              // 计算theta角
138              float numerator = (img_r - img_g + img_r - img_b ) / 2;
139              float denominator = sqrt( 
140                  pow( (img_r - img_g), 2 ) + (img_r - img_b)*(img_g - img_b) );
141 
142              // 计算Hue分量
143              if(denominator != 0)
144              {
145                  float theta = acos( numerator/denominator) * 180/3.14;
146                  
147                  if(img_b <= img_g)
148                  {
149                      fHue = theta ;
150                  }
151                  else
152                  {
153                      fHue = 360 - theta;
154                  }
155              }
156              else
157              {
158                  fHue = 0;
159              }
160 
161              // 赋值
162              cvmSet( HSI_H, i, j, fHue );
163              cvmSet( HSI_S, i, j, fSaturation);
164              cvmSet( HSI_I, i, j, fIntensity );
165         }
166     }
167 
168     IplImage* HSI_Image = catHSImage( HSI_H, HSI_S, HSI_I );
169     IplImage* RGB_Image = HSI2RGBImage( HSI_H, HSI_S, HSI_I );
170 
171     cvShowImage("img", img);
172     cvShowImage("HSI Color Model", HSI_Image);
173     cvShowImage("RGB Color Model", RGB_Image);
174 
175     cvWaitKey(0);
176 
177     cvReleaseImage( &img );
178     cvReleaseImage( &HSI_Image );
179     cvReleaseImage( &RGB_Image );
180     cvReleaseMat( &HSI_H);
181     cvReleaseMat( &HSI_S);
182     cvReleaseMat( &HSI_I);
183 
184     cvDestroyAllWindows();
185 
186     return 0;
187 }
复制代码

测试图像为彩色Lena图,运行结果如下:

猜你喜欢

转载自blog.csdn.net/liumoude6/article/details/78406858