基于HSI颜色模型实现去除照片的“红眼现象”
来源:互联网 发布:淘宝网怎么注册用户 编辑:程序博客网 时间:2024/04/29 18:38
- #include "opencv_libs.h"
- #include <highgui.h>
- #include <cv.h>
- #include <math.h>
- /*
- * 描述:基于HSI颜色模型消除红眼
- * 作者:qdsclove(qdsclove@gmail.com)
- * 时间:22:49 4/18 星期四 2013
- */
- /* 鼠标选择的矩形 */
- CvRect rect;
- /* 标记是否在画 */
- bool draw = false;
- /* 确定下来的眼睛矩形 */
- CvRect eyeRect;
- /* 是否选定眼睛区域 */
- bool isFinalRect = false;
- IplImage* img;
- IplImage* temp;
- IplImage* original;
- // 将HSI颜色空间的三个分量组合起来,便于显示
- IplImage* catHSImage(CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I)
- {
- IplImage* HSI_Image = cvCreateImage( cvGetSize( HSI_H ), IPL_DEPTH_8U, 3 );
- for(int i = 0; i < HSI_Image->height; i++)
- {
- for(int j = 0; j < HSI_Image->width; j++)
- {
- double d = cvmGet( HSI_H, i, j );
- int b = (int)(d * 255/360);
- d = cvmGet( HSI_S, i, j );
- int g = (int)( d * 255 );
- d = cvmGet( HSI_I, i, j );
- int r = (int)( d * 255 );
- cvSet2D( HSI_Image, i, j, cvScalar( b, g, r ) );
- }
- }
- return HSI_Image;
- }
- // 将HSI颜色模型的数据转换为RGB颜色模型的图像
- IplImage* HSI2RGBImage(CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I)
- {
- IplImage * RGB_Image = cvCreateImage(cvGetSize(HSI_H), IPL_DEPTH_8U, 3 );
- int iB, iG, iR;
- for(int i = 0; i < RGB_Image->height; i++)
- {
- for(int j = 0; j < RGB_Image->width; j++)
- {
- // 该点的色度H
- double dH = cvmGet( HSI_H, i, j );
- // 该点的色饱和度S
- double dS = cvmGet( HSI_S, i, j );
- // 该点的亮度
- double dI = cvmGet( HSI_I, i, j );
- double dTempB, dTempG, dTempR;
- // RG扇区
- if(dH < 120 && dH >= 0)
- {
- // 将H转为弧度表示
- dH = dH * 3.1415926 / 180;
- dTempB = dI * (1 - dS);
- dTempR = dI * ( 1 + (dS * cos(dH))/cos(3.1415926/3 - dH) );
- dTempG = (3 * dI - (dTempR + dTempB));
- }
- // GB扇区
- else if(dH < 240 && dH >= 120)
- {
- dH -= 120;
- // 将H转为弧度表示
- dH = dH * 3.1415926 / 180;
- dTempR = dI * (1 - dS);
- dTempG = dI * (1 + dS * cos(dH)/cos(3.1415926/3 - dH));
- dTempB = (3 * dI - (dTempR + dTempG));
- }
- // BR扇区
- else
- {
- dH -= 240;
- // 将H转为弧度表示
- dH = dH * 3.1415926 / 180;
- dTempG = dI * (1 - dS);
- dTempB = dI * (1 + (dS * cos(dH))/cos(3.1415926/3 - dH));
- dTempR = (3* dI - (dTempG + dTempB));
- }
- iB = dTempB * 255;
- iG = dTempG * 255;
- iR = dTempR * 255;
- cvSet2D( RGB_Image, i, j, cvScalar( iB, iG, iR ) );
- }
- }
- return RGB_Image;
- }
- // 利用HSI颜色空间去除红眼
- void EraseRedEye(IplImage* img, CvMat* HSI_H, CvMat* HSI_S, CvMat* HSI_I)
- {
- // 原始图像数据指针, HSI矩阵数据指针
- uchar* data;
- // rgb分量
- byte img_r, img_g, img_b;
- byte min_rgb; // rgb分量中的最小值
- // HSI分量
- float fHue, fSaturation, fIntensity;
- for(int i = 0; i < HSI_H->height; i++)
- {
- for(int j = 0; j < HSI_H->width; j++)
- {
- data = cvPtr2D(img, i, j, 0);
- img_b = *data;
- data++;
- img_g = *data;
- data++;
- img_r = *data;
- // Intensity分量[0, 1]
- fIntensity = (float)((img_b + img_g + img_r)/3)/255;
- // 得到RGB分量中的最小值
- float fTemp = img_r < img_g ? img_r : img_g;
- min_rgb = fTemp < img_b ? fTemp : img_b;
- // Saturation分量[0, 1]
- fSaturation = 1 - (float)(3 * min_rgb)/(img_r + img_g + img_b);
- // 计算theta角
- float numerator = (img_r - img_g + img_r - img_b ) / 2;
- float denominator = sqrt(
- pow( (img_r - img_g), 2 ) + (img_r - img_b)*(img_g - img_b) );
- // 计算Hue分量
- if(denominator != 0)
- {
- float theta = acos( numerator/denominator) * 180/3.14;
- if(img_b <= img_g)
- {
- fHue = theta ;
- }
- else
- {
- fHue = 360 - theta;
- }
- }
- else
- {
- fHue = 0;
- }
- // 赋值
- cvmSet( HSI_H, i, j, fHue );
- // 若为红眼像素,进行处理
- if( (fHue <= 45 || fHue >= 315 ) && fSaturation > 0.3)
- {
- // 设置该像素点饱和度为零
- cvmSet( HSI_S, i, j, 0);
- }
- else
- {
- cvmSet( HSI_S, i, j, fSaturation);
- }
- cvmSet( HSI_I, i, j, fIntensity );
- }
- }
- }
- void draw_rect(IplImage* img, CvRect rect)
- {
- cvRectangle( img,
- cvPoint( rect.x, rect.y ),
- cvPoint( rect.x + rect.width, rect.y + rect.height),
- cvScalar( 0xff, 0x00, 0x00) );
- }
- // 鼠标回调函数
- void my_mouse_callback( int event, int x, int y, int flags, void* param)
- {
- IplImage* image = (IplImage*) param;
- switch( event )
- {
- case CV_EVENT_MOUSEMOVE:
- {
- if(draw)
- {
- rect.width = x - rect.x;
- rect.height = y - rect.y;
- }
- }
- break;
- case CV_EVENT_LBUTTONDOWN:
- {
- draw = true;
- rect = cvRect( x, y, 0, 0 );
- }
- break;
- case CV_EVENT_LBUTTONUP:
- {
- draw = false;
- if(rect.width < 0)
- {
- rect.x += rect.width;
- rect.width *= -1;
- }
- if(rect.height < 0)
- {
- rect.y += rect.height;
- rect.height *= -1;
- }
- // draw
- draw_rect(image, rect);
- isFinalRect = true;
- eyeRect = cvRect( rect.x, rect.y, rect.width, rect.height );
- printf("(%d, %d), %d\t%d", rect.x, rect.y, rect.width, rect.height );
- }
- break;
- // 在右键按下时清除
- case CV_EVENT_RBUTTONDOWN:
- cvCopyImage(original, img);
- printf("clear.\n");
- break;
- }
- }
- int main()
- {
- IplImage* img = cvLoadImage("redeye3.jpg");
- rect = cvRect( -1, -1, 0, 0);
- eyeRect = cvRect(-1, -1, 0, 0);
- // 副本
- temp = cvCreateImage( cvGetSize( img ), img->depth, img->nChannels );
- original = cvCreateImage( cvGetSize( img ), img->depth, img->nChannels );
- cvCopyImage( img, temp );
- cvCopyImage( img, original );
- cvNamedWindow("去除红眼");
- cvSetMouseCallback("去除红眼", my_mouse_callback, (void*)img);
- while(1)
- {
- cvCopyImage(img, temp);
- if(draw)
- {
- draw_rect( temp , rect );
- }
- cvShowImage( "去除红眼", temp);
- if(cvWaitKey(15) == 27)
- break;
- if(isFinalRect == true)
- {
- goto erase;
- }
- }
- // 去除红眼
- erase:
- cvCopyImage(original, img);
- // 三个HSI空间数据矩阵
- CvMat* HSI_H = cvCreateMat( eyeRect.height, eyeRect.width, CV_32FC1 );
- CvMat* HSI_S = cvCreateMat( eyeRect.height, eyeRect.width, CV_32FC1 );
- CvMat* HSI_I = cvCreateMat( eyeRect.height, eyeRect.width, CV_32FC1 );
- // 设置图像感兴趣区域
- cvSetImageROI( img, eyeRect );
- EraseRedEye(img, HSI_H, HSI_S, HSI_I );
- IplImage* HSI_Image = catHSImage( HSI_H, HSI_S, HSI_I );
- IplImage* RGB_Image = HSI2RGBImage( HSI_H, HSI_S, HSI_I );
- cvShowImage("原始图像", img);
- cvCopyImage( RGB_Image, img );
- cvResetImageROI( img );
- cvShowImage("红眼擦除后", img );
- cvWaitKey(0);
- cvWaitKey(0);
- cvReleaseImage( &img );
- cvReleaseImage( &original );
- cvReleaseImage( &temp );
- cvReleaseImage( &HSI_Image );
- cvReleaseImage( &RGB_Image );
- cvReleaseMat( &HSI_H );
- cvReleaseMat( &HSI_S );
- cvReleaseMat( &HSI_I );
- cvDestroyAllWindows();
- return 0;
- }
首先鼠标选择照片的眼睛区域,然后程序实现处理。
效果图:
未来的实现:利用人脸检测自动定位到眼睛区域,不用鼠标选择眼睛区域。
0 0
- 基于HSI颜色模型实现去除照片的“红眼现象”
- 基于HSI颜色模型实现去除照片的“红眼现象”
- 基于HSI颜色模型实现去除照片的“红眼现象”
- 颜色模型的应用——利用HSI模型特性消除红眼
- HSI颜色模型
- 基于HSI空间颜色三角形的边缘检测方法
- 使用OpenCV实现RGB、HSI、CMYK颜色空间的转换
- Python实现RGB与HSI颜色空间的互换
- HSI、HSV、RGB、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV颜色模型的区别
- HSI、HSV、RGB、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV颜色模型的区别
- HSI、HSV、RGB、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV颜色模型的区别
- HSI、HSV、RGB、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV颜色模型的区别
- HSI、HSV、RGB、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV颜色模型的区别
- HSI、HSV、RGB、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV颜色模型的区别
- HSI、HSV、RGB、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV颜色模型的区别
- HSI、HSV、RGB、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV颜色模型的区别
- HSI、HSV、RGB、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV颜色模型的区别
- HSI、HSV、RGB、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV颜色模型的区别
- 日志-eye track
- HTML(网页设计)基础到加强
- 二叉树遍历(前序、中序、后序)递归与非递归
- Python编程学习——装饰器
- 正则表达式:
- 基于HSI颜色模型实现去除照片的“红眼现象”
- 散列表链接法用双向链表的原因
- 转圈打印二维数组
- 操作系统常见面试题
- C语言 输入日期判断一年中的第几天
- 解决字段名与实体类属性名不相同的冲突
- JavaSE基础 Item -- 抽象类Abstract
- 自定义DevExpress GridView Group时显示项目详细信息
- 刚体运动研究方法——欧拉角四元数