Partially fix k-means and commit an example image

This commit is contained in:
2024-08-08 01:52:31 -07:00
parent a0ae310ed3
commit f4c1775f72
2 changed files with 18 additions and 3 deletions
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

+18 -3
View File
@@ -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)