RGB转LAB色彩空间

https://www.cnblogs.com/hrlnw/p/4126017.html

1.原理

RGB无法直接转换成LAB,需要先转换成XYZ再转换成LAB,即:RGB——XYZ——LAB

因此转换公式分两部分:

(1)RGB转XYZ

假设r,g,b为像素三个通道,取值范围均为[0,255],转换公式如下:

    (1)      

 

    (2)

 

    (3)

 

M=

0.4124,0.3576,0.1805

0.2126,0.7152,0.0722

0.0193,0.1192,0.9505

等同于如下公式:

X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805
Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722
Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505

上面的gamma函数,是用来对图象进行非线性色调编辑的,目的是提高图像对比度。这个函数不是唯一的,但是我在网上查到的基本都使用上式。

 

(2)XYZ转LAB

    (5)

 

    (6)

上面两个公式中,L*,a*,b*是最终的LAB色彩空间三个通道的值。X,Y,Z是RGB转XYZ后计算出来的值,Xn,Yn,Zn一般默认是95.047,100.0,108.883。

 

2.代码实现

 (1)完全按照算法无优化实现(经@竹子小蜻蜓指正,原来代码有误,现已改正--206.04.12)

复制代码
inline float gamma(float x)
{return x>0.04045?pow((x+0.055f)/1.055f,2.4f):x/12.92;};void RGBToLab(unsigned char*rgbImg,float*labImg)
{float B=gamma(rgbImg[0]/255.0f);float G=gamma(rgbImg[1]/255.0f);float R=gamma(rgbImg[2]/255.0f);float X=0.412453*R+0.357580*G+0.180423*B;float Y=0.212671*R+0.715160*G+0.072169*B;float Z=0.019334*R+0.119193*G+0.950227*B;

  float X/=0.95047;
  float Y/=1.0;
  float Z/=1.08883;
float FX = X > 0.008856f ? pow(X,1.0f/3.0f) : (7.787f * X +0.137931f);float FY = Y > 0.008856f ? pow(Y,1.0f/3.0f) : (7.787f * Y +0.137931f);float FZ = Z > 0.008856f ? pow(Z,1.0f/3.0f) : (7.787f * Z +0.137931f);labImg[0] = Y > 0.008856f ? (116.0f * FY - 16.0f) : (903.3f * Y);labImg[1] = 500.f * (FX - FY);labImg[2] = 200.f * (FY - FZ); }
复制代码

上面是完全按照转换算法做的无优化的实现,里面涉及了大量的浮点运算,在PC上可能没什么问题,但是如果是在Android操作系统的移动端上,即使利用JNI,把转换算法写成C++版本进行加速,速度也不理想,因为这个操作时逐像素的,每个像素做几十次浮点运算,耗时还是十分巨大的。

 (2)牺牲一些精度的快速实现

首先可以把gamma函数去掉,因为经过我的测试,这个函数带来的影响很小。

其次,M矩阵中的值都为小数,可以通过放大变成整数,接下来的计算就可以变成整数计算(在手机上浮点计算一般耗时是整形计算的几倍)。在这里,可以把M矩阵的值都扩大2^20倍变为整数,在计算得到X,Y,Z分量时再缩小回来。但是,XYZ的小数部分会消失,会引入误差,而在公式(5)(6)中(尤其是(6),涉及到指数运算和阈值运算,之前XYZ的误差在这里会被放大),这种误差还会继续传递给最终的L,a,b值。那怎么才能保证一定的准确率呢?

在这里我的方法是引入了一个查表机制。过程如下:

A.在计算XYZ的时候,参数扩大2^20倍,但最后缩小时只缩小2^18,这样计算出来的XYZ值范围是[0,1023]

B.建立一个table,用于将取值为[0,1023]的XYZ通过f(t)函数映射到中间结果,记为:LabTable(m)

C.将LabTable(m)代入公式(5)计算最终的Lab分量值

代码如下:

复制代码
const static int big_shift=18;
const static int HalfShiftValue=512;
const static int shift=10;
const static int offset=128<<shift;
const static int ScaleLC = (16 * (1 << shift));
const static int ScaleLT = 116;
const static int ScaleY= 903;
const static int para1=500;
const static int para2=200;
const static int ThPara=9;void RGBToLab(unsigned char*rgbImg,int*labImg)
{long long X=(rgbImg[0] * 199049 + rgbImg[1] * 394494 + rgbImg[2] * 455033 + 524288)>> (big_shift);long long Y=(rgbImg[0] * 75675 + rgbImg[1] * 749900 + rgbImg[2] * 223002 + 524288) >> (big_shift);long long Z=(rgbImg[0] * 915161 + rgbImg[1] * 114795 + rgbImg[2] * 18621 + 524288) >> (big_shift);labImg[0] = Y>ThPara?((ScaleLT * LabTable[Y] - ScaleLC + HalfShiftValue)>>shift):((ScaleY* Y)>>shift);labImg[1] = (para1*(LabTable[X] - LabTable[Y])+HalfShiftValue+offset)>>shift;labImg[2] = (para2*(LabTable[Y] - LabTable[Z])+HalfShiftValue+offset)>>shift;
}
复制代码

