http://blog.csdn.net/dyllove98/article/details/9018149

http://1779598.blog.51cto.com/1769598/663423

RGB-->HSI

HSI-->RGB

  1 #include "opencv_libs.h"
2 #include <highgui.h>
3 #include <cv.h>
4 #include <math.h>
5
6 /*
7  * 描述：实现RGB颜色模型到HSI颜色模型之间的相互转换
8  * 作者：qdsclove(qdsclove@gmail.com)
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 {
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 }

HSI颜色模型为了显示，做了点处理，具体见代码。

：近看了一本数字图像处理的原版书。其中提供了RGB与HSI颜色空间之间的相互转变函数。已在matlab7.0中测试成功。不敢独享，贴出来供大家参考。

 1 function hsi=rgb2hsi(rgb)
2 %RGB2HSI Converts an RGB image to HSI
3 % HSI=RGB2HSI(rgb) converts an RGB image to HSI. The input image is
4 % assumed to be of size M-by-N-by-3, where the third dimension accounts
5 % for three image planes:red, green, and blue, in that order. If all RGB
6 % component images are equal, the HSI conversion is undefined. Ths input
7 % image can be of class double (with values in the rang[0,1]), uint8, or
8 % uint16.
9 % The output image, HSI, is of class double, where:
10 % hsi(:,:,1)= hue image normalized values to the range [0,1] by
11 % dividing all angle values by 2*pi.
12 % hsi(:,:,2)=saturation image, in the range [0,1].
13 % hsi(:,:,3)=intensity image, in the range [0,1].
14 %Extract the individual component images.
15 rgb=im2double(rgb);
16 r=rgb(:,:,1);
17 g=rgb(:,:,2);
18 b=rgb(:,:,3);
19 %Implement the conversion equations.
20 num=0.5*((r-g)+(r-b));
21 den=sqrt((r-g).^2+(r-b).*(g-b));
22 theta=acos(num./(den+eps));
23 H=theta;
24 H(b>g)=2*pi-H(b>g);
25 H=H/(2*pi);
26
27 num=min(min(r,g),b);
28 den=r+g+b;
29 den(den==0)=eps;
30 S=1-3.*num./den;
31 H(S==0)=0;
32 I=(r+g+b)/3;
33 %Combine all three results into an hsi image.
34 hsi=cat(3,H,S,I);
35
36
37 function rgb=hsi2rgb(hsi)
38 %HSI2RGB Converts an HSI image to RGB.
39 % HSI2RGB Converts an HSI image to RGB, where HSI is assumed to be of
40 % class double with:
41 % hsi(:,:,1)= hue image normalized values to the range [0,1] by
42 % dividing all angle values by 2*pi.
43 % hsi(:,:,2)=saturation image, in the range [0,1].
44 % hsi(:,:,3)=intensity image, in the range [0,1].
45 % The components of the output image are:
46 % rgb(:,:,1)=red;
47 % rgb(:,:,2)=green.
48 % rgb(:,:,3)=blue.
49 %Extract the individaul HSI component images.
50 H=hsi(:,:,1)*2*pi;
51 S=hsi(:,:,2);
52 I=hsi(:,:,3);
53
54 %Implement the conversion equations.
55 R=zeros(size(hsi,1),size(hsi,2));
56 G=zeros(size(hsi,1),size(hsi,2));
57 B=zeros(size(hsi,1),size(hsi,2));
58
59 % RG sector (0<=H<2*pi/3).
60 idx=find((0<=H)&(H<2*pi/3));
61 B(idx)=I(idx).*(1-S(idx));
62 R(idx)=I(idx).*(1+S(idx).*cos(H(idx))./cos(pi/3-H(idx)));
63 G(idx)=3*I(idx)-(R(idx)+B(idx));
64 %BG sector (2*pi/3<=H<4*pi/3).
65 idx=find((2*pi/3<=H)&(H<4*pi/3));
66 R(idx)=I(idx).*(1-S(idx));
67 G(idx)=I(idx).*(1+S(idx).*cos(H(idx)-2*pi/3)./cos(pi-H(idx)));
68 B(idx)=3*I(idx)-(R(idx)+G(idx));
69 %BR sector.
70 idx=find((4*pi/3<=H)&(H<=2*pi));
71 G(idx)=I(idx).*(1-S(idx));
72 B(idx)=I(idx).*(1+S(idx).*cos(H(idx)-4*pi/3)./cos(5*pi/3-H(idx)));
73 R(idx)=3*I(idx)-(G(idx)+B(idx));
74 %Combine all three results into an RGB image. Clip to [0,1] to compensate for floating-point arithmetic rounding effects.
75 rgb=cat(3,R,G,B);
76 rgb=max(min(rgb,1),0);
77
78 PS：eps在matlab中指最小的不等于0的正数，是matlab uint16数中最接近0的数，或者可以理解为可以使（1＋eps）>1为真的最小数。加eps也就是为了在尽可能不影响计算结果的前提下避免0/0的情况出现的方法！
79
80 PS2:此处提供的rgb转成hsi的程序，结果提供的是double类型的结果，既用图像的double类型的数据计算的结果。如果要转成我们在书上见到的那种（H指角度范围在0到360度之间，S指色度值在0到1之间，I指亮度值在0到1之间）形式，可以在现有的H值上乘以360换算。