def score_discrete_colourmap(colourmap):
    """How good does a discrete colourmap look?

    A lower score indicates a better colourmap.
    """
    # Add up all the distances.
    regular_vision_score = 0
    colourmap_ = colourmap
    colourmap = numpy.clip(colourmap, 0, 1)
    for colour_a in colourmap:
        for colour_b in colourmap:
            dE = colorspacious.deltaE(colour_a, colour_b, input_space='sRGB1')
            if dE == 0:
                continue
            regular_vision_score -= numpy.log(dE)

    deuteranomaly_score = 0
    deuteranomalous_colourmap = colourblind_colourmap(colourmap)
    for colour_a in deuteranomalous_colourmap:
        for colour_b in deuteranomalous_colourmap:
            dE = colorspacious.deltaE(colour_a, colour_b, input_space='sRGB1')
            if dE == 0:
                continue
            deuteranomaly_score -= numpy.log(dE)

    greyscale_score = 0
    grey_colourmap = greyscale_colourmap(colourmap)
    for colour_a in grey_colourmap:
        for colour_b in grey_colourmap:
            dE = colorspacious.deltaE(colour_a, colour_b, input_space='sRGB1')
            if dE == 0:
                continue
            greyscale_score -= numpy.log(dE)

    # Is anything white?
    white_score = 0
    for colour in grey_colourmap:
        dE = colorspacious.deltaE(colour, (1, 1, 1), input_space='sRGB1')
        white_score += numpy.exp(15 - dE)

    # # Is anything out of range?
    # range_score = 0
    # for colour in colourmap_:
    #     for i in colour:
    #         range_score += scipy.special.expit((i - 1) / 100)
    #         range_score += 1 - scipy.special.expit(i / 100)

    return {
        'grey': greyscale_score,
        'deuteranomaly': deuteranomaly_score,
        'regular': regular_vision_score,
        'white': white_score,
        # 'range': range_score,
    }
Exemple #2
0
def _colour_distance(colour_1,
                     colour_2,
                     input_space='sRGB1',
                     uniform_space='CAM02-UCS'):
    distances = [
        deltaE(c1, c2, input_space, uniform_space)
        for c1, c2 in zip(colour_1, colour_2)
    ]
    return np.array(distances)
Exemple #3
0
def deltaE(ctab, src='sRGB1', uniform_space='CAM02-UCS'):
    """Compute color difference deltaE"""
    if missing:
        raise ImportError(missing)
    return [
        cs.deltaE(ctab[i, :3],
                  ctab[i + 1, :3],
                  input_space=src,
                  uniform_space=uniform_space) for i in range(len(ctab) - 1)
    ]
Exemple #4
0
    def __sub__(self, other):
        """Compute the ``DeltaE`` distance between two colors.

        This corresponds to a euclidean distance in the perceptual **CAM02-UCS** space, in which perceptually similar
        colors (*i.e.* "close" colors) have similar coordinates.

        Args:
            other (|Color|): The |Color| to compute the distance index with.

        Returns:
            float: The distance between the two colors.

        """
        if hasattr(other, 'components') and hasattr(
                other, 'astype') and hasattr(other, 'ctype'):
            return deltaE(self.astype('XYZ100').components,
                          other.astype('XYZ100').components,
                          input_space='XYZ100')
        else:
            return NotImplemented
Exemple #5
0
def get_pixel_lines(stk_time,
                    stk,
                    Idx,
                    resample_rule="100L",
                    pxmtc="lightness"):
    """
    Extract pixel timeseries from a given timestack at the locations obtained
    from get_analysis_locations().

    ----------
    Args:
        stk_time (Mandatory [np.array]): array of datetimes.

        stk (Mandatory [np.array]): [time,space,3] timestack array.

        Idx (Mandatory [np.array]): cross-shore indexes obtained from
        get_analysis_locations()

        resample_rule (Optional [str]): Resample frequency. Default is "100L"

        pxmtc (Optional [str]): Pixel metric to use. Default is "lightness"

    ----------
    Returns:
        time (Mandatory [np.array]): Array of datetimes

        dEk (Mandatory [np.array]): [time,Idx] pixel metric array

        RGB (Mandatory [np.array]): [time,Idx,3] colour array
    """

    # case 3D
    if len(stk.shape) == 3:
        RGB = []
        pxint = []
        for idx in Idx:
            # pixel line at exact location
            pxline = stk[:, idx, :]
            # build a dataframe
            df = pd.DataFrame(pxline,
                              columns=["red", "green", "blue"],
                              index=stk_time)
            # add grey values
            df["grey"] = pxline.mean(axis=1).astype(np.int)
            # adjust records in time upsampling to 8Hz
            df = df.resample(resample_rule).backfill()
            # df = smoothpixelseries(df, window=5, order=2)
            # compute color parameters
            if pxmtc == "lightness":
                # get rgb values
                rgb = df[["red", "green", "blue"]].values.astype(np.int)
                # exclude invalid values from interpolation
                rgb[rgb < 0] = 0
                # lightness
                pxint.append(
                    deltaE(rgb, [0, 0, 0], input_space="sRGB255") / 100)
                RGB.append(rgb)
            elif pxmtc == "intensity":
                # get rgb values
                rgb = df[["red", "green", "blue"]].values.astype(np.int)
                # exclude invalid values from interpolation
                rgb[rgb < 0] = 0
                # intensity
                pxint.append(np.mean(rgb))
                RGB.append(rgb)
            else:
                raise NotImplementedError(
                    "Colour metric {} is not valid.".format(pxmtc))
    # case 2D:
    elif len(stk.shape) == 2:
        RGB = []
        pxint = []
        for idx in Idx:
            # pixel line at exact location
            pxline = stk[:, idx]
            # build a dataframe
            df = pd.DataFrame(pxline, columns=["grey"], index=stk_time)
            # adjust records in time upsampling if needed
            df = df.resample(resample_rule).backfill()
            # compute color parameters
            pxint.append(pxline)
            RGB.append([pxline, pxline, pxline])
    else:
        raise ValueError("Image needs to be 2D or 3D.")

    # get times
    time = pd.to_datetime(df.index.values).to_pydatetime()

    return time, pxint, RGB
