Exemple #1
0
def ipt_jch(start, amount, saturation, luminosity):
    # Generate colors
    k = 360/amount
    colors = [(luminosity, saturation, start + i*k) for i in range(amount)]

    # From lch to IPT
    ans = ((l/100, c/100*cos(radians(h)), c/100*sin(radians(h)))
           for l, c, h in colors)

    # From IPT to XYZ1
    ans = (convert_color(IPTColor(i, p, t), XYZColor, target_illuminant="d65")
           for i, p, t in ans)
    ipt_colors = (color.get_value_tuple() for color in ans)

    # From JCh to XYZ1
    ans = (cspace_convert(color, "JCh", "XYZ1") for color in colors)
    jch_colors = (color.tolist() for color in ans)

    # Compute average
    ans = (((x1 + x2)/2, (y1 + y2)/2 , (z1 + z2)/2)
           for (x1, y1, z1), (x2, y2, z2)
           in zip(ipt_colors, jch_colors))

    # From XYZ1 to sRGB1
    ans = (cspace_convert(color, "XYZ1", "sRGB1") for color in ans)
    ans = ((color.tolist() for color in ans))
    ans = (sRGBColor(*color) for color in ans)

    return to_hex_rgb(ans)
Exemple #2
0
 def get_sRGB1_color_points(self, norm = 1.0, use_deuteranomaly = False ):
     cp = self.get_color_points(norm)
     sRGB1_color_points = []
     for i in range(3):
         sRGB1_color_points.append(cspace_convert(cp[i], self.color_space, "sRGB1"))
     if use_deuteranomaly:
         for i in range(3):
             sRGB1_color_points[i] = np.clip(cspace_convert(sRGB1_color_points[i], cvd_space, "sRGB1"),0,1)
     return sRGB1_color_points
Exemple #3
0
def desaturate(hex_color, n):
    if n == 1:
        return hex_color
    cspace = 'CIELab'
    dim = 0
    jch_color = cspace_convert([hex2color(hex_color)], 'sRGB1', cspace)
    desats = np.repeat(jch_color, n, axis=0)
    orig_sat = jch_color[0, dim]
    desats[:, dim] = orig_sat * np.linspace(0.25, 1, n)
    return np.clip(cspace_convert(desats, cspace, 'sRGB1'), 0, 1)
Exemple #4
0
 def mix(color1, color2):
     rgb1, rgb2 = hex_to_rgb(color1), hex_to_rgb(color2)
     x1, y1, z1 = cspace_convert(rgb1, "sRGB255", cie_string).tolist()
     x2, y2, z2 = cspace_convert(rgb2, "sRGB255", cie_string).tolist()
     ans = ((x1 + x2)/2, (y1 + y2)/2 , (z1 + z2)/2)
     ans = cspace_convert(ans, cie_string, "sRGB1").tolist()
     ans = sRGBColor(*ans)
     ans = (ans.clamped_rgb_r, ans.clamped_rgb_g, ans.clamped_rgb_b)
     ans = tuple(round(i*255) for i in ans)
     return "#%02x%02x%02x" % ans
Exemple #5
0
def transform(ctab, src='sRGB1', dst='CAM02-UCS', inverse=False):
    """Transform a colortable between color spaces"""
    if missing:
        raise ImportError(missing)

    out = ctab.copy()
    if not inverse:
        out[:, :3] = cspace_convert(out[:, :3], src, dst)
    else:
        out[:, :3] = cspace_convert(out[:, :3], dst, src)
    return out
Exemple #6
0
    def convert(self, srgb_image):
        """Slightly more complicated convert"""
        srgb_image = self._validate_input_image(srgb_image)
        grayscale = cspace_convert(srgb_image, 'sRGB1', 'JCh')

        if self.severity == 100:
            grayscale[..., 1] = 0
        else:
            grayscale[..., 1] *= self.severity / 100

        converted = cspace_convert(grayscale, 'JCh', self.dest_space_name)
        return np.clip(converted, 0, 1)
