图像RGB与HSI相互转换的C语言代码

直接 PO 代码:

  1 #include <stdio.h>
  2 #include <math.h>
  3 #include "graphics.h"
  4 
  5 
  6 /* 三通道数据,用于保存RGB或HSI图像数据 */
  7 typedef struct {
  8     double *channel1;
  9     double *channel2;
 10     double *channel3;
 11 } ThreeChannels;
 12 /* 三通道数据的初始化 */
 13 void InitThreeChannels(ThreeChannels &tc, int w, int h) {
 14     tc.channel1 = (double *)malloc(w*h*sizeof(double));
 15     tc.channel2 = (double *)malloc(w*h*sizeof(double));
 16     tc.channel3 = (double *)malloc(w*h*sizeof(double));
 17 }
 18 /* 三通道数据的释放 */
 19 void FreeThreeChannels(ThreeChannels &tc) {
 20     free(tc.channel1);
 21     free(tc.channel2);
 22     free(tc.channel3);
 23 }
 24 
 25 /*
 26 功能: 在整型数组中找到最小值和最大值 
 27 输入: 整型数组;数组大小;接收最小值;接收最大值 
 28 结果: 得到数组中的最小值和最大值
 29 */
 30 void GetMinMaxInt(int *arr, int n, int &min, int &max);
 31 /*
 32 功能: 在浮点型数组中找到最小值和最大值 
 33 输入: 浮点型数组;数组大小;接收最小值;接收最大值 
 34 结果: 得到数组中的最小值和最大值 
 35 */
 36 void GetMinMaxDouble(double *arr, int n, double &min, double &max);
 37 /*
 38 功能: 打印RGB彩色图像 
 39 输入: ThreeChannels三通道数据的结构体,宽高 
 40 结果: 打印RGB彩色图像 
 41 */
 42 void PrintRGBImage(ThreeChannels &tc, int w, int h);
 43 /*
 44 功能: 根据文件名获取RGB彩色图像 
 45 输入: 文件名;ThreeChannels三通道数据的结构体,宽高;是否打印图像 
 46 结果: 将获取到的RGB图像保存在ThreeChannels结构体中 
 47 */
 48 void GetImageRGB(char *file, ThreeChannels &tc, int w, int h, int mode);
 49 /*
 50 功能: RGB转为HSI 
 51 输入: RGB三通道结构体,HSI三通道结构体 
 52 结果: 将RGB三通道转为HSI三通道 
 53 */
 54 void RGB2HSI(ThreeChannels &rgb, int w, int h, ThreeChannels &hsi);
 55 /*
 56 功能: HSI转为RGB 
 57 输入: HSI三通道结构体,RGB三通道结构体 
 58 结果: 将HSI三通道转为RGB三通道 
 59 */
 60 void HSI2RGB(ThreeChannels &hsi, int w, int h, ThreeChannels &rgb);
 61 
 62 
 63 int main() {
 64     int w=972, h=607;
 65     char file_name[] = "kanna.jpg";
 66     
 67     initgraph(w, h, 0);
 68     setcaption("RGB与HSI相互转换");
 69     
 70     ThreeChannels imgRGB;
 71     InitThreeChannels(imgRGB, w, h);
 72     
 73     // 获取RGB彩色图像 
 74     GetImageRGB(file_name, imgRGB, w, h, 0);
 75     
 76     // RGB转为HSI 
 77     ThreeChannels imgHSI;
 78     InitThreeChannels(imgHSI, w, h);
 79     RGB2HSI(imgRGB, w, h, imgHSI);
 80     
 81 //    double min, max;
 82 //    GetMinMaxDouble(imgHSI.channel1, w*h, min, max);
 83 //    printf("%lf %lf\n", min, max);
 84     
 85     // HSI转为RGB 
 86     ThreeChannels imgRGBtmp;
 87     InitThreeChannels(imgRGBtmp, w, h);
 88     HSI2RGB(imgHSI, w, h, imgRGBtmp);
 89     
 90     // 打印最终结果 
 91     PrintRGBImage(imgRGBtmp, w, h);
 92     
 93     getch();
 94     FreeThreeChannels(imgRGB);
 95     FreeThreeChannels(imgHSI);
 96     FreeThreeChannels(imgRGBtmp);
 97     closegraph();
 98     return 0;
 99 }