colors_list_one = list(unique_everseen(colors_list_one))

# Do the same things for input file two:
f = open(hexpltFileNameTwoPassedToScript, "r")
colors_list_two = list(f.read().splitlines())
f.close()
colors_list_two = [element[1:] for element in colors_list_two]
colors_list_two = list(unique_everseen(colors_list_two))

if (len(colors_list_one) != len(colors_list_two)):
    print('\nProblem: palette one and two are of different lengths (they have different numbers of colors). They must have the same number of colors for this to work. (This can also happen if there are duplicate elements in a list but it has the same number of elements as the other list to begin with, because this script eliminates duplicate colors before comparison.) Exiting script.')
    sys.exit(3)

DeltaEs = []
for IDX, element in enumerate(colors_list_one):
    CIECAM02_comp_one, SPACE = hex_to_CIECAM02_JCh(colors_list_one[IDX])
    CIECAM02_comp_two, SPACE = hex_to_CIECAM02_JCh(colors_list_two[IDX])
    distance = deltaE(CIECAM02_comp_one, CIECAM02_comp_two, input_space = SPACE)
    # DeltaEs.append([distance, colors_list_one[IDX], colors_list_two[IDX]])
    DeltaEs.append(distance)

# To understand the following math, know this: a _lower_ delta value (toward zero) indicates that the colors are perceptually nearer together. A _higher_ delta value (toward 100) indicates that the colors are perceputally further apart.
sumOfDeltaEs = 0
for deltaE in DeltaEs:
    # sumOfDeltaEs += deltaE[0]
    sumOfDeltaEs += deltaE

# paletteDeltaE = sumOfDeltaEs / len(colors_list_one)
paletteDeltaE = (sumOfDeltaEs / len(colors_list_one)) / 100

print(paletteDeltaE)
Exemple #7
0
def colordiff_3d(image, colorspace):
    """
    Compute the deltaE between an image and that image translated from a
    colorspace
    """
    return deltaE(image, colorspace.convert(image))
# SORT HEX RGB color list to next nearest per color,
# by converting to CIECAM02, then sorting on some dimensions in that space.

# get a list of lists of all possible color two-combinations, with an deltaE (distance measurement between the colors) as a value in the lists:
pair_deltaEs_darks = []
pair_deltaEs_lights = []

white_comp, DISCARD = hex_to_CIECAM02_JCh('FFFFFF')
black_comp, DISCARD = hex_to_CIECAM02_JCh('000000')

print('Input file is ', inputFile)
print('Getting deltaE for all colors vs. black and white . . .')

for i in range(len(colors_list)):
    CIECAM02_comp, SPACE = hex_to_CIECAM02_JCh(colors_list[i])
    distance_white_comp = deltaE(CIECAM02_comp, white_comp, input_space = SPACE)
    distance_black_comp = deltaE(CIECAM02_comp, black_comp, input_space = SPACE)
    if distance_white_comp < distance_black_comp:       # lower delta means _closer_
        pair_deltaEs_lights.append(colors_list[i])
        # print('is less than! distance_white_comp', distance_white_comp, 'distance_black_comp', distance_black_comp)
    else:
        pair_deltaEs_darks.append(colors_list[i])
        # print('is greater than! distance_white_comp', distance_white_comp, 'distance_black_comp', distance_black_comp)
    # There used to be a case for equal here, adding to the lights list, but it would never execute; if the case handling darks fails, it will add to the lights. So this case was deleted.

# dump to lists and report dump
print('Writing to darks list . . .')
with open('darks.hexplt', 'w') as f:
    for element in pair_deltaEs_darks:
        print_element = '#' + element + '\n'
        f.write(print_element)