Exemple #7
0
def set_convertor(name, ill='D65'):
    """ Binds the conversion functions LCH2RGB() and RGB2LCH() to the choosen colour package
    """
    global LCH2RGB, RGB2LCH, convertor, illuminant
    if name not in ['custom', 'colorspacious', 'colourscience']:
        print("Unknown conversion module")
        return
    convertor = name
    illuminant = ill
    if name == 'custom':
        LCH2RGB = lambda L, C, H: XYZ2RGB(Lab2XYZ(LCH2Lab((L, C, H))))
        RGB2LCH = lambda R, G, B: Lab2LCH(XYZ2Lab(RGB2XYZ((R, G, B))))
    if name == 'colorspacious':
        from colorspacious import cspace_convert
        func_LCH2RGB = lambda L, C, H: cspace_convert([L, C, H], {
            "name": "CIELCh",
            "XYZ100_w": ill
        }, "sRGB1")
        func_RGB2LCH = lambda R, G, B: cspace_convert([R, G, B], "sRGB1", {
            "name": "CIELCh",
            "XYZ100_w": ill
        })
    if name == 'colourscience':
        import colour as cs
        cs_ill = cs.ILLUMINANTS['CIE 1931 2 Degree Standard Observer'][ill]
        func_LCH2RGB = lambda L, C, H: cs.XYZ_to_sRGB(
            cs.Lab_to_XYZ(cs.LCHab_to_Lab([L, C, H]), illuminant=cs_ill))
        func_RGB2LCH = lambda R, G, B: cs.Lab_to_LCHab(
            cs.XYZ_to_Lab(cs.sRGB_to_XYZ([R, G, B]), illuminant=cs_ill))
    if name == 'colorspacious' or name == 'colourscience':

        def LCH2RGB(L, C, H):
            if hasattr(L, '__iter__'):
                RGB = np.array(list(map(func_LCH2RGB, L, C, H)))
                R = RGB[:, 0]
                G = RGB[:, 1]
                B = RGB[:, 2]
            else:
                R, G, B = func_LCH2RGB(L, C, H)
            return R, G, B

        def RGB2LCH(R, G, B):
            if hasattr(R, '__iter__'):
                LCH = np.array(list(map(func_RGB2LCH, R, G, B)))
                L = LCH[:, 0]
                C = LCH[:, 1]
                H = LCH[:, 2]
            else:
                L, C, H = func_RGB2LCH(R, G, B)
            return L, C, H

    print("convertor = '%s' (illuminant = '%s')" % (name, illuminant))
Exemple #8
0
def colordiff_1d(image,
                 colorspace,
                 channel=0,
                 input_space='sRGB1',
                 uniform_space='CAM02-UCS'):
    """
    Only compute distance along first axis of uniform space
    """
    uniform1 = cspace_convert(image, input_space, uniform_space)
    uniform2 = cspace_convert(colorspace.convert(image), input_space,
                              uniform_space)
    #return np.min(np.abs(uniform1 - uniform2), axis=-1)
    return np.abs(uniform1[..., channel] - uniform2[..., channel])
Exemple #9
0
def decomposeImage(original_image,
                   image_CIELab,
                   lightness,
                   lambdas,
                   alphas,
                   r,
                   display=True):
    Us = []
    Us_RGB = []
    (m, n) = lightness.shape
    for lambda_, alpha in zip(lambdas, alphas):
        print("WLS with parameters : alpha = {}, lambda = {}".format(
            alpha, lambda_))
        print("Building system...")
        A = buildA(original_image, lambda_, r, alpha, alpha)
        print("Solving system...")
        U = (sp.linalg.spsolve(A, lightness.flatten())).reshape((m, n))
        Us.append(U)
        if (display):
            U_RGB = cs.cspace_convert(
                rescaleLightness(changeLightness(image_CIELab, U)), "CIELab",
                "sRGB1")
            Us_RGB.append(U_RGB)

    if (display):
        print("Multi-scale edge-preserving smoothing results :")
        comparePlotList(original_image, Us_RGB,
                        ["lambda = " + str(l) for l in lambdas])

    details = []
    details_RGB = []
    prev = lightness
    for U in Us:
        D = prev - U
        details.append(D)
        prev = U
        if (display):
            D_RGB = cs.cspace_convert(
                rescaleLightness(changeLightness(image_CIELab, D)), "CIELab",
                "sRGB1")
            details_RGB.append(D_RGB)

    base = Us[len(Us) - 1]

    if (display):
        print("Multi-scale detail extraction results :")
        comparePlotList(original_image, details_RGB,
                        ["lambda = " + str(l) for l in lambdas])

    return base, details
Exemple #10
0
def eval_cost(points):
    norm_ucs = colorspacious.cspace_convert(points, norm_space, 'CAM02-UCS')
    deut_ucs = colorspacious.cspace_convert(points, deut_space, 'CAM02-UCS')
    prot_ucs = colorspacious.cspace_convert(points, prot_space, 'CAM02-UCS')
    trit_ucs = colorspacious.cspace_convert(points, trit_space, 'CAM02-UCS')
    dist = np.concatenate([
        spd.pdist(norm_ucs) - norm_min_dist,
        spd.pdist(deut_ucs) - deut_min_dist,
        spd.pdist(prot_ucs) - prot_min_dist,
        spd.pdist(trit_ucs) - trit_min_dist,
    ])
    cost_collision = np.minimum(0, dist)**2
    cost_contrast = -np.log(1 + np.maximum(0, dist))
    return np.sum(cost_collision + cost_contrast)
def get_avg_color(image):
    """Takes an image, converts it to CIECAM02 UCS color space,
    grabs the center pixels, averages the color. We move to UCS
    because it's a perceptually uniform space, in which we can average.
    Then we move to CIECAM02 JCh space to return the hue angle.

    Inputs:
    image:  non-normalized (i.e. RGB 0-1 floats) numpy array of shape(224,224,3)"""

    perceptually_uniform = cspace_convert(image, "sRGB1", "CAM02-UCS")
    avg_center = np.mean(np.mean(perceptually_uniform, axis=0), axis=0)

    avg_center_JCh = cspace_convert(avg_center, "CAM02-UCS", "JCh")

    return avg_center_JCh
