QT 实现彩色图亮度均衡,RGB和HSI空间互相转换
2013-11-14 09:25
656 查看
从昨天折腾到今天。再折腾下去我都要上主楼了
大致和灰度图均衡是一样的,主要是不能像平滑什么的直接对R,G,B三个分量进行。这样出来的图像时没法看的。因此我们要对亮度进行均衡。而HSI彩色空间中的分量I代表图像的亮度,和图像的彩色信息无关,所以它是我们perfect的折腾对象。
一、首先,就是把图像从RGB空间转换到HSI空间。原理我就很懒的截图了:
(引自《数字图像处理第三版》(中文版)P280)
实现代码如下:
二、当然在进行直方图均衡以后我们还要把HSI转换回RGB,要不然我不知道怎么把它画出来。原理还是截图如下:
代码如下:
第四行定义的otz这个变量就代表2pi/3,即120度,其实有了变量pi完全可以把它省略掉的。
最主要的注意就是除法中除数不能为零,所以第5行和第10行对于即将作为除数的temp都有个判断,其他的照着公式打就可了。头文件里要包含#include "cmath"。
三、最后对分量I进行直方图均衡,基本和对灰度图像进行直方图均衡时一样的步骤,然后再调用上面的HSItoRGB()函数把图像转回到RGB空间画出来就好了。最最最最最最最重要的一天(这个bug我调了很久)就是从HSI转回到RGB空间的时候分量R,G,B的值有可能超过255,一定要修改成255,见下面代码的73~75行!要不出来的图像会吓死你。
代码如下:
实现的效果如下图所示,左边是原图,右边是亮度均衡后的图像:
转载请注明出处:BY DEMONEDGE
大致和灰度图均衡是一样的,主要是不能像平滑什么的直接对R,G,B三个分量进行。这样出来的图像时没法看的。因此我们要对亮度进行均衡。而HSI彩色空间中的分量I代表图像的亮度,和图像的彩色信息无关,所以它是我们perfect的折腾对象。
一、首先,就是把图像从RGB空间转换到HSI空间。原理我就很懒的截图了:
(引自《数字图像处理第三版》(中文版)P280)
实现代码如下:
void RGBtoHSI(float r,float g,float b,float *h,float *s,float *i) { float pi = 3.1415926; float temp = sqrt((r-g)*(r-g)+(r-b)*(g-b)); temp = temp > 0?temp:0.01; if(b<=g) *h = acos(((r-g+r-b)/2.0)/temp); else *h = 2*pi - acos(((r-g+r-b)/2.0)/temp); temp = r+g+b>0?r+g+b:0.01; *s = 1.0-(3.0/temp)*min(r,g,b); *i = (r+g+b)/3.0; }
二、当然在进行直方图均衡以后我们还要把HSI转换回RGB,要不然我不知道怎么把它画出来。原理还是截图如下:
void HSItoRGB(float h,float s,float i,float *r,float *g,float *b) { float pi = 3.1415926; float otz =2*pi / 3; if(h >=0 && h < otz) { *b = i*(1.0-s); *r = i*(1.0+(s*cos(h))/(cos(pi/3.0-h))); *g = 3.0*i-(*b+*r); } else if(h >= otz && h < 2 * otz) { *r = i*(1-s); *g = i*(1+(s*cos(h-otz))/(cos(pi -h))); *b = 3*i-(*g+*r); } else { *g = i*(1-s); *b = i*(1+(s*cos(h-otz*2))/(cos(5*pi/6-h))); *r = 3*i-(*g+*b); } }
第四行定义的otz这个变量就代表2pi/3,即120度,其实有了变量pi完全可以把它省略掉的。
最主要的注意就是除法中除数不能为零,所以第5行和第10行对于即将作为除数的temp都有个判断,其他的照着公式打就可了。头文件里要包含#include "cmath"。
三、最后对分量I进行直方图均衡,基本和对灰度图像进行直方图均衡时一样的步骤,然后再调用上面的HSItoRGB()函数把图像转回到RGB空间画出来就好了。最最最最最最最重要的一天(这个bug我调了很久)就是从HSI转回到RGB空间的时候分量R,G,B的值有可能超过255,一定要修改成255,见下面代码的73~75行!要不出来的图像会吓死你。
代码如下:
void MainWindow::on_action_color_zhifang_triggered() { width = image_png.width(); height = image_png.height(); grayImg = QImage(width,height,QImage::Format_ARGB32); //存放HSI空间分量的结构体 typedef struct HSI{ float h; float s; float i; }hsi; //申请一个二维结构体数组,存放每个像素转换到HSI空间后三分量的值 hsi **p = new hsi*[height]; for(int i = 0;i < height;i++) p[i] = new hsi[height]; //遍历图像,调用函数RGBtoHSI()转换到HSI空间 float max = 0; for(int i = 0;i < width;i++) { for(int j = 0;j < height;j ++) { QRgb rgb = image_png.pixel(i,j); RGBtoHSI(qRed(rgb),qGreen(rgb),qBlue(rgb),&p[i][j].h,&p[i][j].s,&p[i][j].i); max = max > p[i][j].i?max:p[i][j].i; } } //qDebug()<<max; int n = (int)(max+0.5); //对分量I进行直方图均衡 int *II = new int[n+1]; float *IIPro = new float[n+1]; float *IITemp = new float[n+1]; float *IIJun = new float[n+1]; for(int i = 0;i <= n;i++) II[i] = 0; //计算频率,即nk for(int i = 0;i < width;i++) { for(int j = 0;j < height;j ++) { II[(int)(p[i][j].i+0.5)]++; } } //计算每个数量级出现的概率 for(int i = 0;i <= n;i++) { IIPro[i] = (II[i]*1.0)/(width*height); } //概率累加并计算均值 IITemp[0] = IIPro[0]; for(int i = 1;i <= n;i++) { IITemp[i] = IITemp[i-1]+IIPro[i]; IIJun[i]= n*IITemp[i]; } for(int i=0;i<width;i++) { for(int j=0;j<height;j++) { p[i][j].i = IIJun[(int)(p[i][j].i+0.5)]; float r,g,b; HSItoRGB(p[i][j].h,p[i][j].s,p[i][j].i,&r,&g,&b); r = r > 255?255:(int)(r+0.5); g = g > 255?255:(int)(g+0.5); b = b > 255?255:(int)(b+0.5); grayImg.setPixel(i,j,qRgb(r,g,b)); } } update(); }
实现的效果如下图所示,左边是原图,右边是亮度均衡后的图像:
转载请注明出处:BY DEMONEDGE
相关文章推荐
- QT 实现彩色图亮度均衡,RGB和HSI空间互相转换
- OpenCV实现RGB颜色空间和HSI颜色空间的相互转换
- OpenCV实现RGB颜色空间和HSI颜色空间的相互转换
- matlab RGB到HSI的彩色转换及实现
- OpenCV实现RGB颜色空间和HSI颜色空间的相互转换
- OpenCV实现RGB颜色空间和HSI颜色空间的相互转换
- matlab RGB到HSI的彩色转换及实现
- OpenCV实现RGB颜色空间和HSI颜色空间的相互转换
- opencv实现将RGB图像转换到HSI空间
- 使用OpenCV实现RGB、HSI、CMYK颜色空间的转换
- RGB空间与HSI空间的转换算法的C#实现
- Python实现RGB与HSI颜色空间的互换
- 数字图像处理 颜色空间RGB、HSI、CMYK、YUV的相互转换
- RGB不同彩色空间的转换公式
- 数据压缩原理与应用 实验一 彩色空间转换(YUVtoRGB)
- RGB不同彩色空间的转换公式
- VC编程实现色彩空间RGB与XYZ相互转换
- RGB彩色空间的不同转换公式
- 图像的RGB颜色空间和HSI空间的转换
- RGB彩色图像与灰度图像转换 opencv实现 代码及分析