RGB三原色是基于人肉眼对光线的生理作用。人眼内有三种椎状体“对这三种光线频率所能感受的带宽最大,也能独立刺激这三种颜色的受光体”,因此RGB称为三原色。比如,黄色波长的光对人眼的刺激效果,和红色与绿色同时刺激人眼相同,所以,对人来说R+G=yellow,即(255,255,0).
 
相对于RGB,HSB(也叫HSV)模式更便于描述人眼对与颜色的感觉。如图的HSB椎形坐标,横截面从下往上亮度值从0%到100%递增;横截面的中心点是灰色的,随着半径增大,饱和度从0增大到100%;色相取值0°~360°,代表截面上红、黄、绿、青、蓝、粉红的颜色变化。
 
HSB坐标系最顶部的截面最外圈,饱和度和亮度都是100%,随着色相从0°到360°变化,RGB值的变化如上图,红色、绿色、蓝色分别位于0°、120°、240°;0°到60°之间绿色分量均匀增加,60°到120°之间红色分量均匀减少,以此类推。将 这个演示中的S和B调到100%,调整H的值观察RGB的变换就能发现这个规律。这时RGB中最大值一定是255(因为亮度为100%),最小值一定是0(如果不是,比如RGB=(10,20,255),可以看成在(0,10,255)分量的基础上加上一个灰色分量(10,10,10),加灰色后饱和度就不是100%了)。
   
 
 
HSB转RGB
 
要算出(h,s,b)对应的(r,g,b),可以分3步,以HSB=(130°,50%,80%)为例说明:
 
