QT 实现彩色图亮度均衡,RGB和HSI空间互相转换
从昨天折腾到今天。再折腾下去我都要上主楼了 
大致和灰度图均衡是一样的,主要是不能像平滑什么的直接对R,G,B三个分量进行。这样出来的图像时没法看的。因此我们要对亮度进行均衡。而HSI彩色空间中的分量I代表图像的亮度,和图像的彩色信息无关,所以它是我们perfect的折腾对象。
一、首先,就是把图像从RGB空间转换到HSI空间。原理我就很懒的截图了:

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 > ?temp:0.01;
if(b<=g)
*h = acos(((r-g+r-b)/2.0)/temp);
else
*h = *pi - acos(((r-g+r-b)/2.0)/temp);
temp = r+g+b>?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 =*pi / ;
if(h >= && 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 < * otz)
{
*r = i*(-s);
*g = i*(+(s*cos(h-otz))/(cos(pi -h)));
*b = *i-(*g+*r);
}
else
{
*g = i*(-s);
*b = i*(+(s*cos(h-otz*))/(cos(*pi/-h)));
*r = *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 = ;i < height;i++)
p[i] = new hsi[height]; //遍历图像,调用函数RGBtoHSI()转换到HSI空间
float max = ;
for(int i = ;i < width;i++)
{
for(int j = ;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+];
float *IIPro = new float[n+];
float *IITemp = new float[n+];
float *IIJun = new float[n+]; for(int i = ;i <= n;i++)
II[i] = ; //计算频率,即nk
for(int i = ;i < width;i++)
{
for(int j = ;j < height;j ++)
{
II[(int)(p[i][j].i+0.5)]++;
}
} //计算每个数量级出现的概率
for(int i = ;i <= n;i++)
{
IIPro[i] = (II[i]*1.0)/(width*height);
} //概率累加并计算均值
IITemp[] = IIPro[];
for(int i = ;i <= n;i++)
{
IITemp[i] = IITemp[i-]+IIPro[i]; IIJun[i]= n*IITemp[i];
}
for(int i=;i<width;i++)
{ for(int j=;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 > ?:(int)(r+0.5);
g = g > ?:(int)(g+0.5);
b = b > ?:(int)(b+0.5);
grayImg.setPixel(i,j,qRgb(r,g,b));
}
} update();
}
实现的效果如下图所示,左边是原图,右边是亮度均衡后的图像:

转载请注明出处:BY DEMONEDGE
QT 实现彩色图亮度均衡,RGB和HSI空间互相转换的更多相关文章
- 为什么使彩色图变灰RGB的权重会固定(R:0.299 G:0.587 B:0.114)?
人眼对绿色的敏感度最高,对红色的敏感度次之,对蓝色的敏感度最低,因此使用不同的权重将得到比较合理的灰度图像.根据实验和理论推导得出以下数值 R: 0.299. G: 0.587. B: 0.114.
- Qt生成灰度图(转载)
Qt生成灰度图(转载) 项目中用到大量基础图像处理知识,其中灰度图的生成是很重要的一环. 先补充一些基础知识: ------------------------------------------ ...
- OpenNI1.5获取华硕XtionProLive深度图和彩色图并用OpenCV显示
华硕XtionPro类似Kinect,都是体感摄像机,可捕捉深度图和彩色图. 具体參数见:http://www.asus.com.cn/Multimedia/Xtion_PRO_LIVE/specif ...
- OpenNI2获取华硕XtionProLive深度图和彩色图并用OpenCV显示
使用OpenNI2打开XtionProLive时有个问题,彩色图分辨率不管怎样设置始终是320*240,深度图倒是能够设成640*480,而OpenNI1.x是能够获取640*480的彩色图的. 彩色 ...
- Android-将RGB彩色图转换为灰度图
package com.example.yanlei.wifi; import android.graphics.Bitmap; import android.graphics.BitmapFacto ...
- Inkscape svg彩色图转灰度图
操作: Ctrl+A 全选所有对象, 然后使用滤镜渲染成灰度图, 至于这个RGB比值, 看个人需求, 标准情况下rgb2gray是0.299 * R + 0.587 * G + 0.114 * B 原 ...
- Color Models (RGB, CMY, HSI)
目录 概 定义 RGB CMY CMYK HSI 相互的转换 RGB <=> CMY CMY <=> CMYK CMY > CMYK CMYK > CMY RGB ...
- 基于RGB与HSI颜色模型的图像提取法
现实中我们要处理的往往是RGB彩色图像.对其主要通过HSI转换.分量色差等技术来提出目标. RGB分量灰度化: RGB可以分为R.G.B三分量.当R=G=B即为灰度图像,很多时候为了方便,会直接利用某 ...
- Qt 串口通信之使用16进制发送数据的转换方式
Qt 串口通信之使用16进制发送数据的转换方式 一 概述 有时候在做上位机串口通讯时,经常需要将字符串转成16进制的形式作为发送,借此分析记录一下. 二 需求分析 //假设需要转换的字符:如下 QSt ...
随机推荐
- django构建blog--页面部分(eclipse+pydev)
本文介绍的是在eclipse+pydev 平台下,利用django 搭建blog的第2部分:页面部分(主要涉及3个部分:模板.视图.URL模式) 篇幅1:创建模板 blog目录下新建一个文件夹:tem ...
- Codeforces Beta Round #69 (Div. 1 Only) C. Beavermuncher-0xFF 树上贪心
题目链接: http://codeforces.com/problemset/problem/77/C C. Beavermuncher-0xFF time limit per test:3 seco ...
- openwrt的交叉编译
默认情况下,openwrt编译脚本会自动从Internet上获取所需要的软件包源代码,并把下载的源码包存放在当前目录的 dl/ 目录中: 在 build_dir/ 目录中存放编译中使用的软件包, ...
- 使用log4javascript记录日志
1.定义log4js服务类,用于初始化log4javascript相关参数 log4jsService.js //启用javascript 日志功能 var logger = log4javascri ...
- Matlab交集并集的实现
>> a = [1 2 3 4 8 9]; >> b = [4 5 6 1] b = 4 5 6 1 >> c = intersect(a,b) c = 1 4 判 ...
- Asp.net 导入Excel(服务器不带Office)
#region 把excel文件转换为DataSet. /// <summary> /// 把excel文件转换为DataSet. /// </summary> /// < ...
- word插件开发 运行时,插件不启动.
word插件开发 运行时,插件不启动. 查看插件信息时. 在禁用的应用程序加载项中. 启动禁用的插件: 点击转到. 选择你要启动的插件就可以了.
- 6 高级IO函数
6.1 pipe函数 pipe函数创建一个管道,用于实现进程间通信 #include<unistd.h> ]); 参数包含两个文件描述符fd[0]和fd[1],往fd[1]写入的数据可以从 ...
- Docker学习资料
官方Docker:https://www.docker.com/ CSDN Docker : http://docker.csdn.net/ Docker中文社区:http://www.docker. ...
- Javascript学习笔记1 数论
1.Javascript不用担心内存的回收与对象的销毁! 2.Javascript有:±infinity.NaN全局变量表示 被0整除的±无穷 和 非数字.undefined和null表示 未定义 和 ...


