常见的色彩模型

  • RGB色彩模型:常用于电视、摄像机等显示器,遵循加色法则(光的三原色,越混越白);缺点是色彩空间不够均匀,不容易进行色差的评价;与直观的色调、饱和度、亮度没有直接联系,不符合人的认知心理

  • CMYK模型:用于彩色打印,对应青、品红、黄、黑,遵循减色法则(颜料三原色,越混越黑),可以满足打印的要求

  • YCbCr模型:是YUV压缩和偏移的版本,将亮度(Y)和色度(U, V)分开。Cb、Cr指蓝色色度、红色色度,图片(JPEG)、视频(MPEG)、DVD、摄像机、数字电视都采用这一格式,注意在不同色域(如BT.601, BT.709)下要使用相应的RGB2YUV转换矩阵

  • CIEXYZ色彩模型:为人眼实际感知的物体色彩响应值,是一种设备无关的颜色系统,可以由反射率、CIE XYZ人眼颜色匹配函数、光源SPD (Spectral Power Distribution)量化,是一种非均匀的颜色空间。各颜色空间各自独立,但可以通过XYZ作为媒介,变换至其他的颜色空间

  • CIELAB色彩模型:是一种设备无关的颜色系统,基于一种颜色不能同时既是蓝又是黄这个理论而建立。同一个椭圆内的颜色人眼观察起来是相同的,可见CIELAB的椭圆大小和形状优于CIELUV,是一种相对均匀的颜色空间

  • CIELCH色彩模型:采用了同CIELAB一样的颜色空间,但它采用L表示明度值,C表示饱和度以及H表示色调角度值的柱形坐标

  • HSL色彩模型 (Hue, Saturation, Lightness):类似于人眼对颜色的感知方式。HSL将RGB色彩模型中的点在圆柱坐标系中表示,H-色相,如红色、黄色等;S-饱和度,取0-100%;L-亮度,取0-100%

  • HSV色彩模型 (Hue, Saturation, Value):同样类似于人眼对颜色的感知方式。HSV在概念上常被认为是颜色的倒圆锥体,代表可区分出的饱和度和色相的级别数目随着明度接近黑色而降低。实际应用经常选择HSV色轮,色相表示为圆环, 三角形表示饱和度和明度,对饱和度的定义和HSL是明显不同的

常见的色域

CIE 1931 XYZ颜色空间:为人眼最大能感知色彩的范围,将人眼三刺激值量化后,取x和y平面图。其中黑线为普朗克曲线,从右至左的范围为1000K-20000K

  • sRGB:是美国HP公司和Microsoft公司于1997年开发的标准颜色空间
  • Adobe RGB:是Adobe Systems于1998年开发的色彩空间,粗略包括了50%的Lab色彩空间中的可视色彩,主要在青绿色系上有所提升,能够在CMYK彩色印刷中利用计算机显示器等设备的RGB颜色模式上囊括更多的颜色
  • DCI-P3:美国电影行业推出的一种广色域标准,是目前数位电影回放设备的色彩标准之一,比sRGB大了25%,绿色和红色的范围更广;苹果、索尼、三星等公司正逐步将DCI-P3作为广色域的标准;90% DCI-P3色域代表HDR规格显示器的基本色彩要求
  • BT. 2020:传统电视使用BT.601和BT.709色域,大多数高清电视和电脑会使用BT.709或DCI/P3,超高清电视会使用更广的色域空间,如BT.2020,包含可视颜色的57.3%

颜色空间转换

包括:

  1. RGB2XYZ / XYZ2RGB
  2. XYZ2LAB / LAB2XYZ
  3. LAB2LCH
  4. RGB2HSL / HSL2RGB
  5. RGB2HSV / HSV2RGB
  6. RGB2YUV / YUV2RGB (Origin / Full Range / Limit Range)
RGB2XYZ / XYZ2RGB
  • sRGB
  • P3
  • RGB2XYZ Code
def RGB2XYZ(RGB, mode):if mode == "sRGB":RGB2XYZ_matrix = np.array([[0.412391, 0.357584, 0.180481],[0.212639, 0.715169, 0.072192],[0.019331, 0.119195, 0.950532]])if mode == "P3":RGB2XYZ_matrix = np.array([[0.486571, 0.265668, 0.198217], [0.228975, 0.691739, 0.079287], [-0.0000003, 0.045113, 1.043944]])XYZ = np.matmul(RGB2XYZ_matrix, RGB)return XYZ
  • XYZ2RGB Code
def XYZ2RGB(XYZ, mode):if mode == "sRGB":XYZ_to_RGB_matrix = np.array([[3.2404542, -1.5371385, -0.4985314],[-0.9692660, 1.8760108, 0.0415560],[0.0556434, -0.2040259, 1.0572252]])elif mode == "P3":XYZ_to_RGB_matrix = np.array([[2.4935223, -0.9313173, -0.4027241],[-0.8294634, 1.7626022, 0.0236200],[0.0358510, -0.0761817, 0.9570290]])RGB = np.matmul(XYZ_to_RGB_matrix, XYZ)return RGB
XYZ2LAB / LAB2XYZ

转换参考色Xr, Yr, Zr使用D65光源。其中,L∈(0, 100),a∈(-128, 127),代表红绿,b∈(-128, 127),代表黄蓝。在OpenCV中,对LAB数据对齐做了量化,使其处于0~255的范围。

  • 基于LAB空间,可以计算色差ΔE
  • 也可以计算Δab
  • XYZ2LAB Code
def XYZ2LAB(XYZ):XYZ = np.array(XYZ).astype(np.float64) * 100# d65white = np.array([95.0489, 100.00, 108.884])LAB = np.array([0.0, 0.0, 0.0])fx = np.array([0.0, 0.0, 0.0])for c in range(3):r_white = 0if (XYZ[c] / white[c]) > ((6.0 / 29.0) ** 3.0):r_white = 1fx[c] = fx[c] + r_white * (XYZ[c] / white[c]) ** (1 / 3.0)fx[c] = fx[c] + (1 - r_white) * ((841.0 / 108.0) * XYZ[c] / white[c] + 4.0 / 29.0)LAB[0] = 116 * fx[1] - 16LAB[1] = 500 * (fx[0] - fx[1])LAB[2] = 200 * (fx[1] - fx[2]return LAB
  • LAB2XYZ Code
def LAB2XYZ(LAB):white = np.array([95.0489, 100.00, 108.884])xyz = np.array([0.0, 0.0, 0.0])XYZ = np.array([0.0, 0.0, 0.0])fx = np.array([0.0, 0.0, 0.0])fx[1] = (LAB[0] + 16) / 116fx[0] = LAB[1] / 500 + fx[1]fx[2] = fx[1] - LAB[2] / 200if fx[0] ** 3.0 > ((6.0 / 29.0) ** 3.0):xyz[0] = fx[0] ** 3.0else:xyz[0] = (108.0 / 841.0) * fx[0] - 432.0 / 24389.0if LAB[0] > 8.0:xyz[1] = ((LAB[0] + 16) / 116) ** 3.0else:xyz[1] = LAB[0] * (3.0 / 29.0) ** 3.0if fx[2] ** 3.0 > ((6.0 / 29.0) ** 3.0):xyz[2] = fx[2] ** 3.0else:xyz[0] = (108.0 / 841.0) * fx[2] - 432.0 / 24389.0for c in range(3):XYZ[c] = xyz[c] * white[c] / 100return XYZ
  • ΔE / Δab Code
def calculate_deltaE_deltaAB(LAB1, LAB2):[L1, A1, B1] = np.array([LAB1[..., x] for x in range(LAB1.shape[-1])])[L2, A2, B2] = np.array([LAB2[..., x] for x in range(LAB2.shape[-1])])deltaE = np.sqrt((L1 - L2) ** 2 + (A1 - A2) ** 2 + (B1 - B2) ** 2)deltaAB = np.sqrt((A1 - A2) ** 2 + (B1 - B2) ** 2)return deltaE, deltaAB
LAB2LCH

  • 基于LCH色彩空间,可以计算ΔHue
  • 也可以计算ΔChroma
  • LAB2LCH Code
def LAB2LCH(LAB)LAB = np.array(LAB)[L, A, B] = np.array([LAB[..., x] for x in range(LAB.shape[-1])])C = np.hypot(A, B)H = np.rad2deg(np.arctan2(B, A))LCH = np.concatenate([x[..., np.newaxis]] for x in [L, C, H], axis=-1)return LCH
  • ΔHue / ΔChroma Code
def calculate_delta_hue_chroma(LCH1, LCH2):[L1, C1, H1] = np.array([LCH1[..., x] for x in range(LCH1.shape[-1])])[L2, C2, H2] = np.array([LCH2[..., x] for x in range(LCH2.shape[-1])])D_hue = abs(H1 - H2)D_chroma = C1 - C2return D_hue, D_chroma
RGB2HSL / HSL2RGB



  • RGB2HSL Code
