Skip to content

Commit 78cafe0

Browse files
authored
Merge pull request #20 from zeroquinc/dominant-color-embed
enhancement: use scikit-learn to get the most distinct color for the embed
2 parents 1cf68d4 + cfe1856 commit 78cafe0

File tree

2 files changed

+28
-18
lines changed

2 files changed

+28
-18
lines changed

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ numpy==1.26.4
55
Pillow==10.3.0
66
pytz==2024.1
77
Requests==2.31.0
8-
psnawp_api==1.3.3
8+
psnawp_api==1.3.3
9+
scikit-learn==1.4.2

utils/image_utils.py

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,46 @@
1-
import requests
21
from PIL import Image
2+
import requests
33
from io import BytesIO
4-
from colorthief import ColorThief
54
import numpy as np
5+
from sklearn.cluster import KMeans
66

7-
def get_discord_color(image_url, border_percentage=0.2):
7+
def get_discord_color(image_url, num_colors=5, crop_percentage=0.5):
88
"""
9-
Get the most common color from an image for Discord usage.
9+
Get the most distinct color from the center of an image for Discord usage.
1010
1111
Args:
1212
image_url (str): The URL of the image to analyze.
13-
border_percentage (float): The percentage of border to exclude when cropping the image (default is 0.2).
13+
num_colors (int): Number of dominant colors to extract (default is 5).
14+
crop_percentage (float): Percentage of the image to keep in the center (default is 0.5).
1415
1516
Returns:
16-
int: The most common color in hexadecimal format.
17+
int: The most distinct color in hexadecimal format.
1718
1819
Raises:
1920
(Exception): If there is an issue with fetching or processing the image.
2021
"""
2122
response = requests.get(image_url)
22-
img = Image.open(BytesIO(response.content)).convert('RGB')
23-
24-
# Crop the image to exclude borders
23+
img = Image.open(BytesIO(response.content))
24+
25+
# Calculate the crop dimensions
2526
width, height = img.size
26-
img = img.crop((width * border_percentage, height * border_percentage, width * (1 - border_percentage), height * (1 - border_percentage)))
27+
crop_width = int(width * crop_percentage)
28+
crop_height = int(height * crop_percentage)
29+
left = (width - crop_width) // 2
30+
top = (height - crop_height) // 2
31+
right = left + crop_width
32+
bottom = top + crop_height
33+
34+
img = img.crop((left, top, right, bottom))
35+
36+
img = img.resize((img.width // 2, img.height // 2)) # Resize for faster processing
2737

28-
color_thief = ColorThief(BytesIO(response.content))
29-
palette = color_thief.get_palette(color_count=4, quality=4)
38+
img_array = np.array(img)
39+
img_flattened = img_array.reshape(-1, 3)
3040

31-
img_arr = np.array(img)
32-
color_counts = {tuple(color): np.sum(np.all(img_arr == color, axis=-1)) for color in palette}
41+
kmeans = KMeans(n_clusters=num_colors)
42+
kmeans.fit(img_flattened)
3343

34-
# Find the most common color
35-
most_common_color = max(color_counts, key=color_counts.get)
44+
dominant_color = kmeans.cluster_centers_[np.argmax(np.bincount(kmeans.labels_))]
3645

37-
return int('0x{:02x}{:02x}{:02x}'.format(*most_common_color), 16)
46+
return int('0x{:02x}{:02x}{:02x}'.format(*dominant_color.astype(int)), 16)

0 commit comments

Comments
 (0)