建立LabTable的代码如下:

复制代码
int LabTable[1024];
for (int I = 0; I < 1024; I++)
{if (I > 9)LabTable[I] = (int)(pow((float)I / 1020, 1.0F / 3) * (1 << 10) + 0.5 );elseLabTable[I] = (int)((29 * 29.0 * I / (6 * 6 * 3 * 1020) + 4.0 / 29) * (1 << 10) + 0.5 );printf("%d,",LabTable[I]);
}
复制代码

 

参考文章:

http://www.easyrgb.com/index.php?X=MATH&H=07#text7

http://vcsos.com/Article/pageSource/120314/20120314114422.shtml

http://www.cnblogs.com/Imageshop/archive/2013/01/31/2888097.html

http://www.cnblogs.com/Imageshop/archive/2013/02/02/2889897.html

转载于:https://www.cnblogs.com/jukan/p/7844302.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/571610.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React- jsx的使用可以渲染html标签 或React组件

React 的 JSX 使用大、小写的约定来区分本地组件的类和 HTML 标签。既渲染html标签需要使用小写字母开头的标签名而渲染本地React组件需要使用大写字母开头的标签名 注意: 由于 JSX 就是 JavaScript&#xff0c;一些标识符像 class 和 for 不建议作为 XML 属性名。作为替代&…

bigdecimal保留4位小数_四年级数学小数的加减乘法知识点汇总,带练习!

张老师 - 4年级(多品小学教育)顺城中心小学郭老师和环县虎洞中心小学谭老师需要的这份学习资料现在分享。本资料已制作电子版下载码是&#xff1a;76qa32vd《小数的加减乘法》知识点一、小数加、减法的计算法则(1)小数点要对齐&#xff0c;也就是相同数位要对齐&#xff1b;相同…

vs未指定启动文件_高效开发利器之自定义模板文件

简介越来越多的设计模式, 最佳实践, 优化了软件开发方式, 提高了软件质量, 但是也带来了大量的类似的文件. 比如说: 现在都使用三层模式来开发Web程序, 都会有服务层(Service), DI的流行, 每个服务类都会自动注入一些固定的对象, 日志对象, 缓存对象等等. 实体类(Entity)到DTO对…

react-router 4.0 学习笔记

1、安装react-router-dom 2、页面上要使用的时候要引入  import {BrowserRouter as Router,Route,Link } from react-router-dom 3、使用的时候要在外层包一个<Router> 4、param 在路径上如果带有/:id类似这种的&#xff0c;要取值的时候&#xff0c;match.params.id取…

分数优先遵循志愿php源码_2021年南昌中考志愿填报指导,这七大要点你都了解吗?...

中考是孩子即将面对人生的第一个十字路口&#xff0c;家长们也因此开始为孩子的未来紧张。都说选择大于努力&#xff0c;给孩子选一个适合的学校也很重要&#xff0c;为了大家可以更好的填报志愿&#xff0c;小编为大家汇总了这份指南&#xff0c;快来一起看看吧~1、认清自己&a…

gin ip 和 本地访问的结果不一样_golang web开发——gin实战之整合swagger

背景如果我们之前搞过java web开发&#xff0c;我们应该都知道swagger这个API文档自动生成利器&#xff0c;有了swagger可以方便我们与客户端的联调&#xff0c;基本上是一目了然&#xff0c;swagger支持java&#xff0c;自然它也能支持golang的gin框架&#xff0c;本小节&…

cif是目的港交货吗_刚接手出口业务,搞不懂FOB? CIF? 为你科普→

Export专用名词辨析01 名词辨析#FOBFOB(Free On Board)&#xff0c;含义是装运港船上交货&#xff0c;指卖方在合同规定的装运港负责将货物装上买方指定的船上&#xff0c;并负责货物装船之前的一切费用和风险&#xff0c;以及办理出口通关的相关事宜及费用&#xff0c;所以在实…

中的数组怎么转成结构体_传说中的“衡水体”应该怎么练?

传说中的“衡水体”应该怎么练&#xff1f;我也不知道&#xff0c;哈哈哈哈哈哈。因为我之前关于衡水体的回答最高赞评论说我这个不是衡水体……随便写的之前的回答所以&#xff0c;这篇文章纯属交流分享&#xff0c;同时枯燥无味&#xff0c;可能适合觉得自己书写不好看的高中…

windows 显示苹果分区_基准测试数据显示苹果M1运行Windows的表现比微软自家硬件好上近一倍...

根据最新的基准测试&#xff0c;苹果M1运行 "Windows 10 on ARM "的速度比微软自家的硬件快了近2倍。更新后的基准数据显示&#xff0c;苹果M1上的Windows 10比Surface Pro X快得多&#xff0c;这还是配备了基于骁龙8cx的处理器的Surface Pro X原生运行该操作系统的环…

