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

大致和灰度图均衡是一样的,主要是不能像平滑什么的直接对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

图像处理之图像格式变换和色彩增强---rgb2hsi2hsv 色彩增强的更多相关文章

  1. Win8 Metro(C#)数字图像处理--2.38Hough变换直线检测

    原文:Win8 Metro(C#)数字图像处理--2.38Hough变换直线检测  [函数名称] Hough 变换直线检测         HoughLineDetect(WriteableBit ...

  2. 【数字图像处理】gamma变换

    论文:gamma校正的快速算法及其c语言实现 gamma变换实现过程 假设图像中有一个像素,值是 200 ,那么对这个像素进行校正必须执行如下步骤: 1. 归一化 :将像素值转换为  0 - 1  之 ...

  3. opencv图像处理之gamma变换

    import cv2 import numpy as np img=cv2.imread('4.jpg') def adjust_gamma(image, gamma=1.0): invGamma = ...

  4. PIE SDK彩色空间变换

    1. 算法功能简介 使用彩色空间变换工具可以将三波段红.绿.蓝图像变换到一个特定的彩色空间,并且能从所选彩色空间变换回 RGB.两次变换之间,通过对比度拉伸,可以生成一个色彩增强的彩色合成图像.此外, ...

  5. iOS中的图像处理(一)——基础滤镜

    最近在稍微做一些整理,翻起这部分的代码,发现是两个多月前的了. 这里讨论的是基于RGBA模型下的图像处理,即将变换作用在每个像素上. 代码是以UIImage的category形式存在的: typede ...

  6. PIE SDK最小噪声变换

    1.算法功能简介 最小噪声分离变换是用于判定图像数据内在的维数(即波段数),分离数据中的噪声,减少随后处理中的计算需求量. MNF 本质上是两次层叠的主成分变换.第一次变换(基于估计的噪声协方差矩阵) ...

  7. PIE SDK主成分变换

    1.算法功能简介   主成分变换(Principal Component Analysis,PCA)又称K-L(Karhunen-Loeve)变换或霍特林(Hotelling)变换,是基于变量之间的相 ...

  8. CxImage新手教程,图文并茂

    作为一个游戏client程序猿,须要对图像处理有一定的知识. CxImage是C++实现的功能强大的.能处理多种文件格式的图像管理类.它可以简单高速的实现图像的导入.保存.显示和变换. 同一时候又具有 ...

  9. Saliency Detection: A Spectral Residual Approach

    Saliency Detection: A Spectral Residual Approach 题目:Saliency Detection: A Spectral Residual Approach ...

随机推荐

  1. springboot集成redis操作

    使用HashOperations操作redis----https://www.cnblogs.com/shiguotao-com/p/10560458.html 使用HashOperations操作r ...

  2. 【Python】SyntaxError: Non-ASCII character '\xe8' in file

    遇到的第一个问题: SyntaxError: Non-ASCII character '\xe8' in file D:/PyCharmProject/TempConvert.py on line 2 ...

  3. [uiautomator篇] UiWatcher的使用

    //package com.softwinner.pad.mark3d; package com.softwinner.performance.benchmark.mark3d; import and ...

  4. 九度oj 题目1120:全排列

    题目描述: 给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列. 我们假设对于小写字母有'a' < 'b' < ... < 'y' < 'z',而且给定的字符串中 ...

  5. [BZOJ3545] [ONTAK2010]Peaks(线段树合并 + 离散化)

    传送门 由于困难值小于等于x这个很恶心,可以离线处理,将边权,和询问时的x排序. 每到一个询问的时候,将边权小于等于x的都合并起来再询问. .. 有重复元素的线段树合并的时间复杂度是nlog^2n # ...

  6. 做运动(Dijkstra+并查集+MST)

    上面的题解是这样,这道题我真的脑残,其实打代码的时候就意识到了许多,可以用Dfs+Dij+二分,这样还可以卡一卡 但是我打了spfa+spfa+二分,这个显然很慢,类似的题目我好像还做过一道的,就是在 ...

  7. Oracle Partition 分区详细总结

    此文从以下几个方面来整理关于分区表的概念及操作:        1.表空间及分区表的概念        2.表分区的具体作用        3.表分区的优缺点        4.表分区的几种类型及操作 ...

  8. linux命令dhclient

    linux命令 dhclient 背景 多台服务器(CentOS7 系统)设置静态IP,其中有台服务器设置了静态IP后,只要重启就变更为其他的,但是配置文件并无改动. 使用命令 #自动获取IP dhc ...

  9. Mysql常见配置说明

    [mysqld]配置 default-storage-engine = MyISAM 默认选择某种表存储引擎 ignore-bulidin-innodb 忽略mysql自带的innodb引擎,使用这个 ...

  10. eclipse 搭建ruby环境

    第一步:获取RDT,http://sourceforge.net/projects/rubyeclipse/files/ 解压该文件,获得features和plugins两个文件夹,将这两个文件夹分别 ...