cutcutcodec.core.colorspace.func

Mathematical functions to switching from a color space to another.

Functions

convert(src, dst)

Return the symbolic expression to convert colorspace.

rgb2xyz_matrix_from_chroma(xy_r, xy_g, xy_b, ...)

Compute the RGB to XYZ matrix from chromaticity coordinates and white point.

rgb2yuv_matrix_from_kr_kb(k_r, k_b)

Compute the RGB to YpPbPr matrix from the kr and kb constants.

yuv_cst_from_chroma(xy_r, xy_g, xy_b, xy_w)

Compute the kr and kb constants from chromaticity coordinates and white point.

Details

cutcutcodec.core.colorspace.func.convert(src: Colorspace | str, dst: Colorspace | str) tuple[Basic, Basic, Basic][source]

Return the symbolic expression to convert colorspace.

Parameters

src, dstColorspace or str

The source and destination colorspace.

Returns

componantstuple[sympy.core.basic.Basic, sympy.core.basic.Basic, sympy.core.basic.Basic]

The 3 sympy equations that link the input color space components, to each of the output components.

Examples

>>> import sympy, torch
>>> from cutcutcodec.core.colorspace.func import convert
>>> from cutcutcodec.core.colorspace.cst import SPACES
>>> from cutcutcodec.core.compilation.sympy_to_torch.lambdify import Lambdify
>>> convert("y'pbpr_bt709", "r'g'b'_bt709")[0]
12901312*p_r/8192847 + y'
>>> trans_symb = convert("y'pbpr_bt709", "y'pbpr_bt2020")
>>> trans_symb = trans_symb.subs(zip(SPACES["y'pbpr"], sympy.symbols("y u v", real=True)))
>>> trans_func = Lambdify(trans_symb)
>>> yuv_709 = torch.rand(1_000_000), torch.rand(1_000_000)-0.5, torch.rand(1_000_000)-0.5
>>> yuv_2020 = trans_func(y=yuv_709[0], u=yuv_709[1], v=yuv_709[2])
>>>
cutcutcodec.core.colorspace.func.rgb2xyz_matrix_from_chroma(xy_r: tuple[Real | Basic, Real | Basic], xy_g: tuple[Real | Basic, Real | Basic], xy_b: tuple[Real | Basic, Real | Basic], xy_w: tuple[Real | Basic, Real | Basic]) MutableDenseMatrix[source]

Compute the RGB to XYZ matrix from chromaticity coordinates and white point.

Relationship between tristimulus values in CIE XYZ 1936 color space and in RGB signal space.

It is an implementation of the International Telecomunication Union Report ITU-R BT.2380-2.

Returns the \(\boldsymbol{M}\) matrix with \((r, g, b) \in [0, 1]^3\) such as:

(1)\[\begin{split}\begin{pmatrix} x \\ y \\ z \\ \end{pmatrix} = \boldsymbol{M} \begin{pmatrix} r \\ g \\ b \\ \end{pmatrix}\end{split}\]

Where

\[\begin{split}\begin{cases} (x'_r, y'_r, z'_r) = \left(\frac{x_r}{y_r}, 1, \frac{1-x_r-y_r}{y_r}\right) \\ (x'_g, y'_g, z'_g) = \left(\frac{x_g}{y_g}, 1, \frac{1-x_g-y_g}{y_g}\right) \\ (x'_r, y'_r, z'_r) = \left(\frac{x_r}{y_r}, 1, \frac{1-x_r-y_r}{y_r}\right) \\ (x'_w, y'_w, z'_w) = \left(\frac{x_w}{y_w}, 1, \frac{1-x_w-y_w}{y_w}\right) \\ \begin{pmatrix} s_r \\ s_g \\ s_b \end{pmatrix} = \begin{pmatrix} x'_r & x'_g & x'_b \\ y'_r & y'_g & y'_b \\ z'_r & z'_g & z'_b \\ \end{pmatrix}^{-1} \begin{pmatrix} x'_w \\ y'_w \\ z'_w \end{pmatrix} \\ \boldsymbol{M} = \begin{pmatrix} s_r x'_r & s_g x'_g & s_b x'_b \\ s_r y'_r & s_g y'_g & s_b y'_b \\ s_r z'_r & s_g z'_g & s_b z'_b \\ \end{pmatrix} \\ \end{cases}\end{split}\]

Parameters

xy_rtuple

The red point \((x_r, y_r)\) in the xyz space.

xy_gtuple

The green point \((x_g, y_g)\) in the xyz space.

xy_btuple

The blue point \((x_b, y_b)\) in the xyz space.

xy_wtuple

The white point \((x_w, y_w)\) in the xyz space.

Returns

rgb2xyzsympy.Matrix

The 3x3 \(\boldsymbol{M}\) matrix, sometimes called primaries, which converts points from RGB space to XYZ space (1).

Examples

>>> import sympy
>>> from cutcutcodec.core.colorspace.func import rgb2xyz_matrix_from_chroma
>>> wrgb = sympy.Matrix([[1, 1, 0, 0],  # red
...                      [1, 0, 1, 0],  # green
...                      [1, 0, 0, 1]]) # blue
...
>>> # rec.709
>>> xy_r, xy_g, xy_b, white = (0.640, 0.330), (0.300, 0.600), (0.150, 0.060), (0.3127, 0.3290)
>>> m_709 = rgb2xyz_matrix_from_chroma(xy_r, xy_g, xy_b, white)
>>> # rec.2020
>>> xy_r, xy_g, xy_b, white = (0.708, 0.292), (0.170, 0.797), (0.131, 0.046), (0.3127, 0.3290)
>>> m_2020 = rgb2xyz_matrix_from_chroma(xy_r, xy_g, xy_b, white)
>>>
>>> # convert from rec.709 to rec.2020
>>> (m_2020**-1 @ m_709 @ wrgb).evalf(n=5)
Matrix([
[1.0,   0.6274,  0.32928, 0.043313],
[1.0, 0.069097,  0.91954, 0.011362],
[1.0, 0.016391, 0.088013,   0.8956]])
>>>
cutcutcodec.core.colorspace.func.rgb2yuv_matrix_from_kr_kb(k_r: Real | Basic, k_b: Real | Basic) MutableDenseMatrix[source]

Compute the RGB to YpPbPr matrix from the kr and kb constants.

Relationship between gamma corrected R’G’B’ color space and Y’PbPr color space.

It is an implementation based on wikipedia.

Returns the \(\boldsymbol{A}\) matrix with \((r', g', b') \in [0, 1]^3\) and \((y', p_b, p_r) \in [0, 1] \times \left[-\frac{1}{2}, \frac{1}{2}\right]^2\) such as:

(2)\[\begin{split}\begin{pmatrix} y' \\ p_b \\ p_r \\ \end{pmatrix} = \boldsymbol{A} \begin{pmatrix} r' \\ g' \\ b' \\ \end{pmatrix}\end{split}\]

Where

\[\begin{split}\begin{cases} k_r + k_g + k_b = 1 \\ \boldsymbol{A} = \begin{pmatrix} k_r & k_g & k_b \\ -\frac{k_r}{2-2k_b} & -\frac{k_g}{2-2k_b} & \frac{1}{2} \\ \frac{1}{2} & -\frac{k_g}{2-2k_r} & -\frac{k_b}{2-2k_r} \\ \end{pmatrix} \\ \end{cases}\end{split}\]

Parameters

k_r, k_b

The 2 scalars \(k_r\) and \(k_b\) (1). They may come from cutcutcodec.core.colorspace.func.yuv_cst_from_chroma().

Returns

rgb2yuvsympy.Matrix

The 3x3 \(\boldsymbol{A}\) color matrix.

Examples

>>> import sympy
>>> from cutcutcodec.core.colorspace.func import rgb2yuv_matrix_from_kr_kb
>>> wrgb = sympy.Matrix([[1, 1, 0, 0],  # red
...                      [1, 0, 1, 0],  # green
...                      [1, 0, 0, 1]]) # blue
...
>>> kr, kb = sympy.Rational(0.2126), sympy.Rational(0.0722)  # rec.709
>>> a_709 = rgb2yuv_matrix_from_kr_kb(kr, kb)
>>> (a_709 @ wrgb).evalf(n=5)
Matrix([
[1.0,   0.2126,   0.7152,    0.0722],
[  0, -0.11457, -0.38543,       0.5],
[  0,      0.5, -0.45415, -0.045847]])
>>> kr = kb = sympy.sympify("1/3")  # for demo
>>> rgb2yuv_matrix_from_kr_kb(kr, kb) @ wrgb
Matrix([
[1,  1/3,  1/3,  1/3],
[0, -1/4, -1/4,  1/2],
[0,  1/2, -1/4, -1/4]])
>>>
cutcutcodec.core.colorspace.func.yuv_cst_from_chroma(xy_r: tuple[Real | Basic, Real | Basic], xy_g: tuple[Real | Basic, Real | Basic], xy_b: tuple[Real | Basic, Real | Basic], xy_w: tuple[Real | Basic, Real | Basic]) tuple[Real | Basic, Real | Basic][source]

Compute the kr and kb constants from chromaticity coordinates and white point.

It is an implementation of the International Telecomunication Union Recomandation ITU-T H.273 (V4).

(3)\[\begin{split}k_r = \frac{\det\boldsymbol{R}}{\det\boldsymbol{D}} \\ k_b = \frac{\det\boldsymbol{B}}{\det\boldsymbol{D}} \\\end{split}\]

Where

\[\begin{split}\begin{cases} (x'_r, y'_r, z'_r) = \left(\frac{x_r}{y_r}, 1, \frac{1-x_r-y_r}{y_r}\right) \\ (x'_g, y'_g, z'_g) = \left(\frac{x_g}{y_g}, 1, \frac{1-x_g-y_g}{y_g}\right) \\ (x'_r, y'_r, z'_r) = \left(\frac{x_r}{y_r}, 1, \frac{1-x_r-y_r}{y_r}\right) \\ (x'_w, y'_w, z'_w) = \left(\frac{x_w}{y_w}, 1, \frac{1-x_w-y_w}{y_w}\right) \\ \boldsymbol{D} = \begin{pmatrix} x'_r & y'_r & z'_r \\ x'_g & y'_g & z'_g \\ x'_b & y'_b & z'_b \\ \end{pmatrix} \\ \boldsymbol{R} = \begin{pmatrix} x'_w & x'_g & x'_b \\ y'_w & y'_g & y'_b \\ z'_w & z'_g & z'_b \\ \end{pmatrix} \\ \boldsymbol{B} = \begin{pmatrix} x'_w & x'_r & x'_g \\ y'_w & y'_r & y'_g \\ z'_w & z'_r & z'_g \\ \end{pmatrix} \\ \end{cases}\end{split}\]

Parameters

xy_rtuple

The red point \((x_r, y_r)\) in the xyz space.

xy_gtuple

The green point \((x_g, y_g)\) in the xyz space.

xy_btuple

The blue point \((x_b, y_b)\) in the xyz space.

xy_wtuple

The white point \((x_w, y_w)\) in the xyz space.

Returns

k_r, k_b

The 2 scalars \(k_r\) and \(k_b\) (1) used in rgb to yuv conversion.

Examples

>>> from cutcutcodec.core.colorspace.func import yuv_cst_from_chroma
>>> # rec.709
>>> xy_r, xy_g, xy_b, white = (0.640, 0.330), (0.300, 0.600), (0.150, 0.060), (0.3127, 0.3290)
>>> kr, kb = yuv_cst_from_chroma(xy_r, xy_g, xy_b, white)
>>> round(kr, 5), round(kb, 5)
(0.21264, 0.07219)
>>> # rec.2020
>>> xy_r, xy_g, xy_b, white = (0.708, 0.292), (0.170, 0.797), (0.131, 0.046), (0.3127, 0.3290)
>>> kr, kb = yuv_cst_from_chroma(xy_r, xy_g, xy_b, white)
>>> round(kr, 5), round(kb, 5)
(0.26270, 0.05930)
>>>