Skier8402 commited on
Commit
895e0c3
·
verified ·
1 Parent(s): 8993b69

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -250
app.py CHANGED
@@ -1,229 +1,51 @@
1
- '''
2
- This is the originall CLL Explorer application that allows users to upload, process, and save images.
3
-
4
- The application provides the following functionalities:
5
- - Upload microscope images.
6
- - Adjust image view with zoom and enhancement controls.
7
- - Detect and measure cells automatically.
8
- - Save analysis results and annotations.
9
-
10
- The application is divided into the following sections:
11
- 1. **Upload Images**: Users can upload microscope images in JPG or PNG format.
12
- 2. **Select Image**: Users can select an image from the uploaded files.
13
- 3. **Processed Image**: Displays the processed image with zoom and enhancement controls.
14
- 4. **Image Controls**: Allows users to adjust the image view with sliders for X and Y coordinates, zoom, contrast, brightness, and sharpness.
15
- 5. **Save Options**: Provides options to save the processed image, image description, and image parameters.
16
-
17
- To run the application:
18
- 1. Save the script in a Python file (e.g., app.py).
19
- 2. Run the script using the Streamlit command:
20
- ```bash
21
- streamlit run app.py
22
-
23
- '''
24
-
25
  import streamlit as st
26
  from PIL import Image, ImageEnhance
27
  import pandas as pd
28
  import numpy as np
29
  import io
30
  import os
31
- import tempfile
32
- import zipfile
33
- import cv2
34
- import numpy as np
35
 
36
  def zoom_at(img, x, y, zoom):
37
- '''
38
- Zoom into an image at a specific location.
39
-
40
- Parameters:
41
- ----------
42
- img : PIL.Image
43
- Input image.
44
-
45
- x : int
46
- X-coordinate of the zoom center.
47
-
48
- y : int
49
- Y-coordinate of the zoom center.
50
-
51
- zoom : float
52
- Zoom factor.
53
-
54
- Returns:
55
- -------
56
- PIL.Image
57
- Zoomed image resized to 500x500 pixels.
58
- '''
59
  w, h = img.size
60
- zoom_half = zoom / 2
61
- left = max(x - w * zoom_half, 0)
62
- upper = max(y - h * zoom_half, 0)
63
- right = min(x + w * zoom_half, w)
64
- lower = min(y + h * zoom_half, h)
65
- img_cropped = img.crop((left, upper, right, lower))
66
- return img_cropped.resize((500, 500), Image.LANCZOS)
67
-
68
- @st.cache_data
69
- def apply_enhancements(img, x, y, zoom, contrast, brightness, sharpness):
70
- '''
71
- Apply zoom and image enhancements to the input image.
72
-
73
- Parameters:
74
- ----------
75
- img : PIL.Image
76
- Input image.
77
- x : int
78
- X-coordinate of the zoom center.
79
- y : int
80
- Y-coordinate of the zoom center.
81
- zoom : float
82
- Zoom factor.
83
- contrast : float
84
- Contrast adjustment factor.
85
- brightness : float
86
- Brightness adjustment factor.
87
- sharpness : float
88
- Sharpness adjustment factor.
89
-
90
- Returns:
91
- -------
92
- PIL.Image
93
- Enhanced image resized to 500x500 pixels.
94
- '''
95
- zoomed = zoom_at(img, x, y, zoom)
96
- enhanced_contrast = ImageEnhance.Contrast(zoomed).enhance(contrast)
97
- enhanced_brightness = ImageEnhance.Brightness(enhanced_contrast).enhance(brightness)
98
- enhanced_sharpness = ImageEnhance.Sharpness(enhanced_brightness).enhance(sharpness)
99
- return enhanced_sharpness
100
-
101
- def apply_enhancements_cv(img, x, y, zoom, contrast, brightness, sharpness):
102
- """
103
- Use OpenCV for zoom and enhancements.
104
- """
105
- # Convert PIL to OpenCV format
106
- img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
107
- h, w = img_cv.shape[:2]
108
-
109
- # Zoom
110
- zoom_half = int(zoom / 2)
111
- left = max(x - w * zoom_half, 0)
112
- top = max(y - h * zoom_half, 0)
113
- right = min(x + w * zoom_half, w)
114
- bottom = min(y + h * zoom_half, h)
115
- cropped = img_cv[int(top):int(bottom), int(left):int(right)]
116
- resized = cv2.resize(cropped, (500, 500), interpolation=cv2.INTER_LANCZOS4)
117
-
118
- # Convert back to PIL for other enhancements
119
- pil_img = Image.fromarray(cv2.cvtColor(resized, cv2.COLOR_BGR2RGB))
120
- enhanced_contrast = ImageEnhance.Contrast(pil_img).enhance(contrast)
121
- enhanced_brightness = ImageEnhance.Brightness(enhanced_contrast).enhance(brightness)
122
- enhanced_sharpness = ImageEnhance.Sharpness(enhanced_brightness).enhance(sharpness)
123
- return enhanced_sharpness
124
-
125
- def create_zip(processed_img, description, params):
126
- '''
127
- Create a zip archive containing the processed image and annotations.
128
-
129
- Parameters:
130
- ----------
131
- processed_img : PIL.Image
132
- The processed image.
133
- description : str
134
- Description of the image.
135
- params : dict
136
- Image parameters.
137
-
138
- Returns:
139
- -------
140
- bytes
141
- Byte content of the zip file.
142
- '''
143
- with tempfile.TemporaryDirectory() as tmpdirname:
144
- img_path = os.path.join(tmpdirname, "processed_image.jpg")
145
- desc_path = os.path.join(tmpdirname, "description.txt")
146
- params_path = os.path.join(tmpdirname, "parameters.json")
147
 
