Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -7,7 +7,7 @@ import numpy as np
|
|
7 |
import gradio.components as gc
|
8 |
import gradio as gr
|
9 |
|
10 |
-
|
11 |
def pixart(
|
12 |
i,
|
13 |
block_size=4,
|
@@ -16,6 +16,8 @@ def pixart(
|
|
16 |
local_contrast_blur_radius=51, # has to be odd
|
17 |
upscale=True,
|
18 |
seed=None,
|
|
|
|
|
19 |
):
|
20 |
w, h = i.size
|
21 |
dw = w//block_size
|
@@ -56,17 +58,35 @@ def pixart(
|
|
56 |
most_sat_color = (hsv[label_grid == cluster] @
|
57 |
np.array(hsv_weights)).argmax()
|
58 |
return hsv[label_grid == cluster][most_sat_color]
|
|
|
59 |
cluster_colors = np.array([
|
60 |
pick_representative_pixel(c)
|
61 |
for c in range(centers.shape[0])])
|
|
|
|
|
62 |
|
63 |
-
|
64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
rgb = cv2.cvtColor(ki.astype(np.uint8), cv2.COLOR_HSV2RGB)
|
67 |
i = Image.fromarray(rgb)
|
68 |
if upscale:
|
69 |
i = i.resize((w, h), Image.Resampling.NEAREST)
|
|
|
|
|
|
|
|
|
70 |
return i, seed
|
71 |
|
72 |
|
@@ -77,6 +97,8 @@ def query(
|
|
77 |
hsv_weights, # ='0,0,1'
|
78 |
local_contrast_blur_radius, # =51 has to be odd
|
79 |
seed, # =42,
|
|
|
|
|
80 |
):
|
81 |
bs = float(block_size)
|
82 |
w, h = i.size
|
@@ -95,12 +117,13 @@ def query(
|
|
95 |
local_contrast_blur_radius=local_contrast_blur_radius,
|
96 |
upscale=True,
|
97 |
seed=int(seed) if seed != '' else None,
|
|
|
|
|
98 |
)
|
99 |
-
if n_clusters<=256:
|
100 |
-
pxart=pxart.convert('P', palette=Image.Palette.ADAPTIVE, colors=n_clusters)
|
101 |
-
|
102 |
return pxart, usedseed
|
103 |
-
|
104 |
|
105 |
|
106 |
# %%
|
@@ -112,7 +135,7 @@ block_size = gc.Textbox(
|
|
112 |
label='Block Size ',
|
113 |
placeholder="e.g. 8 for 8 pixels. 0.01 for 1% of min(w,h) (<1 for percentages, >= 1 for pixels)")
|
114 |
palette_size = gc.Slider(
|
115 |
-
1,
|
116 |
hsv_weights = gc.Textbox(
|
117 |
"0,0,1",
|
118 |
label='HSV Weights. Weights of the channels when selecting a "representative pixel"/centroid from a cluster of pixels',
|
@@ -126,14 +149,19 @@ seed = gc.Textbox(
|
|
126 |
placeholder='e.g. 42')
|
127 |
|
128 |
outimage = gc.Image(
|
129 |
-
#shape=(224, 224),
|
130 |
label="Output", type='pil')
|
131 |
seedout = gc.Textbox(label='used seed')
|
132 |
|
|
|
|
|
|
|
|
|
|
|
133 |
|
134 |
gr.Interface(
|
135 |
query,
|
136 |
-
[searchimage, block_size, palette_size, hsv_weights, lcbr, seed],
|
137 |
[outimage, seedout],
|
138 |
title="kmeans-Pixartifier",
|
139 |
description=f"Turns images into pixel art using kmeans clustering",
|
|
|
7 |
import gradio.components as gc
|
8 |
import gradio as gr
|
9 |
|
10 |
+
|
11 |
def pixart(
|
12 |
i,
|
13 |
block_size=4,
|
|
|
16 |
local_contrast_blur_radius=51, # has to be odd
|
17 |
upscale=True,
|
18 |
seed=None,
|
19 |
+
output_scaling=1,
|
20 |
+
dither_amount=15
|
21 |
):
|
22 |
w, h = i.size
|
23 |
dw = w//block_size
|
|
|
58 |
most_sat_color = (hsv[label_grid == cluster] @
|
59 |
np.array(hsv_weights)).argmax()
|
60 |
return hsv[label_grid == cluster][most_sat_color]
|
61 |
+
|
62 |
cluster_colors = np.array([
|
63 |
pick_representative_pixel(c)
|
64 |
for c in range(centers.shape[0])])
|
65 |
+
|
66 |
+
|
67 |
|
68 |
+
if dither_amount == 0:
|
69 |
+
# assign each pixel the color of its cluster
|
70 |
+
ki = cluster_colors[label_grid]
|
71 |
+
else:
|
72 |
+
# add noise to the colors before selecting the nearest color, this acts as a dithering effect
|
73 |
+
noised_colors = hsv32 + np.random.normal(0, dither_amount, hsv.shape)
|
74 |
+
noised_colors = np.clip(noised_colors, 0, 255)
|
75 |
+
flattened = noised_colors.reshape(-1, 3)
|
76 |
+
# use the dot product to find the closest cluster (could also try euclidean distance)
|
77 |
+
closest_clusters = np.argmax(flattened @ centers.T,axis=1)
|
78 |
+
closest_clusters_eucledian = np.argmin(np.linalg.norm(centers - flattened[:, None], axis=-1), axis=1)
|
79 |
+
label_grid = closest_clusters_eucledian.reshape(hsv32.shape[:2])
|
80 |
+
ki = cluster_colors[label_grid]
|
81 |
|
82 |
rgb = cv2.cvtColor(ki.astype(np.uint8), cv2.COLOR_HSV2RGB)
|
83 |
i = Image.fromarray(rgb)
|
84 |
if upscale:
|
85 |
i = i.resize((w, h), Image.Resampling.NEAREST)
|
86 |
+
|
87 |
+
if output_scaling != 1:
|
88 |
+
i = i.resize(
|
89 |
+
(w*output_scaling, h*output_scaling), Image.Resampling.NEAREST)
|
90 |
return i, seed
|
91 |
|
92 |
|
|
|
97 |
hsv_weights, # ='0,0,1'
|
98 |
local_contrast_blur_radius, # =51 has to be odd
|
99 |
seed, # =42,
|
100 |
+
output_scaling,
|
101 |
+
dither_amount
|
102 |
):
|
103 |
bs = float(block_size)
|
104 |
w, h = i.size
|
|
|
117 |
local_contrast_blur_radius=local_contrast_blur_radius,
|
118 |
upscale=True,
|
119 |
seed=int(seed) if seed != '' else None,
|
120 |
+
output_scaling=output_scaling,
|
121 |
+
dither_amount=dither_amount
|
122 |
)
|
123 |
+
if n_clusters <= 256:
|
124 |
+
pxart = pxart.convert('P', palette=Image.Palette.ADAPTIVE, colors=n_clusters)
|
125 |
+
pxart.save('temp.bmp')
|
126 |
return pxart, usedseed
|
|
|
127 |
|
128 |
|
129 |
# %%
|
|
|
135 |
label='Block Size ',
|
136 |
placeholder="e.g. 8 for 8 pixels. 0.01 for 1% of min(w,h) (<1 for percentages, >= 1 for pixels)")
|
137 |
palette_size = gc.Slider(
|
138 |
+
1, 1024, 32, step=1, label='Palette Size (Number of Colors)')
|
139 |
hsv_weights = gc.Textbox(
|
140 |
"0,0,1",
|
141 |
label='HSV Weights. Weights of the channels when selecting a "representative pixel"/centroid from a cluster of pixels',
|
|
|
149 |
placeholder='e.g. 42')
|
150 |
|
151 |
outimage = gc.Image(
|
152 |
+
# shape=(224, 224),
|
153 |
label="Output", type='pil')
|
154 |
seedout = gc.Textbox(label='used seed')
|
155 |
|
156 |
+
output_scaling = gc.Slider(
|
157 |
+
0, 16, 1, step=1, label='Output scaling factor')
|
158 |
+
|
159 |
+
dither_amount = gc.Slider(
|
160 |
+
0, 255, 0, step=1, label='Dithering amount')
|
161 |
|
162 |
gr.Interface(
|
163 |
query,
|
164 |
+
[searchimage, block_size, palette_size, hsv_weights, lcbr, seed, output_scaling, dither_amount],
|
165 |
[outimage, seedout],
|
166 |
title="kmeans-Pixartifier",
|
167 |
description=f"Turns images into pixel art using kmeans clustering",
|