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.")
|