Spaces:
Build error
Build error
Upload app.py
Browse files
app.py
ADDED
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import numpy as np
|
3 |
+
import matplotlib.pyplot as plt
|
4 |
+
from PIL import Image
|
5 |
+
import colorsys
|
6 |
+
from sklearn.cluster import KMeans
|
7 |
+
import io
|
8 |
+
|
9 |
+
def rgb_to_hsv(rgb):
|
10 |
+
"""Convert RGB to HSV color space."""
|
11 |
+
return colorsys.rgb_to_hsv(rgb[0]/255.0, rgb[1]/255.0, rgb[2]/255.0)
|
12 |
+
|
13 |
+
def classify_undertone(h, s, v):
|
14 |
+
"""
|
15 |
+
Classify skin undertones based on HSV color space.
|
16 |
+
This is a simplified approximation and should not be used for precise skin tone analysis.
|
17 |
+
"""
|
18 |
+
if 0.05 <= h <= 0.15: # Warm orange-yellow range
|
19 |
+
return 'Warm'
|
20 |
+
elif 0.55 <= h <= 0.75: # Cool blue-purple range
|
21 |
+
return 'Cool'
|
22 |
+
else:
|
23 |
+
return 'Neutral'
|
24 |
+
|
25 |
+
def classify_seasonal_type(h, s, v):
|
26 |
+
"""
|
27 |
+
Classify seasonal color types based on HSV values.
|
28 |
+
This is a highly simplified approximation.
|
29 |
+
"""
|
30 |
+
if 0.05 <= h <= 0.15 and s > 0.5 and v > 0.5:
|
31 |
+
return 'Spring'
|
32 |
+
elif 0.15 <= h <= 0.35 and s < 0.5 and v > 0.5:
|
33 |
+
return 'Summer'
|
34 |
+
elif 0.35 <= h <= 0.55 and s > 0.5 and v > 0.5:
|
35 |
+
return 'Autumn'
|
36 |
+
elif (h <= 0.05 or h >= 0.75) and s < 0.3 and v < 0.5:
|
37 |
+
return 'Winter'
|
38 |
+
else:
|
39 |
+
return 'Undefined'
|
40 |
+
|
41 |
+
def analyze_image_colors(img):
|
42 |
+
"""
|
43 |
+
Analyze colors in an image, create visualizations, and perform clustering.
|
44 |
+
"""
|
45 |
+
# Convert image to RGB if needed
|
46 |
+
img = img.convert('RGB')
|
47 |
+
|
48 |
+
# Convert image to numpy array
|
49 |
+
img_array = np.array(img)
|
50 |
+
|
51 |
+
# Reshape the image to be a list of pixels
|
52 |
+
pixels = img_array.reshape(-1, 3)
|
53 |
+
|
54 |
+
# Perform K-means clustering
|
55 |
+
kmeans = KMeans(n_clusters=10, random_state=42)
|
56 |
+
kmeans.fit(pixels)
|
57 |
+
|
58 |
+
# Get cluster centers and labels
|
59 |
+
colors = kmeans.cluster_centers_
|
60 |
+
labels = kmeans.labels_
|
61 |
+
|
62 |
+
# Convert RGB to HSV for further analysis
|
63 |
+
hsv_colors = np.array([rgb_to_hsv(color) for color in colors])
|
64 |
+
|
65 |
+
# Classify undertones and seasonal types
|
66 |
+
undertones = [classify_undertone(h, s, v) for h, s, v in hsv_colors]
|
67 |
+
seasonal_types = [classify_seasonal_type(h, s, v) for h, s, v in hsv_colors]
|
68 |
+
|
69 |
+
# Visualizations
|
70 |
+
plt.figure(figsize=(15, 10))
|
71 |
+
|
72 |
+
# 1. Color Gradient Plot
|
73 |
+
plt.subplot(2, 2, 1)
|
74 |
+
luminance = np.dot(colors, [0.299, 0.587, 0.114])
|
75 |
+
sorted_indices = np.argsort(luminance)
|
76 |
+
sorted_colors = colors[sorted_indices] / 255.0
|
77 |
+
|
78 |
+
plt.imshow(sorted_colors[np.newaxis, :], aspect='auto', extent=[0, 1, 0, 1])
|
79 |
+
plt.title('Color Gradient (Sorted by Luminance)')
|
80 |
+
plt.xlabel('Color Progression')
|
81 |
+
plt.xticks([])
|
82 |
+
plt.yticks([])
|
83 |
+
|
84 |
+
# 2. Color Bar Plot
|
85 |
+
plt.subplot(2, 2, 2)
|
86 |
+
cluster_counts = np.unique(labels, return_counts=True)[1]
|
87 |
+
plt.bar(range(len(colors)), cluster_counts, color=colors/255)
|
88 |
+
plt.title('Color Distribution')
|
89 |
+
plt.xlabel('Cluster')
|
90 |
+
plt.ylabel('Pixel Count')
|
91 |
+
|
92 |
+
# 3. Pie Chart of Undertones
|
93 |
+
plt.subplot(2, 2, 3)
|
94 |
+
undertone_counts = np.unique(undertones, return_counts=True)
|
95 |
+
plt.pie(undertone_counts[1], labels=undertone_counts[0], autopct='%1.1f%%')
|
96 |
+
plt.title('Undertone Distribution')
|
97 |
+
|
98 |
+
# 4. Pie Chart of Seasonal Types
|
99 |
+
plt.subplot(2, 2, 4)
|
100 |
+
seasonal_counts = np.unique(seasonal_types, return_counts=True)
|
101 |
+
plt.pie(seasonal_counts[1], labels=seasonal_counts[0], autopct='%1.1f%%')
|
102 |
+
plt.title('Seasonal Type Distribution')
|
103 |
+
|
104 |
+
plt.tight_layout()
|
105 |
+
|
106 |
+
# Save plot to a buffer
|
107 |
+
buf = io.BytesIO()
|
108 |
+
plt.savefig(buf, format='png')
|
109 |
+
buf.seek(0)
|
110 |
+
plt.close()
|
111 |
+
|
112 |
+
# Prepare color cluster details
|
113 |
+
cluster_details = []
|
114 |
+
for i, (color, undertone, season) in enumerate(zip(colors, undertones, seasonal_types)):
|
115 |
+
cluster_details.append({
|
116 |
+
'Cluster': i,
|
117 |
+
'RGB Color': color,
|
118 |
+
'Undertone': undertone,
|
119 |
+
'Seasonal Type': season
|
120 |
+
})
|
121 |
+
|
122 |
+
return buf, cluster_details
|
123 |
+
|
124 |
+
def main():
|
125 |
+
st.title('Image Color Analysis Tool')
|
126 |
+
|
127 |
+
# File uploader
|
128 |
+
uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "jpeg", "png"])
|
129 |
+
|
130 |
+
if uploaded_file is not None:
|
131 |
+
# Display the uploaded image
|
132 |
+
image = Image.open(uploaded_file)
|
133 |
+
st.image(image, caption='Uploaded Image', use_column_width=True)
|
134 |
+
|
135 |
+
# Analyze colors
|
136 |
+
st.write('Analyzing image colors...')
|
137 |
+
plot_buffer, cluster_details = analyze_image_colors(image)
|
138 |
+
|
139 |
+
# Display analysis plot
|
140 |
+
st.image(plot_buffer, caption='Color Analysis Visualization')
|
141 |
+
|
142 |
+
# Display cluster details
|
143 |
+
st.subheader('Color Cluster Details')
|
144 |
+
for cluster in cluster_details:
|
145 |
+
st.write(f"**Cluster {cluster['Cluster']}:**")
|
146 |
+
st.write(f" - RGB Color: {cluster['RGB Color']}")
|
147 |
+
st.write(f" - Undertone: {cluster['Undertone']}")
|
148 |
+
st.write(f" - Seasonal Type: {cluster['Seasonal Type']}")
|
149 |
+
|
150 |
+
if __name__ == '__main__':
|
151 |
+
main()
|