cutcutcodec.core.colorspace.func
Tools for switching from one color space to another.
The equations used are consistent with:
The filter zscale used in ffmpeg.
The brucelinbloom website.
The coulour_science python library.
Functions
|
Return the symbolic expression to convert colorspace. |
|
Guess a gamut and gamma based on the image shape. |
|
Compute the RGB to XYZ matrix from chromaticity coordinates and white point. |
|
Compute the RGB to YpPbPr matrix from the kr and kb constants. |
|
Compute the kr and kb constants from chromaticity coordinates and white point. |
Details
- cutcutcodec.core.colorspace.func.convert(src: str, dst: str) tuple[Basic, Basic, Basic][source]
Return the symbolic expression to convert colorspace.
Parameters
- src, dststr
The source and destination colorspace formatted as {name}[_{colorspace}]. with name in « y’bpbr », « r’g’b” », « rgb », « xyz ».
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 SYMBS >>> from cutcutcodec.core.compilation.sympy_to_torch.lambdify import Lambdify >>> trans_symb = convert("y'pbpr_bt709", "y'pbpr_bt2020") >>> trans_symb = trans_symb.subs(zip(SYMBS["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.guess_space(height: Integral, width: Integral) tuple[str, str][source]
Guess a gamut and gamma based on the image shape.
It comes from https://wiki.x266.mov/docs/colorimetry/primaries#2-unspecified.
Parameters
- height, widthint
The image shape
Returns
- primariesstr
A guessed primary color space gamut.
- transferstr
A guessed primary transfer function gamma.
- 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 colour space and in RGB signal space.
It is an implementation of the International Telecomunication Union Report ITU-R BT.2380-2.
Returns the \(\mathbf{M}\) matrix with \((r, g, b) \in [0, 1]^3\) such as:
(1)\[\begin{split}\begin{pmatrix} x \\ y \\ z \\ \end{pmatrix} = \mathbf{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} \\ \mathbf{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 \(\mathbf{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” colour space and Y’PbPr colour space.
It is an implementation based on wikipedia.
Returns the \(\mathbf{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} = \mathbf{A} \begin{pmatrix} r' \\ g' \\ b' \\ \end{pmatrix}\end{split}\]Where
\[\begin{split}\begin{cases} k_r + k_g + k_b = 1 \\ \mathbf{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 \(\mathbf{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\mathbf{R}}{\det\mathbf{D}} \\ k_b = \frac{\det\mathbf{B}}{\det\mathbf{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) \\ \mathbf{D} = \begin{pmatrix} x'_r & y'_r & z'_r \\ x'_g & y'_g & z'_g \\ x'_b & y'_b & z'_b \\ \end{pmatrix} \\ \mathbf{R} = \begin{pmatrix} x'_w & x'_g & x'_b \\ y'_w & y'_g & y'_b \\ z'_w & z'_g & z'_b \\ \end{pmatrix} \\ \mathbf{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 convertion.
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) >>>