OpenCV实现RGB颜色空间和HSI颜色空间的相互转换
RGB-->HSI
具体的数学公式参照冈萨雷斯版《数字图像处理(第三版)》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颜色模型为了显示,做了点处理,具体见代码。
参考知识库
您还没有登录,请 [登录]或 [注册]
具体的数学公式参照冈萨雷斯版《数字图像处理(第三版)》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颜色模型为了显示,做了点处理,具体见代码。