1、先算出(h,100%,100%)对应的(r',g',b')。
先固定色相,色环图上色相H∈[-60°,60°]时红色分量最大,H∈[60°,180°]时绿色分量最大,H∈[180°,300°]时蓝色分量最大,此时B=100%,所以RGB的最大分量为255。
先算出HSB=(130°,100%,100%)对应的(r',g',b'):H=130°,在[60°,180°]区间,所以绿色分量为g'=255,红色分量r'=0;进一步地,130°处于[120°,180°],在这60°的区间上,色环上蓝色分量对应地从0递增到255,所以b'=(130°-120°)/60°*255=43。所以(r',g',b')=(0,255,43)
 
2、固定色相后再调整饱和度,算出(h,s,100%)对应的(r'',g'',b'')。
在亮度B=100%时,从 演示中发现,饱和度S降低,即“不饱和度”(1-S)升高,会使得RGB与最大值255相差的部分对应增大,RGB三个分量越趋于相同就使得图像越灰。所以,
r''=r'+(255-r')*(1-S) .................................... ①
g''和b''用同样的方法求出。当然,r'g'b'中的最大值不会变化。(r'',g'',b'')=(128,255,149)
 
3、最后算出(h,s,b)对应的(r,g,b)。
最后调整亮度,只要依照亮度值的百分比缩小就行了,(r,g,b)=(r'',g'',b'')*80%=(102,204,119)就是HSB=(130°,50%,80%)对应的RGB
 
public float[] hsb2rgb(float[] hsb) {
float[] rgb= new float[];
//先令饱和度和亮度为100%,调节色相h
for(int offset=,i=;i<;i++,offset-=) {
//算出色相h的值和三个区域中心点(即0°,120°和240°)相差多少,然后根据坐标图按分段函数算出rgb。但因为色环展开后,红色区域的中心点是0°同时也是360°,不好算,索性将三个区域的中心点都向右平移到240°再计算比较方便
float x=Math.abs((hsb[]+offset)%-);
//如果相差小于60°则为255
if(x<=) rgb[i]=;
//如果相差在60°和120°之间,
else if(<x && x<) rgb[i]=((-(x-)/)*);
//如果相差大于120°则为0
else rgb[i]=;
}
//在调节饱和度s
for(int i=;i<;i++)
rgb[i]+=(-rgb[i])*(-hsb[]);
//最后调节亮度b
for(int i=;i<;i++)
rgb[i]*=hsb[];
return rgb;
}
 
RGB转HSB
 
这个从HSB转RGB倒推回去就会很容易知道亮度和饱和度的算法
 
亮度:B=max(R,G,B)/255
 
饱和度:1-S=min(R,G,B)/255,所以饱和度S=1-min(R,G,B)/255
 
色相:先算出(r,g,b)对应的饱和度和亮度均为100%时的(r',g',b'),然后既可以根据色环的规律求出色相了。
r'、g'、b'的序号用0、1、2表示,max、min、mid分别是r'g'b'中最大值、最小值和中间值;设maxIndex、minIndex、midIndex分别是r'g'b'中最大值、最小值和中间值的序号。首先将色相h定位到(maxIndex*120°)然后根据中间值算出偏移量(mid/255*60°),既
h=(maxIndex*120°)±(mid/255*60°)....................................②
关于②中的±号的确定方法:将当0、1、2顺时针写成一圈,当midIndex在maxIndex的顺时针方向(既minIndex在maxIndex的逆时针方向)时取正,否则取负,原因看色环就能知道。所以±号可以用(maxIndex-minIndex+3)%3是否等于1来判断,是取正,否则取负。②式可以改写成:
h=(maxIndex*120°)+((maxIndex-minIndex+3)%3==1?1:-1)*(mid/255*60°)....................................③
以(r,g,b)=(102,204,85)为例,前两步已求出亮度为80%,饱和度为50%。当亮度和饱和度均为100%而色相不变时,最大值g'一定是255;最小值r'一定是0;中间值b'按照上面HSB转RGB的后两步反推回去,先得出亮度为100%时b''=102/80%=128,再由①式得出饱和度为100%时b'=43。
因为g'=255最大,先定位到色环上的120°的位置,因为蓝色分量不为0,所以要从120°顺时针偏移b'/255*60°=10°,即H=130°

public float[] rgb2hsb(float[] rgb) {
float[] hsb = new float[];
float[] rearranged = rgb.clone();
int maxIndex = ,minIndex = ;
float tmp;
//将rgb的值从小到大排列,存在rearranged数组里
for(int i=;i<;i++) {
for(int j=;j<-i;j++)
if(rearranged[j]>rearranged[j+]) {
tmp=rearranged[j+];
rearranged[j+]=rearranged[j];
rearranged[j]=tmp;
}
}
//rgb的下标分别为0、1、2,maxIndex和minIndex用于存储rgb中最大最小值的下标
for(int i=;i<;i++) {
if(rearranged[]==rgb[i]) minIndex=i;
if(rearranged[]==rgb[i]) maxIndex=i;
}
//算出亮度
hsb[]=rearranged[]/255.0f;
//算出饱和度
hsb[]=-rearranged[]/rearranged[];
//算出色相
hsb[]=maxIndex*+* (rearranged[]/hsb[]/rearranged[]+(-/hsb[])) *((maxIndex-minIndex+)%==?:-);
//防止色相为负值
hsb[]=(hsb[]+)%;
return hsb;
}

RGB和HSB的转换推算的更多相关文章

  1. c# 颜色RGB到HSB互相转换

    /// <summary> /// 色相,饱和度,亮度转换成rgb值 /// </summary> /// <returns></returns> pu ...

  2. RGB与HSB之间转换

    先来了解一些概念: 1.RGB是一种加色模型,就是将不同比例的Red/Green/Blue混合在一起得到新颜色.通常RGB颜色模型表示为: 2.HSB(HSV) 通过色相/饱和度/亮度三要素来表达颜色 ...

  3. 【C#】RGB,CMYK,HSB各种颜色表示的转换(转)

    [C#]RGB,CMYK,HSB各种颜色表示的转换   一.表示颜色的方式有很多种,如RGB,CMYK,HSB,Hex等等 1.RGB:这种表示颜色由三原色构成,通过红,绿,蓝三种颜色分量的不同,组合 ...

  4. RGB,CMYK,HSB各种颜色表示的转换 C#语言

    Introduction Why an article on "colors"? It's the same question I asked myself before writ ...

  5. C# RGB和HSB相互转换

    背景 最近做的项目中有这样一个场景,设置任意一种颜色,得到这种颜色偏深和偏浅的两种颜色.也就是说取该颜色同色系的深浅两种颜色.首先想到的是调节透明度,但效果不理想.后来尝试调节颜色亮度,发现这才是正解 ...

  6. RGB与HSB之间的转换公式

    先来了解一些概念: 1.RGB是一种加色模型,就是将不同比例的Red/Green/Blue混合在一起得到新颜色.通常RGB颜色模型表示为: 2.HSB(HSV) 通过色相/饱和度/亮度三要素来表达颜色 ...

  7. YUV / RGB 格式及快速转换算法

    1 前言 自然界的颜色千变万化,为了给颜色一个量化的衡量标准,就需要建立色彩空间模型来描述各种各样的颜色,由于人对色彩的感知是一个复杂的生理和心理联合作用 的过程,所以在不同的应用领域中为了更好更准确 ...

  8. e585. Converting Between RGB and HSB Colors

    This example demonstrates how to convert between a color value in RGB (three integer values in the r ...

  9. Android 音视频编解码——RGB与YUV格式转换

    一.RGB模型与YUV模型 1.RGB模型 我们知道物理三基色分别是红(Red).绿(Green).蓝(Blue).现代的显示器技术就是通过组合不同强度的红绿蓝三原色,来达成几乎任何一种可见光的颜色. ...

随机推荐

  1. MySQL完整性语言

    文章为作者原创,未经许可,禁止转载.    -Sun Yat-sen University 冯兴伟 实验3:完整性语言 完整性语言实验包含3个实验项目,其中2个必修项目,1个选修项目.该实验的各个实验 ...

  2. VS2015 C#6.0 中的那些新特性

    本人个人博客原文链接地址为http://aehyok.com/Blog/Detail/66.html. 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok ...

  3. ADB工具包15秒快速安装器,已集合ADB、FASTBOOT工具箱和最新的驱动程序

    http://www.cnroms.com/adb-and-fastboot-toolkit-with-google-usb-drivers.html 通过电脑管理安卓手机需要的三个最常用的工具包集合 ...

  4. 机器学习基石--学习笔记02--Hard Dual SVM

    背景 上一篇文章总结了linear hard SVM,解法很直观,直接从SVM的定义出发,经过等价变换,转成QP问题求解.这一讲,从另一个角度描述hard SVM的解法,不那么直观,但是可以避免fea ...

  5. JAVA自动化测试中多数据源的切换

    在做自动化测试时,数据驱动是一个很重要的概念,当数据与脚本分离后,面对茫茫多的数据,管理数据又成了一个大问题,而数据源又可能面对多个,就跟在开发过程中,有时候要连接MYSQL,有时候又要连接SQL S ...

  6. 多线程socket编程示例

    工程: 代码: package com.my.socket.business; /** * 业务实现类 * * @author ZY * */ public class CoreMisBusiness ...

  7. word2007二级标题自动编号不从大标题开始的解决方法

    今天在编写word文档的时候,遇到一个很奇怪的问题,word2007二级标题自动编号不从大标题开始,可能我说的比较模糊,我截个图大家一看就明白了. 我想要的是2.1 2.2结果,他确是从1.1开始了. ...

  8. 连上VPN后,如何访问内网(添加路由表实现网络分流方法)

    route add 192.168.4.0 mask 255.255.255.0 192.168.2.0 metric 1 不止有“邮件系统”会出现这种情况,还有其他情况,这时,你需要在没有连接外网和 ...

  9. python环境中运行程序

    运行Python程序,我们比较常用的是直接在Windows命令提示窗口或者Linux终端或shell窗口中,直接:Python *.py,或者在Linux环境下,在投不中,加入: #!/usr/bin ...

  10. 【书单】book list

    正在看: [泡沫经济学].(日)野口悠纪雄 数学模型--姜启源 R in action Programming with R Scrapy Parallel R     准备看: Advanced.A ...