如何从sRGB转换为线性sRGB以计算opencv中的色彩校正矩阵? (CCM)

时间:2019-07-15 04:10:16

标签: python opencv image-processing colors

我已经参考以下stackoverflow thread来计算色彩校正矩阵。

如上所述,我想从sRGB颜色空间转换为线性sRGB空间,我尝试使用pwkit colorspace mapper代码进行转换。

但是,我不确定最终的线性sRGB值,因为该函数要求sRGB的范围为[0-1],是否将sRGB值除以255.0,这是正确的方法吗?如何验证函数返回的线性sRGB值正确?

import os
import numpy as np
import cv2 
import matplotlib.pyplot as plt

def srgb_to_linsrgb (srgb):
    """Convert sRGB values to physically linear ones. The transformation is
       uniform in RGB, so *srgb* can be of any shape.

       *srgb* values should range between 0 and 1, inclusively.

    """
    gamma = ((srgb + 0.055) / 1.055)**2.4
    scale = srgb / 12.92
    return np.where (srgb > 0.04045, gamma, scale)


if __name__ == "__main__":

    colorChecker = cv2.imread('C:/Users/Ai/Documents/Urine Sample Analysis/Assets/colorchecker_1.jpg')
    cc = cv2.cvtColor(colorChecker,cv2.COLOR_BGR2RGB)
    plt.imshow(cc)

    #Convert srgb to linear rgb
    cc = cc / 255.0
    cc1 = srgb_to_linsrgb(cc)
    print("Conversion from sRGB to linear RGB:\n")
    print(cc1[1,1,:])

转换结果为:[0.30946892 0.23455058 0.19806932]

输入sRGB应该在0-1之间,如何将sRGB通道的值从[0-255]缩放到[0-1],将简单除以255.0会得出正确的线性sRGB值吗?如何验证转换是否导致正确的线性sRGB值?

1 个答案:

答案 0 :(得分:2)

从术语的角度出发,并假设您的图像已有效地进行sRGB编码,即按照IEC 61966-2-1:1999,您将通过应用sRGB光电传递函数(EOTF)来解码sRGB编码的非线性光值,一种颜色分量传递函数(CCTF),因此说:

  

我想从sRGB颜色空间转换为线性RGB空间

是不正确的,因为您仍在有效地使用sRGB编码的颜色,唯一的区别是在使用解码CCTF之前,它们是非线性编码的。附加RGB色彩空间由一组三个组件定义:原色,白点和CCTF。通过使用CCTF,您并没有在所有的原色或白点上都进行过更改,即色域是相同的,因此您应该说的更多:

  

我想从sRGB颜色空间转换为线性sRGB颜色空间

现在要验证您的方法是正确的,您可以与参考实现(例如Colour)进行比较,该参考实现的代码在所引用的SO线程中使用:使用sRGB逆函数进行非线性编码时18%的灰度为118 EOTF:

>>> int(round(colour.models.eotf_inverse_sRGB(0.18) * 255))
118

从那里您可以检查您的方法是否确实转换回18%并且转换了(忽略舍入)!

0.18116424424986022