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

来源:互联网 发布:成都网络营销优化 编辑:程序博客网 时间:2024/04/30 07:47

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                  else152                  {153                      fHue = 360 - theta;154                  }155              }156              else157              {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图,运行结果如下: