转载自:
http://blog.csdn.net/dyllove98/article/details/9018149
http://1779598.blog.51cto.com/1769598/663423
关于HSI颜色空间参照维基百科:http://zh.wikipedia.org/wiki/HSI%E8%89%B2%E5%BD%A9%E5%B1%AC%E6%80%A7%E6%A8%A1%E5%BC%8F
也可参考清华大学图像处理课件:http://media.cs.tsinghua.edu.cn/~ahz/digitalimageprocess/chapter18/chapt18_ahz.htm
下面是别人利用opencv来实现的RGB转化为HSI空间
核心的转换公式:
RGB-->HSI
截图来自中科院刘定生老师的《数字图像处理与分析》课件。
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(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 { 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图,运行结果如下:
左图为显示出来的HSI颜色模型图,右图为RGB颜色模型图。
HSI颜色模型为了显示,做了点处理,具体见代码。
下面是别人利用matlab来实现的RGB转化为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换算。