python 发邮件_Python发邮件告别smtplib,迎接zmail

之前介绍过smtplib发邮件代码&#xff0c;直到今天仍有人在这里遇到问题。而且代码复杂&#xff0c;解释起来很麻烦&#xff0c;今天给大家介绍一个新的发邮件方法——zmailzmail的优势自动填充头信息将一个字典映射为email&#xff0c;构造邮件相当于构造字典自动寻找邮件服务…

重复数据_MongoDB 自动过滤重复数据

摘要&#xff1a;使用 update_one() 方法而不是 insert_one() 插入数据。相信你一定有过这样的经历&#xff1a;大晚上好不容易写好一个爬虫&#xff0c;添加了种种可能出现的异常处理&#xff0c;测试了很多遍都没有问题&#xff0c;点击了 RUN 开始正式运行 &#xff0c;然后…

多个canvas画布合并_canvas的基础入门

nvas是定义在浏览器上的画布。它不仅仅是一个标签元素更是一个编程工具是一套编程的接口。利用它可以开发出很多东西&#xff0c;比如动画&#xff0c;游戏&#xff0c;动态的图表等富有变现力和感染力的应用。还可以开发出绚丽的3D动态效果。接下来我们一起学习&#xff01;一…

工业机器人专业展板图片_南充职业技术学院工业机器人专业线下课程开展情况...

2020年5月18日&#xff0c;南充职业技术学院线下课程已全面展开&#xff0c;下面是工业机器人技术专业的开课情况。历时4个多月的假期&#xff0c;即将开课。在开课前两天&#xff0c;我司专业教师到学院检查维护机器人设备&#xff0c;以保障学生们能够正常使用工业机器人相关…

vmware挂载san存储_细述企业级存储NAS和SAN差异

常见服务器磁盘类型SAS&#xff1a;容量小&#xff0c;300G&#xff0c;600G&#xff0c;价格贵SATA&#xff1a;容量大&#xff0c;4T&#xff0c;不支持热插拔&#xff0c;价格低假SAS&#xff1a;容量大&#xff0c;支持热插拔&#xff0c;价格低&#xff0c;(就是SAS接口的…

蓝牙核心技术了解(蓝牙协议、架构、硬件和软件笔记)

声明&#xff1a;这篇文章转载beautifulzzzz笔记&#xff0c;网址&#xff1a;http://www.cnblogs.com/zjutlitao/&#xff0c;其中比较多的受益于xubin341719的蓝牙系列文章&#xff0c;同时还有其他网上作者的资料。由于有些文章只做参考或统计不足&#xff0c;如涉及版权请在…

初中英语多词性单词怎么办_高考英语阅读理解生僻单词太多怎么办?十大招数帮到你...

英语阅读理解生僻单词太多怎么办&#xff1f;今天&#xff0c;胡老师告诉你猜词十大招数&#xff0c;帮助同学们英语考试拿高分。01 构词法阅读中常常会遇到一些由熟悉的单词派生或合成的新词。掌握构词法对猜测词义很有帮助。如&#xff1a;unforeseeable.这个词&#xff0c;可…

springboot jwt token前后端分离_基于Spring Boot+Spring Security+JWT+Vue前后端分离的开源项目...

一、前言最近整合Spring BootSpring SecurityJWTVue 完成了一套前后端分离的基础项目&#xff0c;这里把它开源出来分享给有需要的小伙伴们功能很简单&#xff0c;单点登录&#xff0c;前后端动态权限配置&#xff0c;前端权限精确到 按钮 级别&#xff0c;后端权限精确到 url …

springboot 微服务_使用 Docker 部署 Spring Boot微服务

Docker 技术发展为微服务落地提供了更加便利的环境&#xff0c;使用 Docker 部署 Spring Boot 其实非常简单&#xff0c;这篇文章我们就来简单学习下。首先构建一个简单的 Spring Boot 项目&#xff0c;然后给项目添加 Docker 支持&#xff0c;最后对项目进行部署。一个简单 Sp…

sql 除以_刷完这些SQL练习题,简单查询就熟能生巧了

练习题&#xff1a;SQLZOO表&#xff1a;&#xff08;图片未显示全部列&#xff09;&#xff08;1&#xff09;SELECT basics&#xff1a;&#xff08;简单查询&#xff09;SELECT basics/zh​sqlzoo.net①The example uses a WHERE clause to show the population of France. …

Tomcat 总体结构

http://threezj.com/2016/06/25/Tomcat%20%E6%9E%B6%E6%9E%84%E6%8E%A2%E7%B4%A2/ Tomcat 架构探索 發表於 2016-06-25 | 前言 花了一个礼拜的时间阅读了 how tomcat works&#xff0c;本文基于此书&#xff0c;整理了一下Tomcat 5的基本架构&#xff0c;其实也没什么多复杂…