def rgb2hsi(rgb: np.ndarray, *, axis: int = None) -> np.ndarray: """ Convert RGB to Hue Saturation Intensity :param rgb: :param axis: :return: """ if axis is None: axis = get_matching_axis(rgb.shape, 3) big_m, little_m, chroma = _compute_chroma(rgb, axis) inds = construct_component_inds(axis, rgb.ndim, 3) hsi = np.zeros(rgb.shape) hsi[inds[0]] = _compute_rgb_hue(rgb, big_m, little_m, chroma, axis) hsi[inds[2]] = np.mean(rgb, axis=axis, keepdims=True) i_nz = hsi[inds[2]] != 0 # type: np.ndarray if little_m.ndim < i_nz.ndim: # This only happens in the 1D case little_m = little_m[slice(None), np.newaxis] if np.any(i_nz): hsi[inds[1]][i_nz] = 1 - little_m[i_nz] / hsi[inds[2]][i_nz] return hsi
def hsl2rgb(hsl: np.ndarray, *, axis: int = None) -> np.ndarray: """ Convert from Hue Saturation Lightness (HSL) to RGB :type hsl: np.ndarray :param hsl: :param axis: :return: """ if axis is None: axis = get_matching_axis(hsl.shape, 3) inds = construct_component_inds(axis, hsl.ndim, 3) chroma = ((1. - np.abs(2. * hsl[inds[2]] - 1.)) * hsl[inds[1]] ) # type: np.ndarray h_prime = hsl[inds[0]] / 60. x = chroma * (1 - np.abs(np.mod(h_prime, 2) - 1)) rgb1 = _compute_rgb1(hsl.shape, inds, h_prime, x, chroma) little_m = hsl[inds[2]] - chroma / 2. if little_m.ndim > rgb1.ndim: # This only happens if hsl is 1-D return rgb1 + little_m[0] else: return rgb1 + little_m
def xyz2xyy(xyz: np.ndarray, *, axis: int = None, illuminant: Illuminant = None, observer: Observer = None) -> np.ndarray: """ Convert XYZ to xyY :param xyz: :param axis: :param illuminant: :param observer: :return: """ if axis is None: axis = get_matching_axis(xyz.shape, 3) if illuminant is None: illuminant = get_default_illuminant() if observer is None: observer = get_default_observer() inds = construct_component_inds(axis, xyz.ndim, 3) denominator = np.sum(xyz, axis, keepdims=True) nzd = denominator != 0 xyy = np.zeros(xyz.shape) if np.any(nzd): xyy[inds[0]][nzd] = xyz[inds[0]][nzd] / denominator[nzd] xyy[inds[1]][nzd] = xyz[inds[1]][nzd] / denominator[nzd] xyy[inds[2]] = xyz[inds[1]] if not np.all(nzd): # For any point that is pure black (X=Y=Z=0), give it the # chromaticity of the white point of the specified illuminant and # observer. white_point = illuminant.get_white_point(observer) # to prevent infinite recursion, ensure that the white point is # non-black if white_point[1] > 0: zd = np.logical_not(nzd) white_point_xyy = xyz2xyy(white_point, illuminant=illuminant, observer=observer) xyy[inds[0]][zd] = white_point_xyy[0] xyy[inds[1]][zd] = white_point_xyy[1] return xyy
def lab2lch(lab: np.ndarray, *, axis: int = None) -> np.ndarray: """ Convert L*a*b* to LCh :param lab: :param axis: :return: """ if axis is None: axis = get_matching_axis(lab.shape, 3) inds = construct_component_inds(axis, lab.ndim, 3) lch = np.zeros(lab.shape) lch[inds[0]] = lab[inds[0]] lch[inds[1]] = np.sqrt(lab[inds[1]]**2 + lab[inds[2]]**2) lch[inds[2]] = np.mod( (180 / np.pi) * np.arctan2(lab[inds[2]], lab[inds[1]]), 360.) return lch
def rgb2hcy(rgb: np.ndarray, *, axis: int = None) -> np.ndarray: """ Convert from RGB to Hue, Chroma, Luma (Y'_601) :param rgb: :param axis: :return: """ if axis is None: axis = get_matching_axis(rgb.shape, 3) big_m, little_m, chroma = _compute_chroma(rgb, axis) inds = construct_component_inds(axis, rgb.ndim, 3) hcy = np.zeros(rgb.shape) hcy[inds[0]] = _compute_rgb_hue(rgb, big_m, little_m, chroma, axis) hcy[inds[1]] = chroma hcy[inds[2]] = 0.299 * rgb[inds[0]] + 0.587 * rgb[inds[1]] + 0.114 * rgb[ inds[2]] return hcy
def xyy2xyz(xyy, *, axis: int = None) -> np.ndarray: """ converts from xyY to XYZ :param xyy: :param axis: :return: """ if axis is None: axis = get_matching_axis(xyy.shape, 3) inds = construct_component_inds(axis, len(xyy.shape), 3) # Determine where y iz 0 so we don't divide by it nzy = np.nonzero(xyy[inds[1]]) xyz = np.zeros(xyy.shape) xyz[inds[0]][nzy] = xyy[inds[0]][nzy] * xyy[inds[2]][nzy] / xyy[ inds[1]][nzy] xyz[inds[1]][nzy] = xyy[inds[2]][nzy] xyz[inds[2]][nzy] = ((1 - xyy[inds[0]][nzy] - xyy[inds[1]][nzy]) * xyy[inds[2]][nzy] / xyy[inds[1]][nzy]) return xyz
def hcy2rgb(hcy: np.ndarray, *, axis: int = None) -> np.ndarray: """ :param hcy: :param axis: :return: """ if axis is None: axis = get_matching_axis(hcy.shape, 3) inds = construct_component_inds(axis, hcy.ndim, 3) h_prime = hcy[inds[0]] / 60. x: np.ndarray = hcy[inds[1]] * (1 - np.abs(np.mod(h_prime, 2) - 1)) rgb1 = _compute_rgb1(hcy.shape, inds, h_prime, x, hcy[inds[1]]) little_m: np.ndarray = hcy[inds[2]] - ( 0.299 * rgb1[inds[0]] + 0.587 * rgb1[inds[1]] + 0.114 * rgb1[inds[2]]) if little_m.ndim > rgb1.ndim: # This only happens in the 1D case return rgb1 + little_m[0] else: return rgb1 + little_m
def hsv2rgb(hsv: np.ndarray, *, axis: int = None) -> np.ndarray: """ Convert from HSV to RGB :param hsv: :param axis: :return: """ if axis is None: axis = get_matching_axis(hsv.shape, 3) inds = construct_component_inds(axis, hsv.ndim, 3) chroma = hsv[inds[1]] * hsv[inds[2]] h_prime = hsv[inds[0]] / 60. x = chroma * (1. - np.abs(np.mod(h_prime, 2.) - 1)) # type: np.ndarray rgb1 = _compute_rgb1(hsv.shape, inds, h_prime, x, chroma) little_m = hsv[inds[2]] - chroma if little_m.ndim > rgb1.ndim: # This only happens in the 1D case return rgb1 + little_m[0] else: return rgb1 + little_m
def lab2xyzr(lab: np.ndarray, *, axis: int = None) -> np.ndarray: """ Convert LAB to normalized XYZ :param lab: :param axis: :return: """ if axis is None: axis = get_matching_axis(lab.shape, 3) inds = construct_component_inds(axis, len(lab.shape), 3) fxyz = np.zeros(lab.shape) fxyz[inds[1]] = (lab[inds[0]] + 16) / 116 fxyz[inds[0]] = lab[inds[1]] / 500 + fxyz[inds[1]] fxyz[inds[2]] = fxyz[inds[1]] - lab[inds[2]] / 200 is_small = fxyz <= (LAB_EPS**(1.0 / 3.0)) is_big = np.logical_not(is_small) xyzr = np.zeros(lab.shape) xyzr[is_big] = fxyz[is_big]**3.0 xyzr[is_small] = (116 * fxyz[is_small] - 16) / LAB_KAPPA return xyzr
def rgb2hsv(rgb: np.ndarray, *, axis: int = None) -> np.ndarray: """ Convert from RGB to Hue Saturation Value (HSV) :param rgb: :param axis: :return: """ if axis is None: axis = get_matching_axis(rgb.shape, 3) big_m, little_m, chroma = _compute_chroma(rgb, axis) inds = construct_component_inds(axis, rgb.ndim, 3) hsv = np.zeros(rgb.shape) hsv[inds[0]] = _compute_rgb_hue(rgb, big_m, little_m, chroma, axis) hsv[inds[2]] = big_m big_m_nz = big_m != 0 hsv[inds[1]][big_m_nz] = chroma[big_m_nz] / big_m[big_m_nz] return hsv
def _compute_rgb_hue(rgb: np.ndarray, big_m, little_m, chroma, axis: int) -> np.ndarray: """ Compute the RGB Hue. This is the same for HSV and HSL """ inds = construct_component_inds(axis, rgb.ndim, 3) r = rgb[inds[0]] g = rgb[inds[1]] b = rgb[inds[2]] if chroma.ndim < r.ndim: # this will only happen when chroma is 1-D chroma = chroma[(slice(None), np.newaxis)] ch_is_nz = chroma != 0. m_is_r = np.logical_and(big_m == r, ch_is_nz) m_is_g = np.logical_and(big_m == g, ch_is_nz) m_is_b = np.logical_and(big_m == b, ch_is_nz) h_prime = np.zeros(r.shape) if np.any(m_is_r): h_prime[m_is_r] = np.mod((g[m_is_r] - b[m_is_r]) / chroma[m_is_r] + 6., 6.) if np.any(m_is_g): h_prime[m_is_g] = (b[m_is_g] - r[m_is_g]) / chroma[m_is_g] + 2. if np.any(m_is_b): h_prime[m_is_b] = (r[m_is_b] - g[m_is_b]) / chroma[m_is_b] + 4. return 60. * h_prime
def hsi2rgb(hsi: np.ndarray, *, axis: int = None) -> np.ndarray: """ Convert Hue Saturation Intensity (HSI) to RGB :param hsi: :param axis: :return: """ if axis is None: axis = get_matching_axis(hsi.shape, 3) inds = construct_component_inds(axis, hsi.ndim, 3) h_prime = hsi[inds[0]] / 60. z = 1 - np.abs(np.mod(h_prime, 2.) - 1) chroma = 3 * hsi[inds[2]] * hsi[inds[1]] / (1 + z) # type: np.ndarray x = chroma * z rgb1 = _compute_rgb1(hsi.shape, inds, h_prime, x, chroma) little_m = hsi[inds[2]] * (1 - hsi[inds[1]]) # type: np.ndarray if little_m.ndim > rgb1.ndim: # This only happens in the 1D case return rgb1 + little_m[0] else: return rgb1 + little_m
def rgb2hsl(rgb: np.ndarray, *, axis: int = None) -> np.ndarray: """ Convert RGB to Hue Saturation Lightness :param rgb: :param axis: :return: """ if axis is None: axis = get_matching_axis(rgb.shape, 3) big_m, little_m, chroma = _compute_chroma(rgb, axis) inds = construct_component_inds(axis, rgb.ndim, 3) hsl = np.zeros(rgb.shape) hsl[inds[0]] = _compute_rgb_hue(rgb, big_m, little_m, chroma, axis) l = 0.5 * (big_m + little_m) hsl[inds[2]] = l l_lt_one = l < 1. if np.any(l_lt_one): hsl[inds[1]][l_lt_one] = ((big_m[l_lt_one] - little_m[l_lt_one]) / (1. - np.abs(2 * l[l_lt_one] - 1))) return hsl