Spaces:
Running
Running
File size: 3,296 Bytes
833f6d1 a05e644 833f6d1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
import gradio as gr
import json
import numpy as np
import tarfile
import PIL.Image as PImage
from os import listdir, path, remove
from sklearn.cluster import KMeans
from urllib import request
def download_extract():
url = "https://github.com/PSAM-5020-2025S-A/5020-utils/releases/latest/download/flowers.tar.gz"
target_path = "flowers.tar.gz"
with request.urlopen(request.Request(url), timeout=15.0) as response:
if response.status == 200:
with open(target_path, "wb") as f:
f.write(response.read())
tar = tarfile.open(target_path, "r:gz")
tar.extractall()
tar.close()
remove("flowers.tar.gz")
# Posterize image and get representative colors
def top_colors(fpath, n_clusters=8, n_colors=4):
pimg = PImage.open(fpath).convert("RGB")
pimg_pxs = list(pimg.getdata())
posterizer = KMeans(n_clusters=n_clusters)
px_clusters = posterizer.fit_predict(pimg_pxs)
cluster_colors = posterizer.cluster_centers_
_, ccounts = np.unique(px_clusters, return_counts=True)
ccounts_order = np.argsort(-ccounts)
ccolors_sorted = [[round(rgb) for rgb in cluster_colors[idx]] for idx in ccounts_order]
return ccolors_sorted[:n_colors]
# Cluster all images
def get_top_colors(flower_image_dir):
flower_files = sorted([f for f in listdir(flower_image_dir) if f.endswith(".png")])
file_colors = []
for fname in flower_files:
file_colors.append({
"filename": fname,
"colors": top_colors(f"{flower_image_dir}/{fname}", n_clusters=8, n_colors=4)
})
return file_colors
# Euclidean distance between 2 RGB color tuples
def color_distance(c0, c1):
return ((c0[0] - c1[0])**2 + (c0[1] - c1[1])**2 + (c0[2] - c1[2])**2) ** 0.5
# Function that returns minimum distance between a reference color and colors from a list
def min_color_distance(ref_color, color_list):
c_dists = [color_distance(ref_color, c) for c in color_list]
return min(c_dists)
# Turns a color hex string in the form `#12AB56`
# into an RGB tuple (18, 171, 87)
def hex_string_to_rgb(hex_str):
return (
int(hex_str[1:3], 16),
int(hex_str[3:5], 16),
int(hex_str[5:7], 16),
)
def order_by_color(center_color_str):
center_color = hex_string_to_rgb(center_color_str)
# Function that returns how close an image is to a given color
def by_color_dist(A):
return min_color_distance(center_color, A["colors"])
file_colors_sorted = sorted(FILE_COLORS, key=by_color_dist)
files_sorted = [A["filename"] for A in file_colors_sorted]
file_order = {
"color": center_color,
"files": files_sorted
}
return json.dumps(file_order)
my_inputs = [
gr.ColorPicker(value="#ffdf00", label="center_color", interactive=True)
]
my_outputs = [
gr.JSON(show_label=False, show_indices=False, height=200, container=False)
]
my_examples = [
["#FFFFFF"],
["#FFD700"],
["#7814BE"]
]
def setup():
global FILE_COLORS
FLOWER_IMG_DIR = "./data/image/flowers"
if not path.isdir(FLOWER_IMG_DIR):
download_extract()
FILE_COLORS = get_top_colors(FLOWER_IMG_DIR)
setup()
with gr.Blocks() as demo:
gr.Interface(
fn=order_by_color,
inputs=my_inputs,
outputs=my_outputs,
cache_examples=True,
examples=my_examples,
allow_flagging="never",
fill_width=True
)
if __name__ == "__main__":
demo.launch()
|