Exemple #12
0
def generate_color_table():
    """
    Generate a lookup table with all possible RGB colors, encoded in
    perceptually uniform CAM02-UCS color space.

    Table rows correspond to individual RGB colors, columns correspond to J',
    a', and b' components. The table is stored as a NumPy array.
    """

    widgets = ["Generating color table: ", Percentage(), " ", Bar(), " ", ETA()]
    pbar = ProgressBar(widgets=widgets, maxval=(MAX * MAX)).start()

    i = 0
    colors = np.empty(shape=(NUM_COLORS, 3), dtype=float)
    for r in range(MAX):
        for g in range(MAX):
            d = i * MAX
            for b in range(MAX):
                colors[d + b, :] = (r, g, b)
            colors[d:d + MAX] = cspace_convert(
                colors[d:d + MAX], "sRGB255", "CAM02-UCS"
            )
            pbar.update(i)
            i += 1
    pbar.finish()
    return colors
Exemple #13
0
def generate_palette(colors, size, base=None, no_black=False):
    # Initialize palette with given base or white color
    if base:
        palette = [colors[i, :] for i in base]
    else:
        palette = [colors[-1, :]]  # white
    # Exclude colors that are close to black
    if no_black:
        MIN_DISTANCE_TO_BLACK = 35
        d = np.linalg.norm((colors - colors[0, :]), axis=1)
        colors = colors[d > MIN_DISTANCE_TO_BLACK, :]
    # Initialize distances array
    num_colors = colors.shape[0]
    distances = np.ones(shape=(num_colors, 1)) * 1000
    # A function to recompute minimum distances from palette to all colors
    def update_distances(colors, color):
        d = np.linalg.norm((colors - color), axis=1)
        np.minimum(distances, d.reshape(distances.shape), distances)
    # Build progress bar
    widgets = ['Generating palette: ',
               Percentage(), ' ',
               Bar(), ' ',
               ETA()]
    pbar = ProgressBar(widgets=widgets, maxval=size).start()
    # Update distances for the colors that are already in the palette
    for i in range(len(palette) - 1):
        update_distances(colors, palette[i])
        pbar.update(i)
    # Iteratively build palette
    while len(palette) < size:
        update_distances(colors, palette[-1])
        palette.append(colors[np.argmax(distances), :])
        pbar.update(len(palette))
    pbar.finish()
    return cspace_convert(palette, 'CAM02-UCS', 'sRGB1')
Exemple #14
0
def printRgb2Cam02UCS(rgb):
    jab = cspace_convert(rgb, "sRGB255", "CAM02-UCS")
    jabStr = ','.join([str(np.round(c, decimals=2)) for c in jab])
    rgbStr = 'RGB: [' + ','.join([str(c) for c in rgb]) + ']'
    while len(rgbStr) < 18:
        rgbStr = rgbStr + ' '
    print rgbStr, '|:::| Jab (UCS): ['+jabStr+']'
Exemple #15
0
def printRgb2XYZ100(rgb):
    xyz = cspace_convert(rgb, "sRGB255", "XYZ100")
    xyzStr = ','.join([str(np.round(c, decimals=2)) for c in xyz])
    rgbStr = 'RGB: [' + ','.join([str(c) for c in rgb]) + ']'
    while len(rgbStr) < 18:
        rgbStr = rgbStr + ' '
    print rgbStr, '|:::| XYZ100: ['+xyzStr+']'
Exemple #16
0
def printRgb2Cam02(rgb):
    jch = cspace_convert(rgb, "sRGB255", "CIECAM02")
    jchStr = ','.join([str(np.round(c, decimals=2)) for c in jch])
    rgbStr = 'RGB: [' + ','.join([str(c) for c in rgb]) + ']'
    while len(rgbStr) < 18:
        rgbStr = rgbStr + ' '
    print rgbStr, '|:::| JCh: ['+jchStr+']'
Exemple #17
0
def convert(data, from_space, to_space):
    if from_space == CSPACE1:
        data = np.clip(data, 0, 1)
    new = cspace_convert(data.T, from_space, to_space).T
    if to_space == CSPACE1:
        new = np.clip(new, 0, 1)
    return new
