Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -52,18 +52,16 @@ def zoom_at(img, x, y, zoom):
|
|
52 |
Returns:
|
53 |
-------
|
54 |
PIL.Image
|
55 |
-
Zoomed image.
|
56 |
-
|
57 |
-
Examples:
|
58 |
-
--------
|
59 |
-
>>> img = Image.open('image.jpg')
|
60 |
-
>>> zoomed_img = zoom_at(img, x=100, y=100, zoom=2.0)
|
61 |
'''
|
62 |
w, h = img.size
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
|
|
|
|
|
|
67 |
|
68 |
def apply_enhancements(img, x, y, zoom, contrast, brightness, sharpness):
|
69 |
'''
|
@@ -89,13 +87,13 @@ def apply_enhancements(img, x, y, zoom, contrast, brightness, sharpness):
|
|
89 |
Returns:
|
90 |
-------
|
91 |
PIL.Image
|
92 |
-
Enhanced image.
|
93 |
'''
|
94 |
zoomed = zoom_at(img, x, y, zoom)
|
95 |
enhanced_contrast = ImageEnhance.Contrast(zoomed).enhance(contrast)
|
96 |
enhanced_brightness = ImageEnhance.Brightness(enhanced_contrast).enhance(brightness)
|
97 |
enhanced_sharpness = ImageEnhance.Sharpness(enhanced_brightness).enhance(sharpness)
|
98 |
-
return enhanced_sharpness
|
99 |
|
100 |
def create_zip(processed_img, description, params):
|
101 |
'''
|
@@ -115,9 +113,7 @@ def create_zip(processed_img, description, params):
|
|
115 |
bytes
|
116 |
Byte content of the zip file.
|
117 |
'''
|
118 |
-
# Create a temporary directory
|
119 |
with tempfile.TemporaryDirectory() as tmpdirname:
|
120 |
-
# Define file paths
|
121 |
img_path = os.path.join(tmpdirname, "processed_image.jpg")
|
122 |
desc_path = os.path.join(tmpdirname, "description.txt")
|
123 |
params_path = os.path.join(tmpdirname, "parameters.json")
|
@@ -132,7 +128,7 @@ def create_zip(processed_img, description, params):
|
|
132 |
# Save parameters
|
133 |
pd.DataFrame([params]).to_json(params_path, orient="records")
|
134 |
|
135 |
-
# Create
|
136 |
zip_buffer = io.BytesIO()
|
137 |
with zipfile.ZipFile(zip_buffer, "w") as zipf:
|
138 |
zipf.write(img_path, arcname="processed_image.jpg")
|
@@ -142,6 +138,7 @@ def create_zip(processed_img, description, params):
|
|
142 |
zip_buffer.seek(0)
|
143 |
return zip_buffer
|
144 |
|
|
|
145 |
st.set_page_config(page_title="CLL Explorer", layout="wide")
|
146 |
st.title("CLL Explorer: Cell Image Analysis Prep Tool")
|
147 |
|
@@ -163,7 +160,7 @@ if uploaded_files:
|
|
163 |
format_func=lambda x: uploaded_files[x].name
|
164 |
)
|
165 |
img_data = uploaded_files[img_index].read()
|
166 |
-
img = Image.open(io.BytesIO(img_data)).resize((500, 500))
|
167 |
|
168 |
# Create columns with image on the left and controls on the right
|
169 |
image_col, controls_col = st.columns([3, 1])
|
@@ -171,20 +168,20 @@ if uploaded_files:
|
|
171 |
with image_col:
|
172 |
st.subheader("Processed Image")
|
173 |
if 'processed_img' in st.session_state:
|
174 |
-
st.image(st.session_state.processed_img,
|
175 |
else:
|
176 |
-
st.image(img,
|
177 |
|
178 |
with controls_col:
|
179 |
st.subheader("Image Controls")
|
180 |
x = st.slider("X Coordinate", 0, 500, 250)
|
181 |
y = st.slider("Y Coordinate", 0, 500, 250)
|
182 |
-
zoom = st.slider("Zoom", 1, 10, 5)
|
183 |
|
184 |
with st.expander("Enhancement Settings", expanded=True):
|
185 |
-
contrast = st.slider("Contrast", 0.0, 5.0, 1.0)
|
186 |
-
brightness = st.slider("Brightness", 0.0, 5.0, 1.0)
|
187 |
-
sharpness = st.slider("Sharpness", 0.0, 2.0, 1.0)
|
188 |
|
189 |
if st.button("Apply Adjustments"):
|
190 |
processed_img = apply_enhancements(img, x, y, zoom, contrast, brightness, sharpness)
|
@@ -195,13 +192,12 @@ if uploaded_files:
|
|
195 |
|
196 |
# Display Original Image Below
|
197 |
st.subheader("Original Image")
|
198 |
-
st.image(img,
|
199 |
|
200 |
-
# Save Options
|
201 |
st.markdown("---")
|
202 |
st.subheader("Save and Export Options")
|
203 |
|
204 |
-
# Description and Parameters Inputs
|
205 |
with st.expander("Add Annotations", expanded=True):
|
206 |
description = st.text_area("Describe the image", "")
|
207 |
params = {
|
@@ -213,7 +209,6 @@ if uploaded_files:
|
|
213 |
"sharpness": sharpness
|
214 |
}
|
215 |
|
216 |
-
# Create a button to prepare the zip file
|
217 |
if st.button("Prepare Download"):
|
218 |
if 'processed_img' in st.session_state and description:
|
219 |
zip_buffer = create_zip(st.session_state.processed_img, description, params)
|
@@ -227,12 +222,13 @@ if uploaded_files:
|
|
227 |
else:
|
228 |
st.warning("Ensure that the processed image is available and description is provided.")
|
229 |
|
230 |
-
# Optional:
|
231 |
save_image = st.checkbox("Save Processed Image Locally")
|
232 |
if save_image:
|
233 |
if 'processed_img' in st.session_state:
|
234 |
-
|
235 |
-
st.
|
|
|
236 |
else:
|
237 |
st.warning("No processed image to save.")
|
238 |
|
@@ -240,13 +236,19 @@ if uploaded_files:
|
|
240 |
if st.button("Rename Files"):
|
241 |
if 'processed_img' in st.session_state:
|
242 |
file_ext = str(np.random.randint(100))
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
248 |
f.write(description)
|
249 |
-
|
250 |
-
st.success("Files renamed
|
251 |
else:
|
252 |
st.warning("No processed image to rename.")
|
|
|
52 |
Returns:
|
53 |
-------
|
54 |
PIL.Image
|
55 |
+
Zoomed image resized to 500x500 pixels.
|
|
|
|
|
|
|
|
|
|
|
56 |
'''
|
57 |
w, h = img.size
|
58 |
+
zoom_half = zoom / 2
|
59 |
+
left = max(x - w * zoom_half, 0)
|
60 |
+
upper = max(y - h * zoom_half, 0)
|
61 |
+
right = min(x + w * zoom_half, w)
|
62 |
+
lower = min(y + h * zoom_half, h)
|
63 |
+
img_cropped = img.crop((left, upper, right, lower))
|
64 |
+
return img_cropped.resize((500, 500), Image.LANCZOS)
|
65 |
|
66 |
def apply_enhancements(img, x, y, zoom, contrast, brightness, sharpness):
|
67 |
'''
|
|
|
87 |
Returns:
|
88 |
-------
|
89 |
PIL.Image
|
90 |
+
Enhanced image resized to 500x500 pixels.
|
91 |
'''
|
92 |
zoomed = zoom_at(img, x, y, zoom)
|
93 |
enhanced_contrast = ImageEnhance.Contrast(zoomed).enhance(contrast)
|
94 |
enhanced_brightness = ImageEnhance.Brightness(enhanced_contrast).enhance(brightness)
|
95 |
enhanced_sharpness = ImageEnhance.Sharpness(enhanced_brightness).enhance(sharpness)
|
96 |
+
return enhanced_sharpness.resize((500, 500), Image.LANCZOS)
|
97 |
|
98 |
def create_zip(processed_img, description, params):
|
99 |
'''
|
|
|
113 |
bytes
|
114 |
Byte content of the zip file.
|
115 |
'''
|
|
|
116 |
with tempfile.TemporaryDirectory() as tmpdirname:
|
|
|
117 |
img_path = os.path.join(tmpdirname, "processed_image.jpg")
|
118 |
desc_path = os.path.join(tmpdirname, "description.txt")
|
119 |
params_path = os.path.join(tmpdirname, "parameters.json")
|
|
|
128 |
# Save parameters
|
129 |
pd.DataFrame([params]).to_json(params_path, orient="records")
|
130 |
|
131 |
+
# Create zip
|
132 |
zip_buffer = io.BytesIO()
|
133 |
with zipfile.ZipFile(zip_buffer, "w") as zipf:
|
134 |
zipf.write(img_path, arcname="processed_image.jpg")
|
|
|
138 |
zip_buffer.seek(0)
|
139 |
return zip_buffer
|
140 |
|
141 |
+
# Streamlit App Configuration
|
142 |
st.set_page_config(page_title="CLL Explorer", layout="wide")
|
143 |
st.title("CLL Explorer: Cell Image Analysis Prep Tool")
|
144 |
|
|
|
160 |
format_func=lambda x: uploaded_files[x].name
|
161 |
)
|
162 |
img_data = uploaded_files[img_index].read()
|
163 |
+
img = Image.open(io.BytesIO(img_data)).convert("RGB").resize((500, 500))
|
164 |
|
165 |
# Create columns with image on the left and controls on the right
|
166 |
image_col, controls_col = st.columns([3, 1])
|
|
|
168 |
with image_col:
|
169 |
st.subheader("Processed Image")
|
170 |
if 'processed_img' in st.session_state:
|
171 |
+
st.image(st.session_state.processed_img, use_column_width=True, caption="Processed Image")
|
172 |
else:
|
173 |
+
st.image(img, use_column_width=True, caption="Processed Image")
|
174 |
|
175 |
with controls_col:
|
176 |
st.subheader("Image Controls")
|
177 |
x = st.slider("X Coordinate", 0, 500, 250)
|
178 |
y = st.slider("Y Coordinate", 0, 500, 250)
|
179 |
+
zoom = st.slider("Zoom", 1.0, 10.0, 5.0, step=0.1)
|
180 |
|
181 |
with st.expander("Enhancement Settings", expanded=True):
|
182 |
+
contrast = st.slider("Contrast", 0.0, 5.0, 1.0, step=0.1)
|
183 |
+
brightness = st.slider("Brightness", 0.0, 5.0, 1.0, step=0.1)
|
184 |
+
sharpness = st.slider("Sharpness", 0.0, 2.0, 1.0, step=0.1)
|
185 |
|
186 |
if st.button("Apply Adjustments"):
|
187 |
processed_img = apply_enhancements(img, x, y, zoom, contrast, brightness, sharpness)
|
|
|
192 |
|
193 |
# Display Original Image Below
|
194 |
st.subheader("Original Image")
|
195 |
+
st.image(img, use_column_width=True, caption="Original Image")
|
196 |
|
197 |
+
# Save and Export Options
|
198 |
st.markdown("---")
|
199 |
st.subheader("Save and Export Options")
|
200 |
|
|
|
201 |
with st.expander("Add Annotations", expanded=True):
|
202 |
description = st.text_area("Describe the image", "")
|
203 |
params = {
|
|
|
209 |
"sharpness": sharpness
|
210 |
}
|
211 |
|
|
|
212 |
if st.button("Prepare Download"):
|
213 |
if 'processed_img' in st.session_state and description:
|
214 |
zip_buffer = create_zip(st.session_state.processed_img, description, params)
|
|
|
222 |
else:
|
223 |
st.warning("Ensure that the processed image is available and description is provided.")
|
224 |
|
225 |
+
# Optional: Save Processed Image Locally
|
226 |
save_image = st.checkbox("Save Processed Image Locally")
|
227 |
if save_image:
|
228 |
if 'processed_img' in st.session_state:
|
229 |
+
processed_img_path = os.path.join("processed_image_500x500.jpg")
|
230 |
+
st.session_state.processed_img.save(processed_img_path)
|
231 |
+
st.success(f"Image saved as `{processed_img_path}`")
|
232 |
else:
|
233 |
st.warning("No processed image to save.")
|
234 |
|
|
|
236 |
if st.button("Rename Files"):
|
237 |
if 'processed_img' in st.session_state:
|
238 |
file_ext = str(np.random.randint(100))
|
239 |
+
new_img_name = f"img_processed_{file_ext}.jpg"
|
240 |
+
processed_img_path = "processed_image_500x500.jpg"
|
241 |
+
if os.path.exists(processed_img_path):
|
242 |
+
os.rename(processed_img_path, new_img_name)
|
243 |
+
|
244 |
+
# Save parameters and description
|
245 |
+
params_path = f"parameters_{file_ext}.json"
|
246 |
+
description_path = f"description_{file_ext}.txt"
|
247 |
+
|
248 |
+
pd.DataFrame([params]).to_json(params_path, orient="records")
|
249 |
+
with open(description_path, "w") as f:
|
250 |
f.write(description)
|
251 |
+
|
252 |
+
st.success(f"Files renamed to `{new_img_name}`, `{params_path}`, and `{description_path}`")
|
253 |
else:
|
254 |
st.warning("No processed image to rename.")
|