Partially fix k-means and commit an example image
This commit is contained in:
+18
-3
@@ -44,15 +44,21 @@ def choose_color_pair_kmeans(counts: dict[RGB,int]) -> tuple[RGB, RGB]:
|
||||
|
||||
def weighted_avg(colors: list[RGB]) -> RGB:
|
||||
result = [0, 0, 0]
|
||||
total_weight = 0
|
||||
for color in colors:
|
||||
weight = counts[color]
|
||||
total_weight += weight
|
||||
for i in range(3):
|
||||
result[i] += weight*color[i]
|
||||
return tuple(round(x/total_count) for x in result)
|
||||
if total_weight == 0:
|
||||
total_weight += 1 # Hack to handle division-by-zero
|
||||
return tuple(round(x/total_weight) for x in result)
|
||||
|
||||
# k-means to choose the two colors
|
||||
old_result = (None, None)
|
||||
result = (darkest_color, lightest_color)
|
||||
result = (min(colors, key=brightness), max(colors, key=brightness))
|
||||
print(f"k-means using {counts=}")
|
||||
print(f"starting value: {result}")
|
||||
while True:
|
||||
lists = ([], [])
|
||||
for color in colors:
|
||||
@@ -63,7 +69,9 @@ def choose_color_pair_kmeans(counts: dict[RGB,int]) -> tuple[RGB, RGB]:
|
||||
else:
|
||||
lists[1].append(color)
|
||||
old_result = result
|
||||
print(f"{lists=}")
|
||||
result = tuple(weighted_avg(cs) for cs in lists)
|
||||
print(f"updated: {result}")
|
||||
if old_result == result:
|
||||
break
|
||||
return tuple(nearest_color(x, palette) for x in result)
|
||||
@@ -119,7 +127,10 @@ def two_tone(img: Image, xy1: tuple[int,int] = None, xy2: tuple[int,int] = None)
|
||||
if color not in counts:
|
||||
counts[color] = 0
|
||||
counts[color] += 1
|
||||
dark, light = choose_color_pair_luminance(counts)
|
||||
#dark, light = choose_color_pair_luminance(counts)
|
||||
print(f"choosing color pair for {xy1=}")
|
||||
dark, light = choose_color_pair_kmeans(counts)
|
||||
print(f"final: {dark=}, {light=}\n")
|
||||
if light == None:
|
||||
# Only one color, *ought* to be a no-op
|
||||
light = dark
|
||||
@@ -138,3 +149,7 @@ blocked = img.copy()
|
||||
for x in range(0, img.width, BLOCK_SIZE):
|
||||
for y in range(0, img.height, BLOCK_SIZE):
|
||||
two_tone(blocked, (x, y), (x + BLOCK_SIZE, y + BLOCK_SIZE))
|
||||
blocked.save("blocked.png")
|
||||
for x in range(5):
|
||||
for y in range(5):
|
||||
blocked.putpixel((x, y), 0)
|
||||
|
||||
Reference in New Issue
Block a user