Exemple #18
0
def plot_analytic_vortex_test_data(ax,
                                   my_map,
                                   npts=16,
                                   xmax=1.5,
                                   ymax=1.75,
                                   with_quiver=True,
                                   with_deuteranomaly=False):

    X, Y = np.meshgrid(linspace(0, xmax, xmax * npts),
                       linspace(0, ymax, ymax * npts))
    U = np.sin(2 * pi * Y)
    V = np.cos(2 * pi * X)

    angle = arctan2(V, U)
    magnitude = sqrt(V**2 + U**2)

    magnitude_norm = magnitude / magnitude.max()
    angle_norm = angle

    image = my_map(angle_norm, magnitude_norm)
    if with_deuteranomaly:
        cvd_space = {
            "name": "sRGB1+CVD",
            "cvd_type": "deuteranomaly",
            "severity": 50
        }
        image = clip(cspace_convert(image, cvd_space, "sRGB1"), 0, 1)

    ax.imshow(image,
              origin='lower',
              extent=(0, xmax, 0, ymax),
              interpolation='None')
    if with_quiver: ax.quiver(X, Y, U, V, units='width')
Exemple #19
0
def generate_color_table():
    """
    Generate a lookup table with all possible RGB colors, encoded in
    perceptually uniform CAM02-UCS color space.

    Table rows correspond to individual RGB colors, columns correspond to J',
    a', and b' components. The table is stored as a NumPy array.
    """

    widgets = [
        'Generating color table: ',
        Percentage(), ' ',
        Bar(), ' ',
        ETA()
    ]
    pbar = ProgressBar(widgets=widgets, maxval=(MAX * MAX)).start()

    i = 0
    colors = np.empty(shape=(NUM_COLORS, 3), dtype=float)
    for r in range(MAX):
        for g in range(MAX):
            d = i * MAX
            for b in range(MAX):
                colors[d + b, :] = (r, g, b)
            colors[d:d + MAX] = cspace_convert(colors[d:d + MAX], 'sRGB255',
                                               'CAM02-UCS')
            pbar.update(i)
            i += 1
    pbar.finish()
    return colors
Exemple #20
0
def colorblind(colors, type):
    space = {
        'name': 'sRGB1+CVD',
        'cvd_type': type,
        'severity': 100,
    }
    return np.clip(colorspacious.cspace_convert(colors, space, 'sRGB1'), 0, 1)
Exemple #21
0
def color_palette2(n_colors=6,
                   chroma=0.5,
                   hue_offset=0.1,
                   v_scale="linear",
                   max_lum=1.0):

    h = 360 * hue_offset + np.linspace(0, 360, n_colors, endpoint=False)[::-1]
    C = [chroma * 100] * n_colors

    if v_scale == "linear":
        J = np.linspace(0, max_lum, n_colors)
    elif v_scale == "log":
        J = np.log10(np.linspace(1, 10**max_lum, n_colors))
    elif v_scale == "sqrt":
        J = np.sqrt(np.linspace(0, max_lum, n_colors))
    else:
        raise NotImplementedError()
    J *= 100
    J = np.maximum(1e-1, J)

    # convert to RGB
    pal = cspace_convert(list(zip(J, C, h)), "JCh", "sRGB1")

    # clip RGB values to [0, 1]
    pal = np.maximum(0, pal)
    pal = np.minimum(1, pal)

    return pal
Exemple #22
0
    def get_colors(n_colors=1, lightness=50, saturation=50, shift=0):
        """Get colors on the LCh ring

        Parameters
        ----------
        n_colors :
            param lightness: (Default value = 1)
        lightness :
             (Default value = 50)
        saturation :
             (Default value = 50)
        shift :
             (Default value = 0)

        Returns
        -------

        """
        hues = np.linspace(0, 360, n_colors + 1)[:-1] + shift
        return (np.clip(
            colorspacious.cspace_convert(
                np.stack(
                    [
                        np.ones_like(hues) * lightness,
                        np.ones_like(hues) * saturation,
                        hues,
                    ],
                    1,
                ),
                "CIELCh",
                "sRGB1",
            ),
            0,
            1,
        ) * 255)
Exemple #23
0
    def maximize_triangle_radius(self, cut_off = 0.01, radius_min = 0.0,
                            radius_max = 256.0, verbose=False):

        angles = self.angle_0 + np.array([0,120,240])
        a_unit_vec = np.cos(np.pi/180*angles)
        b_unit_vec = np.sin(np.pi/180*angles)

        lab_sequence = np.zeros((3,3))
        lab_sequence[:,0] = self.L_plane
        while (radius_max - radius_min) > cut_off:
            radius = 0.5*(radius_max + radius_min)

            lab_sequence[:,1] = radius*a_unit_vec + self.center[0]
            lab_sequence[:,2] = radius*b_unit_vec + self.center[1]
            sRGB1_sequence = cspace_convert(lab_sequence, self.color_space, "sRGB1")

            if np.any(sRGB1_sequence>1.0) or np.any(sRGB1_sequence<0.0):
                radius_is_safe = False
                if verbose:print (radius_min, radius, radius_max, radius_is_safe)
                radius_max = radius

            else:
                radius_is_safe = True
                if verbose:print (radius_min, radius, radius_max, radius_is_safe)
                radius_min = radius

        if radius_is_safe==False:
            radius = radius_min

        self.radius = radius
        return radius
