def euclidean(a, b): '''returns the euclidean distance between two pixel RGB values.''' r = (a[0] - b[0]) * (a[0] - b[0]) g = (a[1] - b[1]) * (a[1] - b[1]) b = (a[2] - b[2]) * (a[2] - b[2]) return math.sqrt(r + g + b) def kmeans(source_colors, k): '''takes a list of source colors as tuples and returns a kmeans generated color palette''' kmeans = {} for i in range(k): r = random.choice(source_colors) kmeans[r] = [] while True: for color in source_colors: distances = {} for mean in kmeans: distances[mean] = euclidean(color, mean) mdist = min(distances.values()) for key, val in distances.items(): if val == mdist: kmeans[key].append(color) new_kmeans = {} for mean, colors in kmeans.items(): r, g, b = 0, 0, 0 for i in colors: r += i[0] g += i[1] b += i[2] r = r // len(colors) g = g // len(colors) b = b // len(colors) new_kmeans[(r, g, b)] = [] if kmeans.keys() == new_kmeans.keys(): break else: kmeans = new_kmeans palette = list(kmeans.keys()) return palette