核心的转换公式:

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 }另一种方法:对彩色图像处理的时候,一般都是基于颜色空间来做的,比如要检测一片连续的蓝色,就可以基于颜色空间来实现分割。大家首先想到的是RGB,但是这里有个问题。RGB关联太大,每个通道都编入了亮度信息,容易受周围环境的处理,比如说光照不足。而HSI空间就不会。HSI空间是从人的视觉系统出发用色调(Hue), 色饱和度(Situration)和亮度(Intensity)来描述颜色,一旦用HSI空间就可以从色调通道中分离出蓝色色调,蓝色色调差不多在220左右。
下面要说的RGB到HSI空间的转换。我是用OPENCV来实现图像处理的,OPENCV读入图像是存储在IplImage结构中。对于彩色图像可以分开成三个通道存储 cvLoadImage(imageName, 1);三个通道依次是blue, green, red. 在OPENCV中并没有实现转化成HSI空间,这个我们得针对每个像素点自己手动写,公式在上面那个链接里。
上代码
// HSI.cpp : RGB  TO  HSI并显示出来

//
#include <stdio.h>
#include <math.h>
#include <cv.h>
#include <highgui.h>
#include <cxcore.h>
#include <cvaux.h>int min(int a, int b, int c);int main(int argc, char ** argv)
{IplImage * Img  = cvLoadImage(argv[1], 1);IplImage * HImg = cvCreateImage(cvGetSize(Img), IPL_DEPTH_8U, 1);IplImage * SImg = cvCreateImage(cvGetSize(Img), IPL_DEPTH_8U, 1);IplImage * IImg = cvCreateImage(cvGetSize(Img), IPL_DEPTH_8U, 1);    if( Rgb2Hsi(Img, HImg, SImg, IImg) == 0){printf("Convert Error!\n");exit(-1);}//高斯滤波先,以平滑图像
cvSmooth(SImg, SImg, CV_GAUSSIAN, 3, 0, 0, 0);
//    cvThreshold(SImg, SImg, 100, 255, CV_THRESH_BINARY);IplImage *pImgCanny = cvCreateImage(cvGetSize(SImg), IPL_DEPTH_8U, 1);cvCanny(SImg, pImgCanny, 50, 150, 3);cvNamedWindow("Img", 1);    cvNamedWindow("HImg", 1);cvNamedWindow("SImg", 1);cvNamedWindow("IImg", 1);cvShowImage("Img", Img);cvShowImage("HImg", HImg);cvShowImage("SImg", SImg);cvShowImage("IImg", IImg);cvWaitKey(0);return 0;
}int Rgb2Hsi(const IplImage* src, IplImage* dataH, IplImage* dataS, IplImage* dataI)
{//返回0:成功,1:失败
//输入为彩色图像src, 输出dataH,dataS,dataI,分别为HSI模型的H、S、I分量
int  y,x,offsetSrc,offsetHsi;int step,channels,step1;int r,g,b,minRgb;double cosThita,num,den,S,H;uchar *dataImg;uchar *dataS1;uchar *dataI1;uchar *dataH1;channels = src->nChannels;dataImg = (uchar *)src->imageData;dataI1 = (uchar *)dataI->imageData;dataH1=(uchar *)dataH->imageData;dataS1=(uchar *)dataS->imageData;if (channels!=3){printf("The input image is not 3-channels!\n");return 0;}step=src->widthStep;step1=dataI->widthStep;for (y=0; y<src->height; y++)for (x=0; x<src->width; x++){offsetSrc = y*step + x*channels;offsetHsi=y*step1+x;b = dataImg[offsetSrc]; g=dataImg[offsetSrc+1]; r=dataImg[offsetSrc+2];dataI1[offsetHsi] = (int)((r+g+b)/3+0.5);num=(2*r-g-b)/2;den=sqrt((r-g)*(r-g)+(r-b)*(g-b));if (den==0)den=0.01;cosThita=acos(num/den);minRgb = min(r, g, b);den=r+g+b;if (den==0)den=0.01;S=1-3*minRgb/den;dataS1[offsetHsi]=(int) (S*255+0.5);//将S分量和H分量都扩充到[0,255]区间以便于显示
//一般H分量在[0,2pi]之间,S在[0,1]之间
if (b<=g)H=cosThita/(2*3.14);elseH=(2*3.14-cosThita)/(2*3.14);dataH1[offsetHsi] = (int)(H*255+0.5);if (S==0)dataH1[offsetHsi]=0;}return 1;}int min(int a, int b, int c)
{int m = a;if(m > b)m = b;if( m > c)m = c;return m;
}