Exemple #24
0
def generate_palette(colors, size, base=None, no_black=False):
    # Initialize palette with given base or white color
    if base:
        palette = [colors[i, :] for i in base]
    else:
        palette = [colors[-1, :]]  # white
    # Exclude colors that are close to black
    if no_black:
        MIN_DISTANCE_TO_BLACK = 35
        d = np.linalg.norm((colors - colors[0, :]), axis=1)
        colors = colors[d > MIN_DISTANCE_TO_BLACK, :]
    # Initialize distances array
    num_colors = colors.shape[0]
    distances = np.ones(shape=(num_colors, 1)) * 1000

    # A function to recompute minimum distances from palette to all colors
    def update_distances(colors, color):
        d = np.linalg.norm((colors - color), axis=1)
        np.minimum(distances, d.reshape(distances.shape), distances)

    # Build progress bar
    widgets = ['Generating palette: ', Percentage(), ' ', Bar(), ' ', ETA()]
    pbar = ProgressBar(widgets=widgets, maxval=size).start()
    # Update distances for the colors that are already in the palette
    for i in range(len(palette) - 1):
        update_distances(colors, palette[i])
        pbar.update(i)
    # Iteratively build palette
    while len(palette) < size:
        update_distances(colors, palette[-1])
        palette.append(colors[np.argmax(distances), :])
        pbar.update(len(palette))
    pbar.finish()
    return cspace_convert(palette, 'CAM02-UCS', 'sRGB1')
Exemple #25
0
 def hex_colors(start, amount, saturation, luminosity):
     k = 360/amount
     ans = ((luminosity, saturation, start + i*k) for i in range(amount))
     ans = (cspace_convert(color, cie_string, "sRGB1") for color in ans)
     ans = (color.tolist() for color in ans)
     ans = (sRGBColor(*color) for color in ans)
     return to_hex_rgb(ans)
Exemple #26
0
def convert(data, from_space, to_space):
    '''
    Takes a single color value or matrix of values and converts to the
    desired colorspace

    Parameters
    -----------
    data: 3 x COL array
        Colormap name OR array with complete color data. Invalid
        colormap names throw a ValueError. Refer to _check_cmap for
        more information.
    from_space: str
        Colorspace the current color value(s) reside(s) in
    to_space: str
        Colorspace to convert the color value(s) to

    Returns
    -----------
    n : 3 x COL ndarray
        RGB values for each converted color value
    '''
    if from_space == CSPACE1:
        data = np.clip(data, 0, 1)
    new = cspace_convert(data.T, from_space, to_space).T
    if to_space == CSPACE1:
        new = np.clip(new, 0, 1)
    return new
def get_orientation_map(image, filts):
    """Convolves 4 quadrature filters over an image and returns the image orientation.
    Converts to greyscale first.

    Inputs: image - (224,224,3)
            filts -

    Outputs: angle (between 0 and 1) - remember to rescale later
    intensity = (between 0 and 1) - 0 represents no angle energy

    """

    perceptually_uniform = cspace_convert(image, "sRGB1", "JCh")
    lightness_image = perceptually_uniform[:, :, 0]

    magnitudes = []
    for filt in filts:
        sin_conv = convolve2d(lightness_image, filt[1], mode='same')
        cos_conv = convolve2d(lightness_image, filt[0], mode='same')

        magnitudes.append(np.sqrt(sin_conv ** 2 + cos_conv ** 2))

    orientation_vec = [magnitudes[0] - magnitudes[2],
                       magnitudes[1] - magnitudes[3]]
    angle = np.arctan2(magnitudes[0] - magnitudes[2],
                       magnitudes[1] - magnitudes[3])

    rescaled_angle = angle / (np.pi * 2) + 0.5

    intensity = np.sqrt(orientation_vec[0] ** 2 +
                        orientation_vec[1] ** 2) / \
                np.max(np.sqrt(orientation_vec[0] ** 2 +
                               orientation_vec[1] ** 2))

    return rescaled_angle, intensity
Exemple #28
0
    def generate_palette(self, size):
        """
        Return palette in sRGB1 format.

        If the palette isn't long enough, new entries are generated.
        """
        if size <= len(self.palette):
            return cspace_convert(self.palette[0:size], "CAM02-UCS", "sRGB1")

        # Initialize distances array
        num_colors = self.colors.shape[0]
        distances = np.ones(shape=(num_colors, 1)) * 1000

        # A function to recompute minimum distances from palette to all colors
        def update_distances(colors, color):
            d = np.linalg.norm((colors - color), axis=1)
            np.minimum(distances, d.reshape(distances.shape), distances)

        # Build progress bar
        widgets = [
            "Generating palette: ",
            Percentage(), " ",
            Bar(), " ",
            ETA()
        ]
        pbar = ProgressBar(widgets=widgets, maxval=size).start()
        # Update distances for the colors that are already in the palette
        for i in range(len(self.palette) - 1):
            update_distances(self.colors, self.palette[i])
            pbar.update(i)
        # Iteratively build palette
        while len(self.palette) < size:
            update_distances(self.colors, self.palette[-1])
            self.palette.append(self.colors[np.argmax(distances), :])
            pbar.update(len(self.palette))
        pbar.finish()

        assert self.check_validity_internal_palette(
        ), "Internal error during extend_palette: self.palette is poorly formatted."

        if self.overwrite_base_palette:
            self.save_palette(palette=self.palette,
                              path=self.base_palette,
                              format="byte",
                              overwrite=True)

        return cspace_convert(self.palette[0:size], "CAM02-UCS", "sRGB1")
