thalismind commited on
Commit ·
c913ad2
1
Parent(s): 36b6206
fix pixelization
Browse files- README.md +10 -0
- pixelize.py +58 -13
README.md
CHANGED
|
@@ -79,6 +79,16 @@ Please prepare the repository for use with HuggingFace Spaces. Make sure it has
|
|
| 79 |
|
| 80 |
Followed by manually updating the Gradio version in the README.md frontmatter and the requirements.txt file to use the latest version.
|
| 81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
## License
|
| 83 |
|
| 84 |
This project is open source and available under the MIT License.
|
|
|
|
| 79 |
|
| 80 |
Followed by manually updating the Gradio version in the README.md frontmatter and the requirements.txt file to use the latest version.
|
| 81 |
|
| 82 |
+
The pixelization process was not implemented correctly and was resizing the image. That was fixed with the following prompt:
|
| 83 |
+
|
| 84 |
+
```none
|
| 85 |
+
The pixel_size parameter currently makes the image larger, but it should make the pixels larger within the image, by combining groups of pixels on the grid given by the pixel_size. For example, if pixel_size is 2, then every 2x2 group should be the same color. If pixel_size is 4, then the groups are 4x4. Use the best color for each group based on the pixels within it.
|
| 86 |
+
```
|
| 87 |
+
|
| 88 |
+
```none
|
| 89 |
+
The average color may not be the best color for each pixel. Try both the mean and mode, and see which one is closer to the palette colors.
|
| 90 |
+
```
|
| 91 |
+
|
| 92 |
## License
|
| 93 |
|
| 94 |
This project is open source and available under the MIT License.
|
pixelize.py
CHANGED
|
@@ -2,6 +2,7 @@ import numpy as np
|
|
| 2 |
from PIL import Image
|
| 3 |
from sklearn.cluster import KMeans
|
| 4 |
import gradio as gr
|
|
|
|
| 5 |
|
| 6 |
def extract_palette_from_image(palette_image):
|
| 7 |
"""Extract unique colors from a palette image."""
|
|
@@ -71,13 +72,35 @@ def rgb_to_hsv(rgb):
|
|
| 71 |
h = (h / 6.0) % 1.0
|
| 72 |
return h, s, v
|
| 73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
def pixelize_image(image, palette, mode='rgb', pixel_size=1):
|
| 75 |
"""Convert image to pixel art using the given palette."""
|
| 76 |
img = Image.open(image)
|
| 77 |
img_array = np.array(img)
|
| 78 |
|
| 79 |
-
#
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
# Choose distance function based on mode
|
| 83 |
if mode == 'rgb':
|
|
@@ -87,20 +110,42 @@ def pixelize_image(image, palette, mode='rgb', pixel_size=1):
|
|
| 87 |
else: # brightness
|
| 88 |
distance_func = brightness_distance
|
| 89 |
|
| 90 |
-
#
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
|
| 97 |
# Create output image
|
| 98 |
-
output = Image.fromarray(
|
| 99 |
|
| 100 |
-
# Resize
|
| 101 |
-
|
| 102 |
-
width, height = output.size
|
| 103 |
-
output = output.resize((width * pixel_size, height * pixel_size), Image.NEAREST)
|
| 104 |
|
| 105 |
return output
|
| 106 |
|
|
|
|
| 2 |
from PIL import Image
|
| 3 |
from sklearn.cluster import KMeans
|
| 4 |
import gradio as gr
|
| 5 |
+
from collections import Counter
|
| 6 |
|
| 7 |
def extract_palette_from_image(palette_image):
|
| 8 |
"""Extract unique colors from a palette image."""
|
|
|
|
| 72 |
h = (h / 6.0) % 1.0
|
| 73 |
return h, s, v
|
| 74 |
|
| 75 |
+
def get_mode_color(pixel_group):
|
| 76 |
+
"""Calculate the mode color of a pixel group."""
|
| 77 |
+
# Reshape to get all pixels
|
| 78 |
+
pixels = pixel_group.reshape(-1, 3)
|
| 79 |
+
|
| 80 |
+
# Convert to tuple for counting
|
| 81 |
+
pixel_tuples = [tuple(pixel) for pixel in pixels]
|
| 82 |
+
|
| 83 |
+
# Count occurrences of each color
|
| 84 |
+
color_counts = Counter(pixel_tuples)
|
| 85 |
+
|
| 86 |
+
# Get the most common color
|
| 87 |
+
mode_color = np.array(color_counts.most_common(1)[0][0])
|
| 88 |
+
return mode_color
|
| 89 |
+
|
| 90 |
def pixelize_image(image, palette, mode='rgb', pixel_size=1):
|
| 91 |
"""Convert image to pixel art using the given palette."""
|
| 92 |
img = Image.open(image)
|
| 93 |
img_array = np.array(img)
|
| 94 |
|
| 95 |
+
# Get image dimensions
|
| 96 |
+
height, width = img_array.shape[:2]
|
| 97 |
+
|
| 98 |
+
# Calculate new dimensions based on pixel_size
|
| 99 |
+
new_height = height // pixel_size
|
| 100 |
+
new_width = width // pixel_size
|
| 101 |
+
|
| 102 |
+
# Initialize output array
|
| 103 |
+
output_array = np.zeros((new_height, new_width, 3), dtype=np.uint8)
|
| 104 |
|
| 105 |
# Choose distance function based on mode
|
| 106 |
if mode == 'rgb':
|
|
|
|
| 110 |
else: # brightness
|
| 111 |
distance_func = brightness_distance
|
| 112 |
|
| 113 |
+
# Process each pixel group
|
| 114 |
+
for y in range(new_height):
|
| 115 |
+
for x in range(new_width):
|
| 116 |
+
# Get the pixel group
|
| 117 |
+
y_start = y * pixel_size
|
| 118 |
+
y_end = min((y + 1) * pixel_size, height)
|
| 119 |
+
x_start = x * pixel_size
|
| 120 |
+
x_end = min((x + 1) * pixel_size, width)
|
| 121 |
+
|
| 122 |
+
pixel_group = img_array[y_start:y_end, x_start:x_end]
|
| 123 |
+
|
| 124 |
+
# Calculate mean and mode colors
|
| 125 |
+
mean_color = np.mean(pixel_group, axis=(0, 1)).astype(int)
|
| 126 |
+
mode_color = get_mode_color(pixel_group)
|
| 127 |
+
|
| 128 |
+
# Find closest palette color for mean
|
| 129 |
+
mean_distances = np.array([distance_func(mean_color, palette_color) for palette_color in palette])
|
| 130 |
+
mean_closest_color = palette[np.argmin(mean_distances)]
|
| 131 |
+
mean_min_distance = np.min(mean_distances)
|
| 132 |
+
|
| 133 |
+
# Find closest palette color for mode
|
| 134 |
+
mode_distances = np.array([distance_func(mode_color, palette_color) for palette_color in palette])
|
| 135 |
+
mode_closest_color = palette[np.argmin(mode_distances)]
|
| 136 |
+
mode_min_distance = np.min(mode_distances)
|
| 137 |
+
|
| 138 |
+
# Choose the color with the smaller distance to palette
|
| 139 |
+
if mean_min_distance <= mode_min_distance:
|
| 140 |
+
output_array[y, x] = mean_closest_color
|
| 141 |
+
else:
|
| 142 |
+
output_array[y, x] = mode_closest_color
|
| 143 |
|
| 144 |
# Create output image
|
| 145 |
+
output = Image.fromarray(output_array)
|
| 146 |
|
| 147 |
+
# Resize back to original dimensions
|
| 148 |
+
output = output.resize((width, height), Image.NEAREST)
|
|
|
|
|
|
|
| 149 |
|
| 150 |
return output
|
| 151 |
|