def RGB2HSL(RGB):R, G, B = RGB[:, 0], RGB[:, 1], RGB[:, 2]max_rgb, argmax_rgb = RGB.max(1)min_rgb, argmin_rgb = RGB.min(1)del_rgb = max_rgb - min_rgbdel_R = 60.0 * (G - B) / (del_rgb + epsilon)del_G = 60.0 * (B - R) / (del_rgb + epsilon) + 120.0del_B = 60.0 * (R - G) / (del_rgb + epsilon) + 240.0H = torch.stack((del_R, del_G, del_B), dim=0).gather(dim=0, index=argmax_rgb.unsqueeze(0)).squeeze(0)H = torch.where(H < 0, H + 360, H)L = (max_rgb + min_rgb) / 2S = torch.where(L > 0.5, del_rgb / (2 - 2 * L + epsilon), del_rgb / (2 * L + epsilon))HSL = torch.stack((H, S, L), dim=1)return HSL
  • HSL2RGB Code
def HSL2RGB(HSL):H, S, L = HSL[:, 0].clone(), HSL[:, 1], HSL[:, 2]var_2 = torch.where(L < 0.5, L * (1 + S), (L + S) - (L * S))var_1 = 2.0 * L - var_2H = H / 360.0R = hue2rgb(var_1, var_2, h + (1.0 / 3.0))G = hue2rgb(var_1, var_2, h)B = hue2rgb(var_1, var_2, h - (1.0 / 3.0))rgb_lut = torch.stack((R, G, B), dim=1)return rgb_lutdef hue2rgb(v1, v2, vh):vh_temp = (vh + 1).frac()c1 = v1 + (v2 - v1) * 6.0 * vh_tempc2 = c3 = v2c4 = v1 + (v2 - v1) * ((2.0 / 3.0) - vh_temp) * 6.0c5 = c6 = v1c = torch.stack((c1, c2, c3, c4, c5, c6), dim=0)index = (torch.ceil(vh_temp * 6)).to(torch.long) - 1index = torch.where(index < 0, 0, index)c = (c.gather(dim=0, index=index.unsqueeze(0))).squeeze(0)return c
RGB2HSV / HSV2RGB
  • 对于RGB2HSV,色相H的定义相同,其他分量S, V不同
  • 对于HSV2RGB,如果饱和度S和明度V变化于0~1之间,那么RGB可以表示为
  • RGB2HSV Code
# answer
def rgb2hsv(img):_img = img.copy().astype(np.float32)# / 255v_max = _img.max(axis=2)v_min = _img.min(axis=2)v_argmin = _img.argmin(axis=2)hsv = np.zeros_like(_img, dtype=np.float32)r, g, b = np.split(_img, 3, axis=2)r, g, b = r[..., 0], g[..., 0], b[..., 0]diff = np.maximum(v_max - v_min, 1e-10)# Hueind = v_argmin == 2hsv[..., 0][ind] = 60 * (g - r)[ind] / diff[ind] + 60ind = v_argmin == 0hsv[..., 0][ind] = 60 * (b - g)[ind] / diff[ind] + 180ind = v_argmin == 1hsv[..., 0][ind] = 60 * (r - b)[ind] / diff[ind] + 300ind = v_max == v_minhsv[..., 0][ind] = 0# Saturationhsv[..., 1] = v_max - v_min# Valuehsv[..., 2] = v_maxreturn hsv
  • HSV2RGB Code
def hsv2rgb(hsv):h, s, v = np.split(hsv, 3, axis=2)h, s, v = h[..., 0], s[..., 0], v[..., 0]_h = h / 60x = s * (1 - np.abs(_h % 2 - 1))z = np.zeros_like(x)vals = np.array([[s, x, z], [x, s, z], [z, s, x], [z, x, s], [x, z, s], [s, z, x]])img = np.zeros_like(hsv)for i in range(6):ind = _h.astype(int) == ifor j in range(3):img[..., j][ind] = (v - s)[ind] + vals[i, j][ind]return np.clip(img, 0, 255).astype(np.uint8)
RGB2YUV / YUV2RGB (Origin)

思路:由Kr, Kg, Kb而来,代表整体R, G, B亮度比例

  • BT.601

  • BT.709

  • Adobe RGB

  • Display P3

  • Theater P3

  • BT.2020

  • RGB2YUV Code
def RGB2YUV(RGB, mode):if mode == "BT601":RGB_to_YUV_matrix = np.array([[0.299, 0.587, 0.114],[-0.169, -0.331, 0.5],[0.5, -0.419, -0.081]])elif mode == "BT709":RGB_to_YUV_matrix = np.array([[0.2126, 0.7152, 0.072],[-0.1146, -0.3854, 0.5],[0.5, -0.4542, -0.0458]])elif mode == "AdobeRGB":RGB_to_YUV_matrix = np.array([[0.2973, 0.6274, 0.0753],[-0.1608, -0.3392, 0.5],[0.5, -0.4464, -0.0536]])elif mode == "DisplayP3":RGB_to_YUV_matrix = np.array([[0.2290, 0.6917, 0.0793],[-0.1243, -0.3757, 0.5],[0.5, -0.4486, -0.0514]])elif mode == "TheaterP3":RGB_to_YUV_matrix = np.array([[0.2095, 0.7216, 0.0689],[-0.1125, -0.3875, 0.5],[0.5, -0.4564, -0.0436]])elif mode == "BT2020":RGB_to_YUV_matrix = np.array([[0.2627, 0.6780, 0.0593],[-0.1396, -0.3604, 0.5],[0.5, -0.4598, -0.0402]])YUV = np.matmul(RGB_to_YUV_matrix, RGB)return YUV
  • YUV2RGB Code
def YUV2RGB(YUV, mode):if mode == "BT601":YUV_to_RGB_matrix = np.array([[1.0000, -0.0009, 1.4017],[1.0000, -0.3437, -0.7142],[1.0000, 1.7722, 0.0010]])elif mode == "BT709":YUV_to_RGB_matrix = np.array([[1.0000, -0.0009, 1.5747],[1.0000, -0.1873, -0.4682],[1.0000, 1.8556, 0.0000]])elif mode == "AdobeRGB":YUV_to_RGB_matrix = np.array([[1.0000, 0.0000, 1.4053],[1.0000, -0.2220, -0.6661],[1.0000, 1.8494, 0.0000]])elif mode == "DisplayP3":YUV_to_RGB_matrix = np.array([[1.0000, 0.0000, 1.5421],[1.0000, -0.2111, -0.5104],[1.0000, 1.8414, 0.0000]])elif mode == "TheaterP3":YUV_to_RGB_matrix = np.array([[1.0000, 0.0000, 1.5810],[1.0000, -0.1778, -0.4590],[1.0000, 1.8622, 0.0000]])elif mode == "BT2020":YUV_to_RGB_matrix = np.array([[1.0000, 0.0000, 1.4746],[1.0000, -0.1646, -0.5714],[1.0000, 1.8814, 0.0000]])RGB = np.matmul(YUV_to_RGB_matrix, YUV)return RGB
RGB2YUV / YUV2RGB (Full Range)

所有RGB和YCbCr的范围都是0~255,与RGB2YUV转换公式一致,最后加上0, 128, 128用来拉伸至255

  • BT.601

  • BT.709

  • Adobe RGB

  • Display P3

  • Theater P3

  • BT.2020

RGB2YUV / YUV2RGB (Limited Range)

指Y, Cb, Cr的值不到最大值的255,其中Y的范围16~235,Cb和Cr为16-240,RGB范围为0-255。Limit Range由Full Range转换而来,先将Y, U, V各通道乘以219, 224, 224转成Y, Cb, Cr,再将得到的数除以255得到系数,如果要转为8bit再乘以256

  • BT.601

  • BT.709

  • Adobe RGB

  • Display P3

  • Theater P3

  • BT.2020

详解色彩模型、色域以及颜色空间转换相关推荐

  1. 【转】图形流水线中坐标变换详解:模型矩阵、视角矩阵、投影矩阵

    转自:图形流水线中坐标变换详解:模型矩阵.视角矩阵.投影矩阵_sherlockreal的博客-CSDN博客_视角矩阵 图形流水线中坐标变换详解:模型矩阵.视角矩阵.投影矩阵 图形流水线中坐标变换过程 ...

  2. 图形流水线中坐标变换详解:模型矩阵、视角矩阵、投影矩阵

    图形流水线中坐标变换详解:模型矩阵.视角矩阵.投影矩阵 图形流水线中坐标变换过程 模型矩阵:模型局部坐标系和世界坐标系之间的桥梁 1.模型局部坐标系存在的意义 2.根据模型局部坐标系中点求其在世界坐标 ...

  3. 公开课报名 | 详解CNN-pFSMN模型以及在语音识别中的应用

    近年来,在深度学习技术的帮助下,语音识别取得了极大的进展,从实验室开始走向市场,走向实用化.基于语音识别技术的输入法.搜索和翻译等人机交互场景都有了广泛的应用. Librispeech是当前衡量语音识 ...

  4. 公开课 | 详解CNN-pFSMN模型以及在语音识别中的应用

    近年来,在深度学习技术的帮助下,语音识别取得了极大的进展,从实验室开始走向市场,走向实用化.基于语音识别技术的输入法.搜索和翻译等人机交互场景都有了广泛的应用. Librispeech是当前衡量语音识 ...

  5. Apollo进阶课程㉘丨Apollo控制技术详解——基于模型的控制方法

    原文链接:进阶课程㉘丨Apollo控制技术详解--基于模型的控制方法 PID控制是一个在工业控制应用中常见的反馈回路部件,由比例单元P.积分单元I和微分单元D组成.PID控制的基础是比例控制:积分控制 ...

  6. 电机标幺化、PI标幺化、锁相环PLL标幺化 详解电机模型相关标幺化处理

    电机标幺化.PI标幺化.锁相环PLL标幺化 详解电机模型相关标幺化处理 电流环PI控制器的标幺化处理 观测器中PLL锁相环的标幺化处理 采样时间处理 这是文档,不是代码,文档中的代码均为引用举例子的 ...

  7. 电机标幺化、PI标幺化、锁相环PLL标幺化 详解电机模型相关标幺化处理 电流环PI控制器的标幺化处理

    电机标幺化.PI标幺化.锁相环PLL标幺化 详解电机模型相关标幺化处理 电流环PI控制器的标幺化处理 观测器中PLL锁相环的标幺化处理 采样时间处理 这是文档,不是代码,文档中的代码均为引用举例子的 ...

  8. 详解概率图模型——概述

    详解概率图模型--概述 详解概率图模型--概述 概率图 概览 有向图 vs. 无向图 有向图 无向图 判别式(discriminative)模型 and 生成式(generative)模型 前言 两个 ...

  9. 非阻塞网络编程详解------IO模型

    1.前言 随着互联网的发展,面对海量用户高并发业务,传统的阻塞式的服务端架构模式已经无能为力.本文(和下篇<高性能网络编程(六):一文读懂高性能网络编程中的线程模型>)旨在为大家提供有用的 ...

最新文章

  1. 第一章:火狐浏览器 : 环境配置: FireFox 版本38 + jdk 7 + selenium 2.53.6 + selenum-version 2.48.2...
  2. 汉高澳大利亚matrix矩阵计算器
  3. 【STM32】GPIO模拟I2C程序示例
  4. Mr.J-- jQuery学习笔记(二十二)--入口函数
  5. ASML 发布2021年第三季度财报
  6. elasticsearch java 分页查询_elasticsearch深度分页问题
  7. maven聚合工程打包_史诗级!有手就会的Maven教程(八)
  8. 因为一个YYYY-MM-dd的Bug,我被老板骂的狗血淋头!
  9. Shell命令学习笔记
  10. 高速电路设计与仿真之PCB篇(二)
  11. win10下装黑苹果双系统_高手拆换GPD P2 Max无线模块,实现完美黑苹果
  12. 深信服设备连接linux,deepin官方论坛-深度科技官网旗下网站
  13. 论文发表的刊物级别怎么查询呢
  14. 一个时代的终结:为什么是时候放弃ITOM四大巨头了?这对IT领导者来说意味着什么?
  15. 3400位造型师,80位大数据科学家,这家美国女装公司这么做个性化定制
  16. 巧用热图展示基因分布的总体趋势
  17. Django计算机毕业设计jspm高校职称申报系统(程序+LW)Python
  18. python龙格库塔_龙格库塔积分法
  19. 鸿蒙之始写完了吗,【精选】重阳节作文合集六篇
  20. PaperWeekly 第32期 | 基于知识图谱的问答系统关键技术研究 #01

热门文章

  1. 汇编指令lmm_动画视频角色的LMM神经网络
  2. 9 mybatis中使用Java8的日期LocalDate、LocalTime、LocalDateTime
  3. 前端怎么画三角形_css画出三角形和梯形
  4. Qt音视频开发27-Onvif设备搜索
  5. 用Markdown优雅地一键排版公众号 解决公众号排版代码块换行错误的问题
  6. 如何解除病毒对各种杀毒软件的劫持
  7. matlab 求对称,matlab-线性代数 判断 矩阵的对称、实对称、反对称
  8. 计算机中rom,计算机中RAM和ROM
  9. 15年IT经验,如何从一无所有成为上市公司高层!
  10. Basic Concepts in Graphics and Architecture