OpenCV实现RGB颜色空间和HSI颜色空间的相互转换相关推荐

  1. matlab hsi颜色,RGB 颜色空间转 HSI 颜色空间的matlab程序实现

    RGB 颜色空间转 HSI 颜色空间的matlab程序实现 程序实现的时候注意把RGB像素值归一化就是了,然后千千万万要根据公式来,不能大意,我之前就有theta为复数的情况,是sqrt对负数进行运算 ...

  2. MATLAB 将RGB颜色空间转为HSI颜色空间、LAB颜色空间 原理及程序

    一张彩色图像是由R.G.B三个通道组成,所以首先需要将彩色图像分为三个通道的图像. 以下是对猫图进行单通道提取得到的图像. HSI颜色空间 HSI[Hue-Saturation-Intensity(L ...

  3. HSI颜色空间及其应用

    from:http://nkwavelet.blog.163.com/blog/static/22775603820147197503722/ [摘要] 本文首先阐述HSI颜色模式的基本特性,然后介绍 ...

  4. 使用OpenCV实现RGB、HSI、CMYK颜色空间的转换

    RGB to HSI.CMYK的代码实现 前言: 在之前博文的基础上,我使用OpenCV2实现了RGB颜色空间向HIS.CMYK转换的代码.下列链接为各种经典颜色空间的介绍及转换公式的介绍. http ...

  5. matlab hsi颜色空间,RGB与HSI颜色空间互换函数(matlab)

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

  6. HSV与HSI颜色空间的区别以及和RGB之间的转换

    Gonzalez的Digital Image Processing中介绍了HSI颜色空间,以其中的圆锥模型为例 HSI(也称为HSL(Lightness))和HSV的区别可以这样理解 最本质的区别是V ...

  7. Opencv的RGB到HSV颜色空间转换

    从 RGB 到 HSL 或 HSV 的转换 设 (r, g, b) 分别是一个颜色的红.绿和蓝坐标,它们的值是在 0 到 1 之间的实数.设 max 等价于 r, g 和 b 中的最大者.设 min ...

  8. OpenCV最经典的3种颜色空间(cv2.cvtColor)及互相转换

    OpenCV最经典的3种颜色空间(cv2.cvtColor)及互相转换 1. 效果图 2. 原理 2.1 照明条件的重要性 2.2 OpenCV 中的3种颜色空间/模型 2.3 颜色空间的主要用途 3 ...

  9. opencv颜色识别python_opencv使用HSV颜色空间实现颜色识别

    一.颜色空间介绍 RGB 颜色空间是大家最熟悉的颜色空间,即三基色空间,任何一种颜色都可以由该三种 颜色混合而成.然而一般对颜色空间的图像进行有效处理都是在 HSV 空间进行的,HSV(色调 Hue, ...

最新文章

  1. 多模态深度学习:用深度学习的方式融合各种信息
  2. 程序员50题(JS版本)(九)
  3. 致远OA如何实施才可行
  4. 机器学习之生成学习算法
  5. 【译】How I hacked Google’s bug tracking system itself for $15,600 in bounties
  6. android 骨骼动画库,cocos creator spine骨骼动画组件使用
  7. 对linux中多线程编程中pthread_join的理解
  8. 【报告分享】2019抖音创作者生态报告.pdf
  9. 史上最强三千六百道脑筋急转弯(5)
  10. 用免费WiFi上网软件有什么好处
  11. c语言编程中句柄无效怎么解决,句柄无效,小编教你句柄无效怎么解决
  12. mysql姓氏笔画排序_php根据姓氏笔画排序怎么做
  13. three.js加载和使用纹理-specularMap使用高光贴图创建色彩鲜明的地球(vue中使用three.js77)
  14. 沙巴克皇宫门修复后需要重启服务器,关于传奇3.0的沙巴克设置问题解决
  15. 非线性控制1.0——S函数定义
  16. Litepal在没有存数据之前,需要在主线程中去先去存一些不必要的数据
  17. 同学早已年薪百万,你却还在朋友圈集赞
  18. chrome 插件导出与导入
  19. css——指定某个区域可垂直或水平滑动
  20. 关于捷联惯导解算的理解笔记

热门文章

  1. c++成员函数可以将this传递给普通函数
  2. html标签在html页面正常显示而不被解析
  3. unity字符串换行符_Unity中Text中首行缩进两个字符和换行的代码
  4. linux创建进程读共享写复制,Linux下进程的创建、执行和终止
  5. php中的几种跳转语句以及各自的特点,PHP中的跳转语句有且仅有break和continue两个语句。...
  6. oracle 并接去掉字符串,ORACLE删除字符-TRIM字符截取-substr查找字符-instr
  7. mysql触发器和存储过程_MySql的存储过程和触发器
  8. 安徽大学计算机科学与技术复试线,安徽大学计算机考研报录比及分数线
  9. Spring Cloud 2022.0.0 M1 发布:需Java 17、兼容Spring Boot 3
  10. 皮一皮:大型海王翻车现场...