参考自:http://www.cnblogs.com/qdsclove/archive/2013/04/18/3029738.html

基本的算法描述如下:

代码:

  1 #include "opencv_libs.h"
  2 #include <highgui.h>
  3 #include <cv.h>
  4 #include <math.h>
  5
  6 /*
  7  * 描述:基于HSI颜色模型消除红眼
  8  * 作者:qdsclove(qdsclove@gmail.com)
  9  * 时间:22:49 4/18 星期四 2013
 10  */
 11
 12 /* 鼠标选择的矩形 */
 13 CvRect rect;
 14 /* 标记是否在画 */
 15 bool draw = false;
 16 /* 确定下来的眼睛矩形 */
 17 CvRect eyeRect;
 18 /* 是否选定眼睛区域 */
 19 bool isFinalRect = false;
 20
 21 IplImage* img;
 22 IplImage* temp;
 23 IplImage* original;
 24
 25 // 将HSI颜色空间的三个分量组合起来,便于显示
 26 IplImage* catHSImage(CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I)
 27 {
 28     IplImage* HSI_Image = cvCreateImage( cvGetSize( HSI_H ), IPL_DEPTH_8U, 3 );
 29
 30     for(int i = 0; i < HSI_Image->height; i++)
 31     {
 32         for(int j = 0; j < HSI_Image->width; j++)
 33         {
 34             double d = cvmGet( HSI_H, i, j );
 35             int b = (int)(d * 255/360);
 36             d = cvmGet( HSI_S, i, j );
 37             int g = (int)( d * 255 );
 38             d = cvmGet( HSI_I, i, j );
 39             int r = (int)( d * 255 );
 40
 41             cvSet2D( HSI_Image, i, j, cvScalar( b, g, r ) );
 42         }
 43     }
 44     return HSI_Image;
 45 }
 46
 47 // 将HSI颜色模型的数据转换为RGB颜色模型的图像
 48 IplImage* HSI2RGBImage(CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I)
 49 {
 50     IplImage * RGB_Image = cvCreateImage(cvGetSize(HSI_H), IPL_DEPTH_8U, 3 );
 51
 52     int iB, iG, iR;
 53     for(int i = 0; i < RGB_Image->height; i++)
 54     {
 55         for(int j = 0; j < RGB_Image->width; j++)
 56         {
 57             // 该点的色度H
 58             double dH = cvmGet( HSI_H, i, j );
 59             // 该点的色饱和度S
 60             double dS = cvmGet( HSI_S, i, j );
 61             // 该点的亮度
 62             double dI = cvmGet( HSI_I, i, j );
 63
 64             double dTempB, dTempG, dTempR;
 65             // RG扇区
 66             if(dH < 120 && dH >= 0)
 67             {
 68                 // 将H转为弧度表示
 69                 dH = dH * 3.1415926 / 180;
 70                 dTempB = dI * (1 - dS);
 71                 dTempR = dI * ( 1 + (dS * cos(dH))/cos(3.1415926/3 - dH) );
 72                 dTempG = (3 * dI - (dTempR + dTempB));
 73             }
 74             // GB扇区
 75             else if(dH < 240 && dH >= 120)
 76             {
 77                 dH -= 120;
 78
 79                 // 将H转为弧度表示
 80                 dH = dH * 3.1415926 / 180;
 81
 82                 dTempR = dI * (1 - dS);
 83                 dTempG = dI * (1 + dS * cos(dH)/cos(3.1415926/3 - dH));
 84                 dTempB = (3 * dI - (dTempR + dTempG));
 85             }
 86             // BR扇区
 87             else
 88             {
 89                 dH -= 240;
 90
 91                 // 将H转为弧度表示
 92                 dH = dH * 3.1415926 / 180;
 93
 94                 dTempG = dI * (1 - dS);
 95                 dTempB = dI * (1 + (dS * cos(dH))/cos(3.1415926/3 - dH));
 96                 dTempR = (3* dI - (dTempG + dTempB));
 97             }
 98
 99             iB = dTempB * 255;
100             iG = dTempG * 255;
101             iR = dTempR * 255;
102
103             cvSet2D( RGB_Image, i, j, cvScalar( iB, iG, iR ) );
104         }
105     }
106     return RGB_Image;
107 }
108
109 // 利用HSI颜色空间去除红眼
110 void EraseRedEye(IplImage* img, CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I)
111 {
112     // 原始图像数据指针, HSI矩阵数据指针
113     uchar* data;
114
115     // rgb分量
116     byte img_r, img_g, img_b;
117     byte min_rgb;  // rgb分量中的最小值
118     // HSI分量
119     float fHue, fSaturation, fIntensity;
120
121     for(int i = 0; i < HSI_H->height; i++)
122     {
123         for(int j = 0; j < HSI_H->width; j++)
124         {
125              data = cvPtr2D(img, i, j, 0);
126              img_b = *data;
127              data++;
128              img_g = *data;
129              data++;
130              img_r = *data;
131
132              // Intensity分量[0, 1]
133              fIntensity = (float)((img_b + img_g + img_r)/3)/255;
134
135              // 得到RGB分量中的最小值
136              float fTemp = img_r < img_g ? img_r : img_g;
137              min_rgb = fTemp < img_b ? fTemp : img_b;
138              // Saturation分量[0, 1]
139              fSaturation = 1 - (float)(3 * min_rgb)/(img_r + img_g + img_b);
140
141              // 计算theta角
142              float numerator = (img_r - img_g + img_r - img_b ) / 2;
143              float denominator = sqrt(
144                  pow( (img_r - img_g), 2 ) + (img_r - img_b)*(img_g - img_b) );
145
146              // 计算Hue分量
147              if(denominator != 0)
148              {
149                  float theta = acos( numerator/denominator) * 180/3.14;
150
151                  if(img_b <= img_g)
152                  {
153                      fHue = theta ;
154                  }
155                  else
156                  {
157                      fHue = 360 - theta;
158                  }
159              }
160              else
161              {
162                  fHue = 0;
163              }
164
165              // 赋值
166              cvmSet( HSI_H, i, j, fHue );
167
168              // 若为红眼像素,进行处理
169              if( (fHue <= 45 || fHue >= 315 ) && fSaturation > 0.3)
170              {
171                  // 设置该像素点饱和度为零
172                  cvmSet( HSI_S, i, j, 0);
173              }
174              else
175              {
176                  cvmSet( HSI_S, i, j, fSaturation);
177              }
178              cvmSet( HSI_I, i, j, fIntensity );
179         }
180     }
181 }
182
183 void draw_rect(IplImage* img, CvRect rect)
184 {
185     cvRectangle( img,
186         cvPoint( rect.x, rect.y ),
187         cvPoint( rect.x + rect.width, rect.y + rect.height),
188         cvScalar( 0xff, 0x00, 0x00) );
189 }
190
191 // 鼠标回调函数
192 void my_mouse_callback( int event, int x, int y, int flags, void* param)
193 {
194     IplImage* image = (IplImage*) param;
195
196     switch( event )
197     {
198     case CV_EVENT_MOUSEMOVE:
199         {
200             if(draw)
201             {
202                 rect.width = x - rect.x;
203                 rect.height = y - rect.y;
204             }
205         }
206         break;
207     case CV_EVENT_LBUTTONDOWN:
208         {
209             draw = true;
210             rect = cvRect( x, y, 0, 0 );
211         }
212         break;
213     case CV_EVENT_LBUTTONUP:
214         {
215             draw = false;
216             if(rect.width < 0)
217             {
218                 rect.x += rect.width;
219                 rect.width *= -1;
220             }
221             if(rect.height < 0)
222             {
223                 rect.y += rect.height;
224                 rect.height *= -1;
225             }
226             // draw
227             draw_rect(image, rect);
228
229             isFinalRect = true;
230             eyeRect = cvRect( rect.x, rect.y, rect.width, rect.height );
231             printf("(%d, %d), %d\t%d", rect.x, rect.y, rect.width, rect.height );
232         }
233         break;
234         // 在右键按下时清除
235     case CV_EVENT_RBUTTONDOWN:
236         cvCopyImage(original, img);
237         printf("clear.\n");
238         break;
239     }
240 }
241
242 int main()
243 {
244     IplImage* img = cvLoadImage("redeye3.jpg");
245
246     rect = cvRect( -1, -1, 0, 0);
247     eyeRect = cvRect(-1, -1, 0, 0);
248
249     // 副本
250     temp = cvCreateImage( cvGetSize( img ), img->depth, img->nChannels );
251     original = cvCreateImage( cvGetSize( img ), img->depth, img->nChannels );
252     cvCopyImage( img, temp );
253     cvCopyImage( img, original );
254
255     cvNamedWindow("去除红眼");
256     cvSetMouseCallback("去除红眼", my_mouse_callback, (void*)img);
257
258     while(1)
259     {
260         cvCopyImage(img, temp);
261
262         if(draw)
263         {
264             draw_rect( temp , rect );
265         }
266
267         cvShowImage( "去除红眼", temp);
268
269         if(cvWaitKey(15) == 27)
270             break;
271
272         if(isFinalRect == true)
273         {
274             goto erase;
275         }
276     }
277     // 去除红眼
278 erase:
279     cvCopyImage(original, img);
280
281
282     // 三个HSI空间数据矩阵
283     CvMat* HSI_H = cvCreateMat( eyeRect.height, eyeRect.width, CV_32FC1 );
284     CvMat* HSI_S = cvCreateMat( eyeRect.height, eyeRect.width, CV_32FC1 );
285     CvMat* HSI_I = cvCreateMat( eyeRect.height, eyeRect.width, CV_32FC1 );
286
287     // 设置图像感兴趣区域
288     cvSetImageROI( img, eyeRect );
289
290     EraseRedEye(img, HSI_H, HSI_S, HSI_I );
291
292     IplImage* HSI_Image = catHSImage( HSI_H, HSI_S, HSI_I );
293     IplImage* RGB_Image = HSI2RGBImage( HSI_H, HSI_S, HSI_I );
294
295     cvShowImage("原始图像", img);
296     cvCopyImage( RGB_Image, img );
297
298     cvResetImageROI( img );
299     cvShowImage("红眼擦除后", img );
300
301     cvWaitKey(0);
302     cvWaitKey(0);
303
304     cvReleaseImage( &img );
305     cvReleaseImage( &original );
306     cvReleaseImage( &temp );
307     cvReleaseImage( &HSI_Image );
308     cvReleaseImage( &RGB_Image );
309     cvReleaseMat( &HSI_H );
310     cvReleaseMat( &HSI_S );
311     cvReleaseMat( &HSI_I );
312
313     cvDestroyAllWindows();
314
315     return 0;
316 }