148
- # Save processed image
149
- processed_img.save(img_path)
150
 
151
- # Save description
152
- with open(desc_path, "w") as f:
153
- f.write(description)
154
-
155
- # Save parameters
156
- pd.DataFrame([params]).to_json(params_path, orient="records")
157
-
158
- # Create zip
159
- zip_buffer = io.BytesIO()
160
- with zipfile.ZipFile(zip_buffer, "w") as zipf:
161
- zipf.write(img_path, arcname="processed_image.jpg")
162
- zipf.write(desc_path, arcname="description.txt")
163
- zipf.write(params_path, arcname="parameters.json")
164
-
165
- zip_buffer.seek(0)
166
- return zip_buffer
167
-
168
- # Streamlit App Configuration
169
- st.set_page_config(page_title="CLL Explorer", layout="wide")
170
- st.title("CLL Explorer: Cell Image Analysis Prep Tool")
171
-
172
- st.markdown("""
173
- ### About This Application
174
- This tool assists researchers in analyzing microscope images of any cell type.
175
- - **Upload** microscope images.
176
- - **Adjust** image view with zoom and enhancement controls.
177
- - **Detect** and measure cells automatically.
178
- - **Save** analysis results and annotations.
179
- """)
180
-
181
- uploaded_files = st.file_uploader("Upload Images", accept_multiple_files=True, type=["jpg", "png"])
182
 
183
  if uploaded_files:
184
- img_index = st.selectbox(
185
- "Select Image",
186
- range(len(uploaded_files)),
187
- format_func=lambda x: uploaded_files[x].name
188
- )
189
- img_data = uploaded_files[img_index].read()
190
- img = Image.open(io.BytesIO(img_data)).convert("RGB").resize((500, 500))
191
-
192
- # Create columns with image on the left and controls on the right
193
- image_col, controls_col = st.columns([3, 1])
194
-
195
- with image_col:
196
- st.subheader("Processed Image")
197
- if 'processed_img' in st.session_state:
198
- st.image(st.session_state.processed_img, use_container_width=True, caption="Processed Image")
199
- else:
200
- st.image(img, use_container_width=True, caption="Processed Image")
201
 
202
- with controls_col:
203
- st.subheader("Image Controls")
204
- x = st.slider("X Coordinate", 0, 500, 250)
205
- y = st.slider("Y Coordinate", 0, 500, 250)
206
- zoom = st.slider("Zoom", 1.0, 10.0, 5.0, step=0.1)
207
-
208
- with st.expander("Enhancement Settings", expanded=True):
209
- contrast = st.slider("Contrast", 0.0, 5.0, 1.0, step=0.1)
210
- brightness = st.slider("Brightness", 0.0, 5.0, 1.0, step=0.1)
211
- sharpness = st.slider("Sharpness", 0.0, 2.0, 1.0, step=0.1)
212
 
213
- if st.button("Apply Adjustments"):
214
- processed_img = apply_enhancements(img, x, y, zoom, contrast, brightness, sharpness)
215
- st.session_state.processed_img = processed_img
216
 
217
- # Display Original Image Below
218
- st.subheader("Original Image")
219
- st.image(img, use_container_width=True, caption="Original Image")
220
 
221
- # Save and Export Options
222
- st.markdown("---")
223
- st.subheader("Save and Export Options")
 
 
224
 
225
- with st.expander("Add Annotations", expanded=True):
226
- description = st.text_area("Describe the image", "")
227
  params = {
228
  "coordinates_x": x,
229
  "coordinates_y": y,
@@ -232,47 +54,13 @@ if uploaded_files:
232
  "brightness": brightness,
233
  "sharpness": sharpness
234
  }
 
 
 
235
 