Exemple #29
0
def max_chroma_colormap(z, nancolor='gray'):
    """
    Map complex value to color, with maximum chroma at each lightness

    Magnitude is represented by lightness and angle is represented by hue.
    The interval [0, ∞] is mapped to lightness [0, 100].

    Parameters
    ----------
    z : array_like
        Complex numbers to be mapped.
    nancolor
        Color used to represent NaNs.  Can be any valid matplotlib color,
        such as ``'k'``, ``'deeppink'``, ``'0.5'`` [gray],
        ``(1.0, 0.5, 0.0)`` [orange], etc.

    Returns
    -------
    rgb : ndarray
        Array of colors, with values varying from 0 to 1.  Shape is same as
        input, but with an extra dimension for R, G, and B.

    Examples
    --------
    A point with infinite magnitude will map to white, and magnitude 0 will
    map to black.  A point with magnitude 10 and phase of π/2 will map to a
    saturated yellow.  NaNs will map to gray by default:

    >>> max_chroma_colormap([[np.inf, 0, 10j, np.nan]])
    array([[[ 1.   ,  1.   ,  1.   ],
            [ 0.051,  0.   ,  0.001],
            [ 0.863,  0.694,  0.   ],
            [ 0.502,  0.502,  0.502]]])
    """
    # Map magnitude in [0, ∞] to J in [0, 100]
    J = (1.0 - (1 / (1.0 + np.abs(z)**0.3))) * 100

    # Map angle in [0, 2π) to hue h in [0, 360)
    h = np.angle(z, deg=True)

    # TODO: Don't interpolate NaNs and get warnings

    # 2D interpolation of C lookup table
    C = max_interpolator(J, h, grid=False)

    # So if z is (vertical, horizontal), then
    # imshow expects shape of (vertical, horizontal, 3)
    JCh = np.stack((J, C, h), axis=-1)

    # TODO: Don't convert NaNs and get warnings
    rgb = cspace_convert(JCh, new_space, "sRGB1")

    # White for infinity (colorspacious doesn't quite reach it for J = 100)
    rgb[np.isinf(z)] = (1.0, 1.0, 1.0)

    # Color NaNs
    rgb[np.isnan(z)] = to_rgb(nancolor)

    return rgb.clip(0, 1)
Exemple #30
0
def jmh_mixer_2(*colors):
    n = len(colors)
    ans = (hex_to_rgb(color) for color in colors)
    ans = (cspace_convert(color, "sRGB255", "JMh") for color in ans)
    ans = (color.tolist() for color in ans)
    ans = zip(*ans)
    ans = (sum(items)/n for items in ans)
    return list(ans)
Exemple #31
0
def colorblind(pal, typ):
    input_space = {
        'name': 'sRGB1+CVD',
        'cvd_type': typ,
        'severity': 100,
    }
    return np.clip(colorspacious.cspace_convert(pal, input_space, 'sRGB1'), 0,
                   1)
Exemple #32
0
def sRGB_gamut_Jp_slice(Jp, uniform_space, ap_lim=(-50, 50), bp_lim=(-50, 50), resolution=200):
    bp_grid, ap_grid = np.mgrid[bp_lim[0] : bp_lim[1] : resolution * 1j, ap_lim[0] : ap_lim[1] : resolution * 1j]
    Jp_grid = Jp * np.ones((resolution, resolution))
    Jpapbp = np.concatenate((Jp_grid[:, :, np.newaxis], ap_grid[:, :, np.newaxis], bp_grid[:, :, np.newaxis]), axis=2)
    sRGB = cspace_convert(Jpapbp, uniform_space, "sRGB1")
    sRGBA = np.concatenate((sRGB, np.ones(sRGB.shape[:2] + (1,))), axis=2)
    sRGBA[np.any((sRGB < 0) | (sRGB > 1), axis=-1)] = [0, 0, 0, 0]
    return sRGBA
Exemple #33
0
def convert_to_jab(df, from_cm='sRGB255', from_cols=['R', 'G', 'B']):
    """Converts a dataframe inplace from one color map to JCAM02-UCS
        Will delete originating columns
    """
    arr_tmp = cspace_convert(df[from_cols], from_cm, 'CAM02-UCS')
    df[['J', 'a', 'b']] = pd.DataFrame(arr_tmp, index=df.index)

    df.drop(columns=from_cols, inplace=True)
    return df