首先鼠标选择照片的眼睛区域,然后程序实现处理。

效果图:

基于HSI颜色模型实现去除照片的“红眼现象”相关推荐

  1. 【3000字扫盲】来搞“颜色“!RGB/HSV/HSI颜色模型

    一:RGB三原色 RGB三原色是怎么来的呢? 当然,是因为他们三者可以调配出其他所有颜色.但为什么偏偏是这三个颜色呢? 人眼有四种感光细胞,分别是三种锥状感光细胞,分别感知红,绿,蓝三色,以及感知黑白 ...

  2. 一种基于HSV颜色模型的动态调色板算法研究与应用

    本文相关的论文<一种基于HSV颜色模型的动态调色板算法研究与应用>录用并在<工业控制计算机>2022年第7期(7月25日出刊)上发表.此处内容仅做交流使用. 本文相关的成果已发 ...

  3. Android上基于HSV颜色模型实现取色盘功能

    HSV色彩空间 HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model).这个 ...

  4. 无聊的时候写了个颜色识别算法,基于RGB颜色模型

    halcon是个好东西,里面有诸多的"轮子",随着版本的迭代"轮子"会越来越多越来越全面和完善.我用的halcon12里面有一种颜色识别的算法,它这种颜色识别是 ...

  5. 基于OpenCV的火焰检测(三)——HSI颜色判据

    上文向大家介绍了如何用最简单的RGB判据来初步提取火焰区域,现在我要给大家分享的是一种更加直观的判据--HSI判据.为什么说HSI判据是更加直观的判据呢?老规矩,先介绍一下HSI色彩模型:HSI颜色模 ...

  6. HSI、HSV、RGB、CMY、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV等颜色模型简介

    基本概念 所谓颜色模型就是指某个三维颜色空间中的一个可见光子集,它包含某个颜色域的所有颜色.例如,RGB颜色模型就是三维直角坐标颜色系统的一个单位正方体.颜色模型的用途是在某个颜色域内方便的指定颜色, ...

  7. 视觉系统照明模型 光通量,辐照度,颜色模型(RGB,HSV,CMYK)

    简述对视觉系统照明模型的基本理解 1.光通量 强调光的强度,指人眼所能感受到的辐射功率,他等于单位时间内某一波段的辐射能量和该波段的相对视见率的乘积.符号是φ,单位位lm(流明),通常1lm=0.00 ...

  8. 基于HSI空间颜色三角形的边缘检测方法

    基于HSI空间颜色三角形的边缘检测方法 摘 要:利用像素点的颜色坐标H.S.I构建像素的颜色三角形,计算该三角形的面积和边长.根据面积以及边长的差值确定该像素点是否为彩色图像的边缘点.这种边缘检测方法 ...

  9. MATLAB中颜色模型介绍级各模型之间转换(RGB、HSV、NTSC、YCbCr、HSI)

    1.颜色模型定义 2.各颜色模型简介 3.颜色模型的转换 一.颜色模型定义 颜色模型:某个三维颜色空间中的一个可见光子集,它包含某个颜色域的所有颜色.例如,RGB颜色模型就是三维直角坐标颜色系统的一个 ...

