如何将sRGB转换为线性sRGB以计算OpenCV中的颜色校正矩阵(CCM)?

4

我参考了以下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个回答

8
从术语角度来看,假设您的图像已经有效地采用sRGB编码,即遵循IEC 61966-2-1:1999标准,那么您正在应用sRGB电光传输函数(EOTF),一种颜色分量转换函数(CCTF)对sRGB编码的非线性光值进行解码,因此说:
“我想从sRGB颜色空间转换到线性RGB空间”
是不正确的,因为您仍然有效地使用sRGB编码的颜色,唯一的区别是在使用解码CCTF之前它们被非线性编码了。加性RGB颜色空间由一组三个分量定义:原色、白点和CCTF。通过使用CCTF,您没有改变原色或白点,即色域是相同的,因此您应该更多地说:
“我想从sRGB颜色空间转换到线性sRGB颜色空间”
现在要验证您的方法是否正确,可以与参考实现进行比较,例如Colour,其代码在您引用的SO线程中使用:18%灰色在使用sRGB反向EOTF进行非线性编码时为118。
>>> int(round(colour.models.eotf_inverse_sRGB(0.18) * 255))
118

从那里,您可以检查您的方法是否将其转换回18%(不考虑四舍五入)!

0.18116424424986022

你好,非常感谢您澄清了一些重要的概念,并分享了关于Color lib的信息。我已经尝试使用我的代码,并通过首先对其进行归一化((118,118,118) / 255.0),将18%灰度值(118,118,118)转换,得到结果:0.18116424。 - Sweta Dwivedi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接