236
- if st.button("Prepare Download"):
237
- if 'processed_img' in st.session_state and description:
238
- zip_buffer = create_zip(st.session_state.processed_img, description, params)
239
- st.download_button(
240
- label="Download Zip",
241
- data=zip_buffer,
242
- file_name="processed_image_and_annotations.zip",
243
- mime="application/zip"
244
- )
245
- st.success("Zip file is ready for download.")
246
- else:
247
- st.warning("Ensure that the processed image is available and description is provided.")
248
-
249
- # Optional: Save Processed Image Locally
250
- save_image = st.checkbox("Save Processed Image Locally")
251
- if save_image:
252
- if 'processed_img' in st.session_state:
253
- processed_img_path = os.path.join("processed_image_500x500.jpg")
254
- st.session_state.processed_img.save(processed_img_path)
255
- st.success(f"Image saved as `{processed_img_path}`")
256
- else:
257
- st.warning("No processed image to save.")
258
-
259
- # Optional: Rename Files
260
  if st.button("Rename Files"):
261
- if 'processed_img' in st.session_state:
262
- file_ext = str(np.random.randint(100))
263
- new_img_name = f"img_processed_{file_ext}.jpg"
264
- processed_img_path = "processed_image_500x500.jpg"
265
- if os.path.exists(processed_img_path):
266
- os.rename(processed_img_path, new_img_name)
267
-
268
- # Save parameters and description
269
- params_path = f"parameters_{file_ext}.json"
270
- description_path = f"description_{file_ext}.txt"
271
-
272
- pd.DataFrame([params]).to_json(params_path, orient="records")
273
- with open(description_path, "w") as f:
274
- f.write(description)
275
-
276
- st.success(f"Files renamed to `{new_img_name}`, `{params_path}`, and `{description_path}`")
277
- else:
278
- st.warning("No processed image to rename.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
  from PIL import Image, ImageEnhance
3
  import pandas as pd
4
  import numpy as np
5
  import io
6
  import os
 
 
 
 
7
 
8
  def zoom_at(img, x, y, zoom):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  w, h = img.size
10
+ zoom2 = zoom * 2
11
+ img = img.crop((x - w / zoom2, y - h / zoom2,
12
+ x + w / zoom2, y + h / zoom2))
13
+ return img.resize((w, h), Image.LANCZOS)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
+ st.title("Cell Explorer")
 
16
 
17
+ uploaded_files = st.file_uploader("Upload Images", accept_multiple_files=True, type="jpg")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  if uploaded_files:
20
+ img_index = st.selectbox("Select Image", range(len(uploaded_files)))
21
+ x = st.slider("X Coordinate", 0, 500, 205)
22
+ y = st.slider("Y Coordinate", 0, 500, 250)
23
+ zoom = st.slider("Zoom", 1, 10, 5)
24
+ contrast = st.slider("Contrast", 0.0, 5.0, 1.0)
25
+ brightness = st.slider("Brightness", 0.0, 5.0, 1.0)
26
+ sharpness = st.slider("Sharpness", 0.0, 2.0, 1.0)
27
+ save_image = st.checkbox("Save Image")
 
 
 
 
 
 
 
 
 
28
 
29
+ img_data = uploaded_files[img_index].read()
30
+ img = Image.open(io.BytesIO(img_data)).resize((500, 500))
31
+ img_zoomed = zoom_at(img, x, y, zoom)
32
+ img_contrast = ImageEnhance.Contrast(img_zoomed).enhance(contrast)
33
+ img_bright = ImageEnhance.Brightness(img_contrast).enhance(brightness)
34
+ img_sharp = ImageEnhance.Sharpness(img_bright).enhance(sharpness)
 
 
 
 
35
 
36
+ if save_image:
37
+ img_sharp.save("image-processed.jpg")
38
+ st.success("Image saved as image-processed.jpg")
39
 
40
+ st.image(img_sharp, caption="Processed Image", use_column_width=True)
 
 
41
 
42
+ description = st.text_area("Describe the image", "")
43
+ if st.button("Save Description"):
44
+ with open("saved_image_description.txt", "w") as f:
45
+ f.write(description)
46
+ st.success("Description saved as saved_image_description.txt")
47
 
48
+ if st.button("Save Image Parameters"):
 
49
  params = {
50
  "coordinates_x": x,
51
  "coordinates_y": y,
 
54
  "brightness": brightness,
55
  "sharpness": sharpness
56
  }
57
+ with open("saved_image_parameters.json", "w") as f:
58
+ f.write(pd.DataFrame([params]).to_json(orient="records"))
59
+ st.success("Image parameters saved as saved_image_parameters.json")
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  if st.button("Rename Files"):
62
+ file_ext = str(np.random.randint(100))
63
+ os.rename("image-processed.jpg", f"img_processed{file_ext}.jpg")
64
+ os.rename("saved_image_parameters.json", f"saved_image_parameters{file_ext}.json")
65
+ os.rename("saved_image_description.txt", f"saved_image_description{file_ext}.txt")
66
+ st.success("Files renamed successfully")