最新文章

  1. 干货|建议初创团队起初也要构建分布式应用
  2. 费曼学习法与孔子温故知新学习法为两大重要学习法,前者外向表现,后者内省提升
  3. 最前线|阿里大文娱板块Q3营收同比增长20%,优酷及UC业务带动显著
  4. uwsgi部署到nginx出现invalid request block size: 4161 (max 4096)...skip问题(亲测)
  5. 蒋涛,CSDN创始人,俺村的骄傲
  6. hadoop日常运维
  7. CF980D Perfect Groups
  8. pytorch之trainer.zero_grad()
  9. Linux下压缩包生成与解压命令以及进度
  10. Soul网关源码解析目录
  11. 马蹄疾 | 聊聊你可能并没有完全掌握的 Flex 布局:从概念入手,丝丝入扣
  12. SpringCloudAlibaba电商项目实战
  13. App逆向-安卓环境搭建-LineageOS刷机指南
  14. 网站申请服务器,网站申请服务器空间
  15. hinet邮箱密码可以破解?
  16. C++实现ID3决策树(UCI DNA数据集)
  17. javascript轮播技术
  18. 闲话自动驾驶的工程化落地
  19. Restful-API设计最佳实战--Django播客系统(五)
  20. 赵国荣教授治疗病毒性肝病临床经验述要

热门文章

  1. EasyExcel删除模版Sheet页
  2. 数据库系统概述---第二章关系数据库
  3. AE502 112种创意视频字幕动画呼出线框文字标题效果包括PR预设与扩展脚本ae模板
  4. Petya and Inequiations 题解
  5. 微信图文中出现了腾讯视频时,教你弄到不能直接获取的视频原始地址的方法~
  6. 全国各地dns服务器列表
  7. SDUT第二次选拔赛 7-2魔镜与抽卡
  8. 计算算法的时间复杂度
  9. Tushare不止数字!新文字特色数据 ---(4)
  10. 自媒体人都在用的免费音效素材网站