100 
101 
102 
103 /* 在整型数组中找到最小值和最大值 */
104 void GetMinMaxInt(int *arr, int n, int &min, int &max) {
105     min = 0x7fffffff;
106     max = 0x80000000;
107     for(int i=0; i<n; i++) {
108         if(arr[i] > max) max = arr[i];
109         if(arr[i] < min) min = arr[i];
110     }
111 }
112 /* 在浮点型数组中找到最小值和最大值 */
113 void GetMinMaxDouble(double *arr, int n, double &min, double &max) {
114     min = 1.7976931348623158e+308;
115     max = 2.2250738585072014e-308;
116     for(int i=0; i<n; i++) {
117         if(arr[i] > max) max = arr[i];
118         if(arr[i] < min) min = arr[i];
119     }
120 }
121 
122 
123 /* 打印RGB彩色图像 */
124 void PrintRGBImage(ThreeChannels &tc, int w, int h) {
125     color_t color;
126     int i, j, red, green, blue;
127     for(i=0; i<w; i++) {
128         for(j=0; j<h; j++) {
129             red = *(tc.channel1+h*i+j) * 255.0;
130             green = *(tc.channel2+h*i+j) * 255.0;
131             blue = *(tc.channel3+h*i+j) * 255.0;
132             color = EGERGB(red, green, blue);
133             putpixel(i, j, color);
134         }
135     }
136 }
137 /* 根据文件名获取RGB彩色图像 */
138 void GetImageRGB(char *file, ThreeChannels &tc, int w, int h, int mode) {
139     color_t color;
140     int i, j, red, green, blue;
141     PIMAGE pimg = newimage();
142     getimage(pimg, file, w, h);
143     
144     for(i=0; i<w; i++) {
145         for(j=0; j<h; j++) {
146             color = getpixel(i, j, pimg);
147             red = EGEGET_R(color);
148             green = EGEGET_G(color);
149             blue = EGEGET_B(color);
150             *(tc.channel1+h*i+j) = red / 255.0;
151             *(tc.channel2+h*i+j) = green / 255.0;
152             *(tc.channel3+h*i+j) = blue / 255.0;
153         }
154     }
155     // 是否打印RGB彩色图像 
156     if(mode) { 
157         PrintRGBImage(tc, w, h);
158     }
159     delimage(pimg);
160 }
161 /* RGB转为HSI */
162 void RGB2HSI(ThreeChannels &rgb, int w, int h, ThreeChannels &hsi) {
163     double rr, gg, bb, theta, ii, ss, hh, min_r_g_b;
164     int i, j;
165     for(i=0; i<w; i++) {
166         for(j=0; j<h; j++) {
167             rr = *(rgb.channel1+h*i+j);
168             gg = *(rgb.channel2+h*i+j);
169             bb = *(rgb.channel3+h*i+j);
170             
171             min_r_g_b = rr<gg ? rr:gg;
172             min_r_g_b = bb<min_r_g_b ? bb:min_r_g_b;
173             
174             /*
175             这有个小细节,且很容易被忽略
176             不能通过rr==gg==bb来避免除零的风险,这样仍然是错误的
177             而是如下这样 
178             */
179             if(rr==gg && rr==bb) theta=PI/2.0;
180             else theta = acos(0.5 * ((rr-gg)+(rr-bb)) / sqrt((rr-gg)*(rr-gg) + (rr-bb)*(gg-bb)));
181             hh = bb>gg ? (2.0*PI-theta):theta;
182             ii = 1.0/3.0 * (rr+gg+bb);
183             ss = 1.0 - min_r_g_b/ii;
184             
185             *(hsi.channel1+h*i+j) = hh;
186             *(hsi.channel2+h*i+j) = ss;
187             *(hsi.channel3+h*i+j) = ii;
188         }
189     }
190 }
191 /* HSI转为RGB */
192 void HSI2RGB(ThreeChannels &hsi, int w, int h, ThreeChannels &rgb) {
193     double ii, ss, hh, theta, rr, gg, bb;
194     int i, j;
195     
196     for(i=0; i<w; i++) {
197         for(j=0; j<h; j++) {
198             hh = *(hsi.channel1+h*i+j);
199             ss = *(hsi.channel2+h*i+j);
200             ii = *(hsi.channel3+h*i+j);
201             
202             if(hh>=0.0 && hh<(PI*120.0/180.0)) {
203                 bb = ii * (1.0-ss);
204                 rr = ii * (1.0 + ss*cos(hh) / cos((PI*60.0/180.0)-hh));
205                 gg = 3.0*ii - (rr+bb);
206             } else if(hh>=(PI*120.0/180.0) && hh<(PI*240.0/180.0)) {
207                 hh -= PI*120.0/180.0;
208                 rr = ii * (1.0-ss);
209                 gg = ii * (1.0 + ss*cos(hh) / cos((PI*60.0/180.0)-hh));
210                 bb = 3.0*ii - (rr+gg);
211             } else if(hh>=(PI*240.0/180.0) && hh<(PI*360.0/180.0)) {
212                 hh -= PI*240.0/180.0;
213                 gg = ii * (1.0-ss);
214                 bb = ii * (1.0 + ss*cos(hh) / cos((PI*60.0/180.0)-hh));
215                 rr = 3.0*ii - (gg+bb);
216             }
217             
218             *(rgb.channel1+h*i+j) = rr;
219             *(rgb.channel2+h*i+j) = gg;
220             *(rgb.channel3+h*i+j) = bb;
221         }
222     }
223 }

 

上一篇:计算机视觉OpenCv学习笔记--第三篇 色彩空间类型转换


下一篇:护眼色的RGB值