Skip to content

Instantly share code, notes, and snippets.

@mikeshardmind
Last active June 5, 2023 09:21
Show Gist options
  • Save mikeshardmind/21673e2d3045e21be9f853d4fcba7d41 to your computer and use it in GitHub Desktop.
Save mikeshardmind/21673e2d3045e21be9f853d4fcba7d41 to your computer and use it in GitHub Desktop.
dominant colors
"""
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
Copyright (C) 2020 Michael Hall <https://github.com/mikeshardmind>
"""
# Reupload of older stuff in a no longer functional discord bot isolated to single functions
# Summary of edits since isolation from old bot code:
# typing updated
# make this play nice with many ide defaults for unused vars
import numpy as np
import pandas as pd
from PIL import Image
from scipy.cluster.vq import kmeans, whiten
def get_dom_colors(img: Image.Image, count: int) -> list[tuple[int, int, int]]:
""" Get the top `count` dominant colors from `img` """
image = np.asarray(img)
df = pd.DataFrame()
for idx, c in enumerate(("r", "g", "b")):
df[c] = pd.Series(image[:,:,idx].flatten())
df[f"{c}_whiten"] = whiten(df[c])
cluster_centers, _distortion = kmeans(df[["r_whiten", "g_whiten", "b_whiten"]], count)
r_std, g_std, b_std = df[["r", "g", "b"]].std()
return [(int(r * r_std), int(g * g_std), int(b * b_std)) for (r, g, b) in cluster_centers]
"""
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
Copyright (C) 2020 Michael Hall <https://github.com/mikeshardmind>
"""
# Reupload of older stuff in a no longer functional discord bot isolated to single functions
# Summary of edits since isolation from old bot code:
# typing updated
# switch to use of scikit-learn for MiniBatchKMeans
import numpy as np
import pandas as pd
from PIL import Image
import scipy.cluster
import sklearn.cluster
def get_dom_colors(img: Image.Image, count: int = 1, iterations: int | None = 1) -> list[tuple[int, int, int]]:
"""
Get the top `count` dominant colors from `img`
kmeans will repeat until mo
"""
image = np.asarray(img)
df = pd.DataFrame()
for idx, c in enumerate(("r", "g", "b")):
df[c] = pd.Series(image[:,:,idx].flatten())
working_matrix = df[["r", "g", "b"]]
kmeans = sklearn.cluster.MiniBatchKMeans(
n_init="auto",
n_clusters=count,
init="k-means++",
max_iter=1,
random_state=0,
).fit(working_matrix)
codes = kmeans.cluster_centers_
vecs, _dist = scipy.cluster.vq.vq(working_matrix, codes)
counts, _bins = np.histogram(vecs, len(codes))
return [tuple(int(code) for code in codes[index]) for index in np.argsort(counts)[::-1]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment