基于HSI颜色模型实现去除照片的“红眼现象”
来源:互联网 发布:中天证券交易软件 编辑:程序博客网 时间:2024/04/29 23:33
接上篇博文中的RGB颜色模型转换为HSI颜色模型,做了消除红眼的算法。
基本的算法描述如下:
代码:
#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++){// 该点的色度Hdouble dH = cvmGet( HSI_H, i, j );// 该点的色饱和度Sdouble 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;}
首先鼠标选择照片的眼睛区域,然后程序实现处理。
效果图:
未来的实现:利用人脸检测自动定位到眼睛区域,不用鼠标选择眼睛区域。
- 基于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颜色模型的区别
- 指针动态申请内存的问题
- POJ 2528 Mayor's posters (线段树+离散化)
- HDOJ 1284 钱币兑换问题 (求多重背包恰好装满总方案数)
- VS--安装VS2010出现VC9.0 Runtime问题的解决方法
- 求1至n的和
- 基于HSI颜色模型实现去除照片的“红眼现象”
- 二维数组的动态分配及参数传递
- 旧版本的ATM
- 硬盘参数释疑
- 一个简洁的CentOS 输入法的安装方法
- TCP/IP协议栈的基本工作原理
- Query on The Trees
- [Python]正则课程 --再次回顾
- 为什么不能给类里面的非static非const变量赋初值