从昨天折腾到今天。再折腾下去我都要上主楼了 

大致和灰度图均衡是一样的,主要是不能像平滑什么的直接对R,G,B三个分量进行。这样出来的图像时没法看的。因此我们要对亮度进行均衡。而HSI彩色空间中的分量I代表图像的亮度,和图像的彩色信息无关,所以它是我们perfect的折腾对象。

一、首先,就是把图像从RGB空间转换到HSI空间。原理我就很懒的截图了:

(引自《数字图像处理第三版》(中文版)P280)
实现代码如下:
 1 void RGBtoHSI(float r,float g,float b,float *h,float *s,float *i)
2 {
3 float pi = 3.1415926;
4 float temp = sqrt((r-g)*(r-g)+(r-b)*(g-b));
5 temp = temp > 0?temp:0.01;
6 if(b<=g)
7 *h = acos(((r-g+r-b)/2.0)/temp);
8 else
9 *h = 2*pi - acos(((r-g+r-b)/2.0)/temp);
10 temp = r+g+b>0?r+g+b:0.01;
11 *s = 1.0-(3.0/temp)*min(r,g,b);
12 *i = (r+g+b)/3.0;
13 }

二、当然在进行直方图均衡以后我们还要把HSI转换回RGB,要不然我不知道怎么把它画出来。原理还是截图如下:

代码如下:

 1 void HSItoRGB(float h,float s,float i,float *r,float *g,float *b)
2 {
3 float pi = 3.1415926;
4 float otz =2*pi / 3;
5 if(h >=0 && h < otz)
6 {
7 *b = i*(1.0-s);
8 *r = i*(1.0+(s*cos(h))/(cos(pi/3.0-h)));
9 *g = 3.0*i-(*b+*r);
10 }
11 else if(h >= otz && h < 2 * otz)
12 {
13 *r = i*(1-s);
14 *g = i*(1+(s*cos(h-otz))/(cos(pi -h)));
15 *b = 3*i-(*g+*r);
16 }
17 else
18 {
19 *g = i*(1-s);
20 *b = i*(1+(s*cos(h-otz*2))/(cos(5*pi/6-h)));
21 *r = 3*i-(*g+*b);
22 }
23 }

第四行定义的otz这个变量就代表2pi/3,即120度,其实有了变量pi完全可以把它省略掉的。

最主要的注意就是除法中除数不能为零,所以第5行和第10行对于即将作为除数的temp都有个判断,其他的照着公式打就可了。头文件里要包含#include "cmath"。

三、最后对分量I进行直方图均衡,基本和对灰度图像进行直方图均衡时一样的步骤,然后再调用上面的HSItoRGB()函数把图像转回到RGB空间画出来就好了。最最最最最最最重要的一天(这个bug我调了很久)就是从HSI转回到RGB空间的时候分量R,G,B的值有可能超过255,一定要修改成255,见下面代码的73~75行!要不出来的图像会吓死你。

代码如下:

 1 void MainWindow::on_action_color_zhifang_triggered()
