arvkevi commited on
Commit
505a4da
1 Parent(s): 3945376

Add application file

Browse files
Files changed (2) hide show
  1. app.py +128 -0
  2. requirements.txt +2 -0
app.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import warnings
2
+ from io import BytesIO
3
+
4
+ import matplotlib as mpl
5
+ import matplotlib.patches as patches
6
+ import matplotlib.pyplot as plt
7
+ import numpy as np
8
+ from mpl_toolkits.axes_grid1 import make_axes_locatable
9
+
10
+ import streamlit as st
11
+ from img2cmap import ImageConverter
12
+
13
+ warnings.filterwarnings("ignore")
14
+ st.set_option("deprecation.showfileUploaderEncoding", False)
15
+
16
+ st.set_page_config(
17
+ page_title="img2cmap web",
18
+ layout="wide",
19
+ )
20
+
21
+ st.title("Convert images to a colormap")
22
+ st.markdown(
23
+ """
24
+ This app converts images to colormaps using the Python
25
+ library [img2cmap](https://github.com/arvkevi/img2cmap).
26
+ Try your own image on the left. **Scroll down to generate an optimal colormap.**
27
+ """
28
+ )
29
+
30
+ st.sidebar.markdown("### Image settings")
31
+ file_or_url = st.sidebar.radio("Upload an image file or paste an image URL", ("file", "url"))
32
+
33
+ if file_or_url == "file":
34
+ user_image = st.sidebar.file_uploader("Upload an image file")
35
+ if user_image is not None:
36
+ user_image = BytesIO(user_image.getvalue())
37
+ elif file_or_url == "url":
38
+ user_image = st.sidebar.text_input("Paste an image URL", "https://static1.bigstockphoto.com/3/2/3/large1500/323952496.jpg")
39
+ else:
40
+ st.warning("Please select an option")
41
+
42
+ # default image to use
43
+ if user_image is None:
44
+ user_image = "https://raw.githubusercontent.com/arvkevi/img2cmap/main/tests/images/south_beach_sunset.jpg"
45
+
46
+ # user settings
47
+ st.sidebar.markdown("### User settings")
48
+ n_colors = st.sidebar.number_input(
49
+ "Number of colors", min_value=2, max_value=20, value=5, help="The number of colors to return in the colormap"
50
+ )
51
+ n_colors = int(n_colors)
52
+ remove_transparent = st.sidebar.checkbox(
53
+ "Remove transparency", False, help="If checked, remove transparent pixels from the image before clustering."
54
+ )
55
+ random_state = st.sidebar.number_input("Random state", value=42, help="Random state for reproducibility")
56
+ random_state = int(random_state)
57
+
58
+
59
+ @st.cache(allow_output_mutation=True)
60
+ def get_image_converter(user_image, remove_transparent):
61
+ converter = ImageConverter(user_image, remove_transparent=remove_transparent)
62
+ return converter
63
+
64
+
65
+ converter = get_image_converter(user_image, remove_transparent)
66
+
67
+ with st.spinner("Generating colormap..."):
68
+ cmap = converter.generate_cmap(n_colors=n_colors, palette_name="", random_state=random_state)
69
+
70
+ # plot the image and colorbar
71
+ fig1, ax1 = plt.subplots(figsize=(8, 8))
72
+
73
+ ax1.axis("off")
74
+ img = converter.image
75
+ im = ax1.imshow(img, cmap=cmap)
76
+
77
+ divider = make_axes_locatable(ax1)
78
+ cax = divider.append_axes("right", size="10%", pad=0.05)
79
+
80
+ cb = fig1.colorbar(im, cax=cax, orientation="vertical", label=cmap.name)
81
+ cb.set_ticks([])
82
+ st.pyplot(fig1)
83
+
84
+ colors1 = [mpl.colors.rgb2hex(c) for c in cmap.colors]
85
+ st.text("Hex Codes (click to copy on far right)")
86
+ st.code(colors1)
87
+
88
+
89
+ st.header("Detect optimal number of colors")
90
+ optimize = st.button("Optimize")
91
+ if optimize:
92
+ with st.spinner("Optimizing... (this takes about a minute)"):
93
+ cmaps, best_n_colors, ssd = converter.generate_optimal_cmap(max_colors=20, palette_name="", random_state=random_state)
94
+
95
+ figopt, ax = plt.subplots(figsize=(7, 5))
96
+
97
+ ymax = 21
98
+ xmax = 20
99
+ ax.set_ylim(2, ymax)
100
+ ax.set_xlim(0, 20)
101
+
102
+ # i will be y axis
103
+ for y, cmap_ in cmaps.items():
104
+ colors = sorted([mpl.colors.rgb2hex(c) for c in cmap_.colors])
105
+ intervals, width = np.linspace(0, xmax, len(colors) + 1, retstep=True)
106
+ # j will be x axis
107
+ for j, color in enumerate(colors):
108
+ rect = patches.Rectangle((intervals[j], y), width, 1, facecolor=color)
109
+ ax.add_patch(rect)
110
+
111
+ ax.set_yticks(np.arange(2, ymax) + 0.5)
112
+ ax.set_yticklabels(np.arange(2, ymax))
113
+ ax.set_ylabel("Number of colors")
114
+ ax.set_xticks([])
115
+
116
+ # best
117
+ rect = patches.Rectangle((0, best_n_colors), ymax, 1, linewidth=1, facecolor="none", edgecolor="black", linestyle="--")
118
+ ax.add_patch(rect)
119
+
120
+ # minus 2, one for starting at 2 and one for 0-indexing
121
+ ax.get_yticklabels()[best_n_colors - 2].set_color("red")
122
+ st.pyplot(figopt)
123
+ st.metric("Optimal number of colors", best_n_colors)
124
+ st.text("Hex Codes of optimal colormap (click to copy on far right)")
125
+ st.code(sorted([mpl.colors.rgb2hex(c) for c in cmaps[best_n_colors].colors]))
126
+
127
+ st.text("Sum of squared distances by number of colors:")
128
+ st.write(ssd)
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ streamlit
2
+ git+https://github.com/arvkevi/img2cmap@main#egg=img2cmap