def test_cmc_accuracy(self): # Test 2:1 result = delta_e_cmc(self.color1, self.color2, pl=2, pc=1) expected = 1.443 self.assertAlmostEqual( result, expected, 3, "DeltaE CMC (2:1) formula error. Got %.3f, expected %.3f (diff: %.3f)." % (result, expected, result - expected)) # Test against 1:1 as well result = delta_e_cmc(self.color1, self.color2, pl=1, pc=1) expected = 1.482 self.assertAlmostEqual( result, expected, 3, "DeltaE CMC (1:1) formula error. Got %.3f, expected %.3f (diff: %.3f)." % (result, expected, result - expected)) # Testing atan H behavior. atan_color1 = LabColor(lab_l=69.417, lab_a=-12.612, lab_b=-11.271) atan_color2 = LabColor(lab_l=83.386, lab_a=39.426, lab_b=-17.525) result = delta_e_cmc(atan_color1, atan_color2) expected = 44.346 self.assertAlmostEqual( result, expected, 3, "DeltaE CMC Atan test formula error. Got %.3f, expected %.3f (diff: %.3f)." % (result, expected, result - expected))
def test_cmc_negative_square_root(self): """ Tests against a case where a negative square root in the delta_H calculation could happen. """ standard = LabColor(lab_l=0.9, lab_a=1, lab_b=1) sample = LabColor(lab_l=0.7, lab_a=0, lab_b=0) delta_e_cmc(standard, sample)
def __init__(self, palette: str="palette.bin", distinguishing: float=5.0): """ Constructor. :param palette: :param distinguishing: """ self.distinguish = distinguishing self.colorList = [] self.labColorList = [] self.lBound, self.uBound = 0.0, 0.0 persistence = shelve.open(palette) _colorList = persistence['data'] for colorTuple in _colorList: color = sRGBColor(colorTuple[0], colorTuple[1], colorTuple[2]) self.colorList.append(color) self.labColorList.append(convert_color(color, LabColor)) persistence.close() self.colorsCount = len(self.colorList) for i in range(self.colorsCount): for j in range(i, self.colorsCount): distance = delta_e_cmc(self.labColorList[i], self.labColorList[j]) self.lBound = min(self.lBound, distance) self.uBound = max(self.uBound, distance)
def delta_e(self, other_color, mode='cie2000', *args, **kwargs): """ Compares this color to another via Delta E. Valid modes: cie2000 cie1976 """ if not isinstance(other_color, ColorBase): raise InvalidArgument('delta_e_cie2000', 'other_color', other_color) # Convert the colors to Lab if they are not already. lab1 = self.convert_to('lab', *args, **kwargs) lab2 = other_color.convert_to('lab', *args, **kwargs) mode = mode.lower() if mode == 'cie2000': return color_diff.delta_e_cie2000(lab1, lab2) elif mode == 'cie1994': return color_diff.delta_e_cie1994(lab1, lab2, **kwargs) elif mode == 'cie1976': return color_diff.delta_e_cie1976(lab1, lab2) elif mode == 'cmc': return color_diff.delta_e_cmc(lab1, lab2, **kwargs) else: raise InvalidDeltaEMode(mode)
def colorPicker(colors, n=100): ''' picks a color that is most different from the colors given in 'colors' does so by generating random colors and using a distance function to choose the one that has the largest minimum distances, i.e. that is most distiguishable from the colors in 'colors' :param colors: an array of Lab color objects from the colormath module :param n: the number of random colors to generate and choose from :return: the color that was most different (had the maximum minium-distance to any other color in 'colors' ''' dcolors = defaultColors() if len(colors) < len(dcolors): pickAColor=dcolors else: pickAColor = Nrandomcolors(n) mindistances = [] #check the distances of the random generated colors to the provided colors. # we are interested in the next color which is farthest away from its closest color that you already have # so we look at the distances from each new color to all provided colors and we keep the miniumn # then we keep the color that provides the maximum minium distance... #print randcolors for newcolor in pickAColor: distances = [] for havecolor in colors: distances.append(delta_e_cmc(newcolor,havecolor)) mindistances.append(np.min(distances)) return (np.array(pickAColor)[mindistances == np.max(mindistances)][0])
def delta_e(self, other_color, mode='cie2000', *args, **kwargs): """ Compares this color to another via Delta E. Valid modes: cie2000 cie1976 """ if not isinstance(other_color, ColorBase): raise InvalidArgument('delta_e_cie2000', 'other_color', other_color) # Convert the colors to Lab if they are not already. lab1 = self.convert_to('lab', *args, **kwargs) lab2 = other_color.convert_to('lab', *args, **kwargs) mode = mode.lower() if mode == 'cie2000': return delta_e_cie2000(lab1, lab2) elif mode == 'cie1994': return delta_e_cie1994(lab1, lab2, **kwargs) elif mode == 'cie1976': return delta_e_cie1976(lab1, lab2) elif mode == 'cmc': return delta_e_cmc(lab1, lab2, **kwargs) else: raise InvalidDeltaEMode(mode)
def distance(c1, c2): """ Calculate the visual distance between the two colors. """ return delta_e_cmc( convert_color(sRGBColor(*c1, is_upscaled=True), LabColor), convert_color(sRGBColor(*c2, is_upscaled=True), LabColor))
def distance(c1, c2): """ Calculate the visual distance between the two colors. """ return delta_e_cmc( convert_color(sRGBColor(*c1, is_upscaled=True), LabColor), convert_color(sRGBColor(*c2, is_upscaled=True), LabColor) )
def __init__(self, data = None, color1 = None, color2 = None): self.color1, self.color2 = color1, color2 if data is None or color1 == color2: self.__data = [0 for _ in xrange(0, 64)] return assert len(data) == 64 self.__data = [] lab1 = convert_color(sRGBColor(*color1[1], is_upscaled = True), LabColor) lab2 = convert_color(sRGBColor(*color2[1], is_upscaled = True), LabColor) for rgb in data: rgb = sRGBColor(*rgb, is_upscaled = True) lab = convert_color(rgb, LabColor) d1 = delta_e_cmc(lab, lab1, 1, 1) d2 = delta_e_cmc(lab, lab2, 1, 1) self.__data.append(d1 / (d1 + d2)) assert len(self.__data) == 64
def DeltaCalculator(CIE, LabCH, delta): lab_reference = LabColor(lab_l=CIE[0], lab_a=CIE[1], lab_b=CIE[2]) lab = LabColor(lab_l=LabCH[0], lab_a=LabCH[1], lab_b=LabCH[2]) if delta == 'delta_e_cie1976': return delta_e_cie1976(lab, lab_reference) elif delta == 'delta_e_cie1994': return delta_e_cie1994(lab, lab_reference) elif delta == 'delta_e_cie2000': return delta_e_cie2000(lab, lab_reference) else: return delta_e_cmc(lab, lab_reference)
def test_cmc_accuracy(self): # Test 2:1 result = delta_e_cmc(self.color1, self.color2, pl=2, pc=1) expected = 1.443 self.assertAlmostEqual(result, expected, 3, "DeltaE CMC (2:1) formula error. Got %.3f, expected %.3f (diff: %.3f)." % ( result, expected, result - expected)) # Test against 1:1 as well result = delta_e_cmc(self.color1, self.color2, pl=1, pc=1) expected = 1.482 self.assertAlmostEqual(result, expected, 3, "DeltaE CMC (1:1) formula error. Got %.3f, expected %.3f (diff: %.3f)." % ( result, expected, result - expected)) # Testing atan H behavior. atan_color1 = LabColor(lab_l=69.417, lab_a=-12.612, lab_b=-11.271) atan_color2 = LabColor(lab_l=83.386, lab_a=39.426, lab_b=-17.525) result = delta_e_cmc(atan_color1, atan_color2) expected = 44.346 self.assertAlmostEqual(result, expected, 3, "DeltaE CMC Atan test formula error. Got %.3f, expected %.3f (diff: %.3f)." % ( result, expected, result - expected))
def compare_similar_hist(rgb_1, rgb_2): # print("rgb1",rgb_1) # print("rgb2",rgb_2) lab_l,lab_a,lab_b=RGB2Lab(rgb_1) color1 = LabColor(lab_l, lab_a, lab_b) # color1 = LabColor(lab_l=0.9, lab_a=16.3, lab_b=-2.22) print("lab",lab_l,lab_a,lab_b) lab_l,lab_a,lab_b=RGB2Lab(rgb_2) color2 = LabColor(lab_l, lab_a, lab_b) print("lab",lab_l,lab_a,lab_b) # delta_e = delta_e_cie2000(color1, color2) delta_e = delta_e_cmc(color1, color2) return delta_e
def getColor(self, rgb): rgb = sRGBColor(*rgb, is_upscaled = True) src = convert_color(rgb, LabColor) match_color = None match_delta = None match_index = None index = 0 for dst_rgb, dst in self.__colors: d = delta_e_cmc(src, dst, 1, 1) if (match_color is None) or (d < match_delta): match_index = index match_color = dst_rgb match_delta = d index += 1 return match_index, match_color.get_upscaled_value_tuple()
def get_color_distance(c1, c2, on_server): if (c1, c2) in dcache: return dcache[(c1, c2)] if (c2, c1) in dcache: return dcache[(c2, c1)] # Delta E CMC seems to be the most reliable method, # slightly more cpu expensive but not dramatically. # Other methods coupled with low permutation limit # on EV3 tend to mix Yellow/White and Orange/Red so # ignore on_server flag here and use Delta E CMC. distance = delta_e_cmc(c1, c2) dcache[(c1, c2)] = distance return distance
def scatter(self, number: int, persistence: bool=False, saveAsFile: str="colorSample.bin") -> list: """ Sample certain number of distinguished colors. :param number: :param saveAsFile: :return: """ gap = (self.uBound - self.lBound) / (2 * number) * self.distinguish sampleIndices = set() result = [] avoidLock = 0 while len(sampleIndices) < number: candidate = random.randint(0, self.colorsCount - 1) isDistinguished = True for i in sampleIndices: if delta_e_cmc(self.labColorList[i], self.labColorList[candidate]) < gap: isDistinguished = False break if isDistinguished: sampleIndices.add(candidate) avoidLock += 1 if avoidLock > self.colorsCount * 8: break for index in sampleIndices: _rgb = self.colorList[index].get_value_tuple() rgb = (int(_rgb[0]), int(_rgb[1]), int(_rgb[2])) result.append(rgb) if persistence: sample = Palette(result) sample.draw("sample-%d.png" % number) persistence = shelve.open(saveAsFile) persistence['data'] = result persistence.close() return result
def _infer_sample(self, well): # return None if the well is empty if well.color == '00000000' and well.color not in [s.color for s in self.samples]: return None # if the whole plate contains a single sample, assign that sample samples = [s for s in self.samples if s.name] if len(samples) == 1: return samples[0].name # find the sample color that's closest to the well color sample_labs = [convert_color( sRGBColor( *self.hex_to_rgb(s.color)), LabColor) for s in samples] well_lab = convert_color( sRGBColor( *self.hex_to_rgb(well.color)), LabColor) diffs = [] for slab in sample_labs: diffs.append(delta_e_cmc(well_lab, slab)) best_match = samples[diffs.index(min(diffs))] return best_match.name
def detect_door_state(self, image, open_door_contour): minX, minY, maxX, maxY = open_door_contour img = image[minY:maxY, minX:maxX] img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) average = img.mean(axis=0).mean(axis=0) average = (int(average[0]), int(average[1]), int(average[2])) avg_color = convert_color(sRGBColor(*average), LabColor) TARGET_COLORS = { DoorStates.DOOR_CLOSED: convert_color(sRGBColor(*(51, 32, 25)), LabColor), DoorStates.DOOR_OPEN: convert_color(sRGBColor(*(151, 117, 72)), LabColor) } differences = [[ delta_e_cmc(avg_color, target_value, pl=1, pc=1), target_name ] for target_name, target_value in TARGET_COLORS.items()] differences.sort() # sorted by the first element of inner lists door_state = differences[0][1] return door_state
def _infer_sample(self, well): # return None if the well is empty if well.color == '00000000' and well.color not in [ s.color for s in self.samples ]: return None # if the whole plate contains a single sample, assign that sample samples = [s for s in self.samples if s.name] if len(samples) == 1: return samples[0].name # find the sample color that's closest to the well color sample_labs = [ convert_color(sRGBColor(*self.hex_to_rgb(s.color)), LabColor) for s in samples ] well_lab = convert_color(sRGBColor(*self.hex_to_rgb(well.color)), LabColor) diffs = [] for slab in sample_labs: diffs.append(delta_e_cmc(well_lab, slab)) best_match = samples[diffs.index(min(diffs))] return best_match.name
def distance(spectrum_pnt, pnt, mode): color1 = LabColor(lab_l=spectrum_pnt[0], lab_a=spectrum_pnt[1], lab_b=spectrum_pnt[2]) color2 = LabColor(lab_l=pnt[0], lab_a=pnt[1], lab_b=pnt[2]) if mode == 'cie1976': return color_diff.delta_e_cie1976(color1, color2) elif mode == 'cie1994': return color_diff.delta_e_cie1994(color1, color2, K_L=1, K_C=1, K_H=1, K_1=0.045, K_2=0.015) elif mode == 'cie2000': return color_diff.delta_e_cie2000(color1, color2, Kl=1, Kc=1, Kh=1) elif mode == 'cmc': return color_diff.delta_e_cmc(color1, color2, pl=2, pc=1) else: return np.sqrt((spectrum_pnt[0] - pnt[0])**2 + (spectrum_pnt[1] - pnt[1])**2 + (spectrum_pnt[2] - pnt[2])**2)
def _get_closest_color_swatch(self, library: QuerySet, color_to_match: LabColor): distance_dict = dict() for item in library: possible_color = convert_color( sRGBColor.new_from_rgb_hex(item.hex_color), LabColor) distance = delta_e_cmc(color_to_match, possible_color) distance_dict.update({item: distance}) distance_dict = { i: distance_dict[i] for i in distance_dict if distance_dict[i] is not None } sorted_distance_list = sorted(distance_dict.items(), key=lambda kv: kv[1]) try: return sorted_distance_list[0][0] except IndexError: return None
hist = utils.centroid_histogram(clt) bar = utils.plot_colors(hist, clt.cluster_centers_) # set up values for known colors colors = [] colors.append((convert_color(sRGBColor(94, 153, 25), LabColor), "Green")) colors.append((convert_color(sRGBColor(138, 50, 48), LabColor), "Red")) colors.append((convert_color(sRGBColor(233, 120, 54), LabColor), "Orange")) colors.append((convert_color(sRGBColor(140, 65, 96), LabColor), "Purple")) colors.append((convert_color(sRGBColor(248, 215, 50), LabColor), "Yellow")) # find dominant color idx, _ = max(enumerate(hist), key=itemgetter(1)) color_rgb = sRGBColor(clt.cluster_centers_[idx][0], clt.cluster_centers_[idx][1], clt.cluster_centers_[idx][2]) color_lab = convert_color(color_rgb, LabColor) # calculate the color difference from known colors colordiffs = [] for color in colors: colordiffs.append(delta_e_cmc(color_lab, color[0])) # print the known color we are the closest from idx, _ = min(enumerate(colordiffs), key=itemgetter(1)) print colors[idx][1] # show our color bart plt.figure() plt.axis("off") plt.imshow(bar) plt.show()
# set up values for known colors colors = [] colors.append((convert_color(sRGBColor(94, 153, 25), LabColor), "Green")) colors.append((convert_color(sRGBColor(138, 50, 48), LabColor), "Red")) colors.append((convert_color(sRGBColor(233, 120, 54), LabColor), "Orange")) colors.append((convert_color(sRGBColor(140, 65, 96), LabColor), "Purple")) colors.append((convert_color(sRGBColor(248, 215, 50), LabColor), "Yellow")) # find dominant color idx, _ = max(enumerate(hist), key=itemgetter(1)) color_rgb = sRGBColor(clt.cluster_centers_[idx][0], clt.cluster_centers_[idx][1], clt.cluster_centers_[idx][2]) color_lab = convert_color(color_rgb, LabColor) # calculate the color difference from known colors colordiffs = [] for color in colors: colordiffs.append(delta_e_cmc(color_lab, color[0])) # print the known color we are the closest from idx, _ = min(enumerate(colordiffs), key=itemgetter(1)) print colors[idx][1] # show our color bart plt.figure() plt.axis("off") plt.imshow(bar) plt.show()
def distance(c1, c2): ''' Calculate the visual distance between the two colors. ''' rgbc1 = sRGBColor(*c1) rgbc2 = sRGBColor(*c2) return delta_e_cmc(convert_color(rgbc1, LabColor), convert_color(rgbc2, LabColor))
def DeltaECMC(self): reference = self.color1(self.lab_L, self.lab_a, self.lab_b) sample = self.color2(self.sam_L, self.sam_a, self.sam_b) return delta_e_cmc(reference, sample)
This module shows some examples of Delta E calculations of varying types. """ # Does some sys.path manipulation so we can run examples in-place. # noinspection PyUnresolvedReferences import example_config from colormath.color_objects import LabColor from colormath.color_diff import delta_e_cie1976, delta_e_cie1994, \ delta_e_cie2000, delta_e_cmc # Reference color. color1 = LabColor(lab_l=0.9, lab_a=16.3, lab_b=-2.22) # Color to be compared to the reference. color2 = LabColor(lab_l=0.7, lab_a=14.2, lab_b=-1.80) print("== Delta E Colors ==") print(" COLOR1: %s" % color1) print(" COLOR2: %s" % color2) print("== Results ==") print(" CIE1976: %.3f" % delta_e_cie1976(color1, color2)) print(" CIE1994: %.3f (Graphic Arts)" % delta_e_cie1994(color1, color2)) # Different values for textiles. print(" CIE1994: %.3f (Textiles)" % delta_e_cie1994(color1, color2, K_1=0.048, K_2=0.014, K_L=2)) print(" CIE2000: %.3f" % delta_e_cie2000(color1, color2)) # Typically used for acceptability. print(" CMC: %.3f (2:1)" % delta_e_cmc(color1, color2, pl=2, pc=1)) # Typically used to more closely model human perception. print(" CMC: %.3f (1:1)" % delta_e_cmc(color1, color2, pl=1, pc=1))
def distance(c1, c2): ''' Calculate the visual distance between the two colors. ''' lc1 = convert_color(sRGBColor(*c1), LabColor) lc2 = convert_color(sRGBColor(*c2), LabColor) return delta_e_cmc(lc1, lc2)
def distance(c1, c2): """ Calculate the visual distance between the two colors. """ return delta_e_cmc(convert_sRGB(c1), convert_sRGB(c2))
def distance(c1, c2): c1lab = convert_color(sRGBColor(c1[0], c1[1], c1[2], True), LabColor) c2lab = convert_color(sRGBColor(c2[0], c2[1], c2[2], True), LabColor) return delta_e_cmc(c1lab, c2lab)
def color_distance(c1, c2): lab1 = convert_color(sRGBColor(*c1), LabColor) lab2 = convert_color(sRGBColor(*c2), LabColor) d = delta_e_cmc(lab1, lab2) / 10 # XXX return d
#im2px[x,y] = (r,g,b) im2.save("/tmp/tmp.png") else: m = re.match(r'(..)(..)(..)', sys.argv[1]) assert m (r, g, b) = map(lambda x: int(x, 16), m.group(1, 2, 3)) c0str = '%02X%02X%02X to ' % (r, g, b) c0 = rgb2lab(r, g, b) fp = open('/tmp/tmp.html', 'w') fp.write('<html>\n') fp.write('<table>\n') fp.write( '<tr><th>input</th><th>palette</th><th>cie1976</th><th>cie1994</th><th>cie2000</th><th>cmc</th></tr>\n' ) for (idx, c1) in enumerate(p8_lab): c1str = '%02X%02X%02X' % p8_rgb[idx] delta0 = delta_e_cie1976(c0, c1) delta1 = delta_e_cie1994(c0, c1) delta2 = delta_e_cie2000(c0, c1) delta3 = delta_e_cmc(c0, c1) fp.write(' <tr>\n') fp.write(' <td bgcolor=#%s>%s</td>\n' % (c0str, c0str)) fp.write(' <td bgcolor=#%s>%s</td>\n' % (c1str, c1str)) fp.write(' <td>%f</td><td>%f</td><td>%f</td><td>%f</td>\n' % (delta0, delta1, delta2, delta3)) fp.write(' </tr>\n') fp.write('</table>\n') fp.write('</html>\n')
def color_distance(c1, c2): color1 = sRGBColor(*c1, is_upscaled=True) lab_color1 = convert_color(color1, LabColor) color2 = sRGBColor(*c2, is_upscaled=True) lab_color2 = convert_color(color2, LabColor) return delta_e_cmc(lab_color1, lab_color2)