2 {
3 width = image_png.width();
4 height = image_png.height();
5 grayImg = QImage(width,height,QImage::Format_ARGB32);
6
7 //存放HSI空间分量的结构体
8 typedef struct HSI{
9 float h;
10 float s;
11 float i;
12 }hsi;
13
14 //申请一个二维结构体数组,存放每个像素转换到HSI空间后三分量的值
15 hsi **p = new hsi*[height];
16 for(int i = 0;i < height;i++)
17 p[i] = new hsi[height];
18
19 //遍历图像,调用函数RGBtoHSI()转换到HSI空间
20 float max = 0;
21 for(int i = 0;i < width;i++)
22 {
23 for(int j = 0;j < height;j ++)
24 {
25 QRgb rgb = image_png.pixel(i,j);
26 RGBtoHSI(qRed(rgb),qGreen(rgb),qBlue(rgb),&p[i][j].h,&p[i][j].s,&p[i][j].i);
27 max = max > p[i][j].i?max:p[i][j].i;
28 }
29 }
30 //qDebug()<<max;
31
32 int n = (int)(max+0.5);
33 //对分量I进行直方图均衡
34 int *II = new int[n+1];
35 float *IIPro = new float[n+1];
36 float *IITemp = new float[n+1];
37 float *IIJun = new float[n+1];
38
39 for(int i = 0;i <= n;i++)
40 II[i] = 0;
41
42 //计算频率,即nk
43 for(int i = 0;i < width;i++)
44 {
45 for(int j = 0;j < height;j ++)
46 {
47 II[(int)(p[i][j].i+0.5)]++;
48 }
49 }
50
51 //计算每个数量级出现的概率
52 for(int i = 0;i <= n;i++)
53 {
54 IIPro[i] = (II[i]*1.0)/(width*height);
55 }
56
57 //概率累加并计算均值
58 IITemp[0] = IIPro[0];
59 for(int i = 1;i <= n;i++)
60 {
61 IITemp[i] = IITemp[i-1]+IIPro[i];
62
63 IIJun[i]= n*IITemp[i];
64 }
65 for(int i=0;i<width;i++)
66 {
67
68 for(int j=0;j<height;j++)
69 {
70 p[i][j].i = IIJun[(int)(p[i][j].i+0.5)];
71 float r,g,b;
72 HSItoRGB(p[i][j].h,p[i][j].s,p[i][j].i,&r,&g,&b);
73 r = r > 255?255:(int)(r+0.5);
74 g = g > 255?255:(int)(g+0.5);
75 b = b > 255?255:(int)(b+0.5);
76 grayImg.setPixel(i,j,qRgb(r,g,b));
77 }
78 }
79
80 update();
81 }

实现的效果如下图所示,左边是原图,右边是亮度均衡后的图像:

http://www.cnblogs.com/DemonEdge/p/3422381.html

http://www.cnblogs.com/jianxinzhou/p/4086806.html 网络神经

http://www.cnblogs.com/easymind223/p/3462195.html hsv 拉升

http://baike.baidu.com/view/2969062.htm?from_id=852&type=syn&fromtitle=HDR&fr=aladdin hdr alg

最新文章

  1. nodejs+edatagrid读取本地excel表格
  2. git cherry-pick合并某个commit
  3. JAVA继承与覆写
  4. 上传自己的Python代码到PyPI
  5. PHP的学习--PHP加密
  6. poj 3034 动态规划
  7. 使用edgesForExtendedLayout遇到的麻烦
  8. ubuntu下php开发环境搭建,nginx+(cgi)php5fpm+memcached+xdebug
  9. Mono For Android中AlarmManager的使用
  10. 查询sql语句耗时的方法!
  11. android Graphics(一):概述及基本几何图形绘制
  12. POJ 2635 The Embarrassed Cryptographer 高精度
  13. tomcat服务器设置用户名和密码
  14. HDU1102(最小生成树Kruskal算法)
  15. day08 JSP
  16. Docker 容器文件导出 - 六
  17. 20180307-Xen、KVM、VMware、hyper-v等虚拟化技术的比较
  18. LVS(Linus Virtual Server):三种负载均衡方式比较+另三种负载均衡方式
  19. HDU 2680 Choose the best route 最短路问题
  20. Zookeeper项目开发环境搭建(Eclipse\MyEclipse + Maven)

热门文章

  1. ASP.NET(二):Application、Session和Server对象
  2. 九度oj 题目1337:寻找最长合法括号序列
  3. NOIP一系列模拟赛小结
  4. BZOJ 3143 [Hnoi2013]游走 ——概率DP
  5. jenkins使用流程
  6. PHP实现当前文件夹下所有文件和文件夹的遍历
  7. hdu 5012 bfs 康托展开
  8. Codeforces Round #265 (Div. 2) C 暴力+ 找规律+ 贪心
  9. Linux中有硬件时钟与系统时钟
  10. Python入门--4--分之和循环