Exemple #34
0
def get_rainbow(Cp, Jp, count):
    # Adapted from the demo in https://youtu.be/xAoljeRJ3lU?t=14m40s
    # Nathaniel Smith and Stéfan van der Walt
    # “A Better Default Colormap for Matplotlib”
    # SciPy 2015 Conference
    hp = np.linspace(0.0, 360.0, count)
    JpCphp = np.column_stack([np.full(hp.shape, Jp), np.full(hp.shape, Cp), hp])
    with np.errstate(divide="ignore", invalid="ignore"):
        rgb = colorspacious.cspace_convert(JpCphp, "JCh", "sRGB255")
    clipped_rgb = np.clip(rgb, 0.0, 255.0)
    return np.ma.masked_array(clipped_rgb, clipped_rgb - rgb)
Exemple #35
0
def get_rainbow(Cp, Jp, count):
    # Adapted from the demo in https://youtu.be/xAoljeRJ3lU?t=14m40s
    # Nathaniel Smith and Stéfan van der Walt
    # “A Better Default Colormap for Matplotlib”
    # SciPy 2015 Conference
    t = (np.linspace(0.0, 1.0, count)) * 2.0 * np.pi
    ap = Cp * np.cos(t)
    bp = Cp * np.sin(t)
    Jpapbp = np.column_stack([np.full(ap.shape, Jp), ap, bp])
    with np.errstate(divide="ignore", invalid="ignore"):
        rgb = colorspacious.cspace_convert(Jpapbp, "CAM02-UCS", "sRGB255")
    clipped_rgb = np.clip(rgb, 0.0, 255.0)
    return np.ma.masked_array(clipped_rgb, clipped_rgb - rgb)
def perceptual(image):
    """
    Convert color from RGB (sRGB1) to a perceptually uniform colorspace.

    This is a convenience function wrapping ``colorspacious.csapce_convert``.
    To configure the specific perceptual colorspace used, change
    ``photomosaic.options['colorspace']``.

    Parameters
    ----------
    image : array
    """
    return colorspacious.cspace_convert(image, options["rgb"], options["perceptual"])
Exemple #37
0
def sRGB_gamut_patch(uniform_space, resolution=20):
    step = 1.0 / resolution
    sRGB_quads = []
    sRGB_values = []
    # each entry in 'quads' is a 4x3 array where each row contains the
    # coordinates of a corner point
    for fixed in 0, 1:
        for i in range(resolution):
            for j in range(resolution):
                # R quad
                sRGB_quads.append(
                    [
                        [fixed, i * step, j * step],
                        [fixed, (i + 1) * step, j * step],
                        [fixed, (i + 1) * step, (j + 1) * step],
                        [fixed, i * step, (j + 1) * step],
                    ]
                )
                sRGB_values.append((fixed, (i + 0.5) * step, (j + 0.5) * step, 1))
                # G quad
                sRGB_quads.append(
                    [
                        [i * step, fixed, j * step],
                        [(i + 1) * step, fixed, j * step],
                        [(i + 1) * step, fixed, (j + 1) * step],
                        [i * step, fixed, (j + 1) * step],
                    ]
                )
                sRGB_values.append(((i + 0.5) * step, fixed, (j + 0.5) * step, 1))
                # B quad
                sRGB_quads.append(
                    [
                        [i * step, j * step, fixed],
                        [(i + 1) * step, j * step, fixed],
                        [(i + 1) * step, (j + 1) * step, fixed],
                        [i * step, (j + 1) * step, fixed],
                    ]
                )
                sRGB_values.append(((i + 0.5) * step, (j + 0.5) * step, fixed, 1))
    sRGB_quads = np.asarray(sRGB_quads)
    # work around colorspace transform bugginess in handling high-dim
    # arrays
    sRGB_quads_2d = sRGB_quads.reshape((-1, 3))
    Jpapbp_quads_2d = cspace_convert(sRGB_quads_2d, "sRGB1", uniform_space)
    Jpapbp_quads = Jpapbp_quads_2d.reshape((-1, 4, 3))
    gamut_patch = mpl_toolkits.mplot3d.art3d.Poly3DCollection(Jpapbp_quads[:, :, [1, 2, 0]])
    gamut_patch.set_facecolor(sRGB_values)
    gamut_patch.set_edgecolor(sRGB_values)
    return gamut_patch
def rgb(image, clip=True):
    """
    Convert color from a perceptually uniform colorspace to RGB.

    This is a convenience function wrapping ``colorspacious.csapce_convert``.
    To configure the specific perceptual colorspace used, change
    ``photomosaic.options['perceptual']`` and ``photomosaic.options['rgb']``.

    Parameters
    ----------
    image : array
    clip : bool, option
        Clip values out of the gamut [0, 1]. True by default.
    """
    result = colorspacious.cspace_convert(image, options["perceptual"], options["rgb"])
    if clip:
        result = np.clip(result, 0, 1)
    return result
Exemple #39
0
    def analyze(filename):
        try:
            raw_image = imread(filename, **options["imread"])
        except Exception as err:
            if skip_read_failures:
                warnings.warn("Skipping {}; raised exception:\n    {}" "".format(filename, err))
                return
            raise
        image = standardize_image(raw_image)
        # Subsample before doing expensive color space conversion.
        if sample_size is not None:
            sample = sample_pixels(image, sample_size)
        else:
            sample = image.reshape(-1, 3)  # list of pixels
        # Convert color to perceptually-uniform color space.
        converted_sample = colorspacious.cspace_convert(sample, options["rgb"], options["perceptual"])

        vector = analyzer(converted_sample)
        return vector
def fun_simulate_cvd_Machado(img_rgb, type_cvd = "p", severity_factor = 100):
    """The function use the code from the module colorspacious where the Method
    from Machado had been implemented
    """

    if type_cvd == "p":
        cvd_space = {"name": "sRGB1+CVD",
                             "cvd_type": "protanomaly",
                             "severity": severity_factor}
    if type_cvd == "d":
        cvd_space = {"name": "sRGB1+CVD",
                             "cvd_type": "deuteranomaly",
                             "severity": severity_factor}
    if type_cvd == "t":
        cvd_space = {"name": "sRGB1+CVD",
                             "cvd_type": "tritanomaly",
                             "severity": severity_factor}

    img_cvd_sRGB = cs.cspace_convert(img_rgb, cvd_space, "sRGB1")
    img_cvd_sRGB = np.clip(img_cvd_sRGB,0, 255)
    img_cvd_sRGB = img_cvd_sRGB.astype("uint8")
    return img_cvd_sRGB
Exemple #41
0
def generate_palette(
    colors,
    size,
    base=None,
    no_black=False,
    lightness_range=None,
    chroma_range=None,
    hue_range=None,
):
    # Initialize palette with given base or white color
    if base:
        palette = [colors[i, :] for i in base]
    else:
        palette = [colors[-1, :]]  # white
    # Exclude greys (values with low Chroma in JCh) and set lightness range,
    if lightness_range is not None:
        jch = cspace_convert(colors, "CAM02-UCS", "JCh")
        colors = colors[
            (jch[:, 0] >= lightness_range[0]) & (jch[:, 0] <= lightness_range[1]), :
        ]
    if chroma_range is not None:
        jch = cspace_convert(colors, "CAM02-UCS", "JCh")
        colors = colors[
            (jch[:, 1] >= chroma_range[0]) & (jch[:, 1] <= chroma_range[1]), :
        ]
    if hue_range is not None:
        jch = cspace_convert(colors, "CAM02-UCS", "JCh")
        if hue_range[0] > hue_range[1]:
            colors = colors[
                (jch[:, 2] >= hue_range[0]) | (jch[:, 2] <= hue_range[1]), :
            ]
        else:
            colors = colors[
                (jch[:, 2] >= hue_range[0]) & (jch[:, 2] <= hue_range[1]), :
            ]
    # Exclude colors that are close to black
    if no_black:
        MIN_DISTANCE_TO_BLACK = 35
        d = np.linalg.norm((colors - colors[0, :]), axis=1)
        colors = colors[d > MIN_DISTANCE_TO_BLACK, :]
    # Initialize distances array
    num_colors = colors.shape[0]
    distances = np.ones(shape=(num_colors, 1)) * 1000
    # A function to recompute minimum distances from palette to all colors
    def update_distances(colors, color):
        d = np.linalg.norm((colors - color), axis=1)
        np.minimum(distances, d.reshape(distances.shape), distances)

    # Build progress bar
    widgets = ["Generating palette: ", Percentage(), " ", Bar(), " ", ETA()]
    pbar = ProgressBar(widgets=widgets, maxval=size).start()
    # Update distances for the colors that are already in the palette
    for i in range(len(palette) - 1):
        update_distances(colors, palette[i])
        pbar.update(i)
    # Iteratively build palette
    while len(palette) < size:
        update_distances(colors, palette[-1])
        palette.append(colors[np.argmax(distances), :])
        pbar.update(len(palette))
    pbar.finish()
    return cspace_convert(palette, "CAM02-UCS", "sRGB1")
Exemple #42
0
# This creates a circular, perceptually uniform colormap
# The code was stolen from the matplotlib/numpy/scipy 
# presentation (matplotlib 2.0 presentation)


# Number of points
N = 256

# Constant lightness
Jp = 75*np.ones(N)

# Constant saturation, varying hue
radius = 30
theta  = np.linspace(0, 2*np.pi, N)
ap     = radius*np.sin(theta)
bp     = radius*np.cos(theta)

Jpapbp = np.column_stack((Jp, ap, bp))

from colorspacious import cspace_convert
rgb = cspace_convert(Jpapbp, "CAM02-UCS", "sRGB1")


# Matplotlib defaults to rgba, not rgb. 
# Reset the transparency values now.
col_list[:,3] = 1.

circular_map = mplc.ListedColormap(col_list, 'circular_map', 256)
plt.register_cmap(cmap=circular_map)
## ------