Spaces:
Sleeping
Sleeping
| ''' | |
| an image processing tool that allows users to upload microscope images, | |
| adjust the view with zoom and enhancement controls, and save the processed | |
| image along with annotations. The tool uses OpenCV for image processing and | |
| PIL for image enhancements. The processed image can be saved locally or | |
| exported as a zip file containing the processed image, description, and | |
| parameters. The tool also provides options to rename the processed image and | |
| associated files. | |
| The tool consists of the following components: | |
| 1. File Uploader: Allows users to upload microscope images in JPG or PNG format. | |
| 2. Image Controls: Provides sliders to adjust the zoom, contrast, brightness, and sharpness of the image. | |
| 3. Processed Image Display: Displays the processed image after applying the adjustments. | |
| 4. Original Image Display: Displays the original image uploaded by the user. | |
| 5. Save and Export Options: Allows users to add annotations, prepare a zip file for download, save the processed image locally, and rename the processed image and associated files. | |
| To run the tool: | |
| 1. Save the script as `cell_exp_past.py`. | |
| 2. Run the script in a Python environment. | |
| ```python | |
| streamlit run cell_exp_past.py | |
| ``` | |
| 3. Open the provided local URL in a web browser. | |
| 4. Upload microscope images and adjust the image view. | |
| 5. Apply adjustments and save the processed image with annotations. | |
| 6. Download the processed image and annotations as a zip file. | |
| 7. Save the processed image locally or rename the processed image and | |
| associated files. | |
| ''' | |
| import streamlit as st | |
| from PIL import Image, ImageEnhance | |
| import pandas as pd | |
| import numpy as np | |
| import io | |
| import os | |
| import tempfile | |
| import zipfile | |
| import json | |
| def zoom_at(img, x, y, zoom): | |
| ''' | |
| increase the zoom level of the image at a specific point (x, y). | |
| Parameters: | |
| img (PIL.Image): The input image. | |
| x (int): The x-coordinate of the point. | |
| y (int): The y-coordinate of the point. | |
| zoom (float): The zoom level. | |
| Returns: | |
| PIL.Image: The zoomed image. | |
| Examples: | |
| >>> img = Image.open('image.jpg') | |
| >>> zoomed_img = zoom_at(img, 100, 100, 2.0) | |
| ''' | |
| w, h = img.size | |
| zoom2 = zoom * 2 | |
| img = img.crop((x - w / zoom2, y - h / zoom2, | |
| x + w / zoom2, y + h / zoom2)) | |
| return img.resize((w, h), Image.LANCZOS) | |
| st.title("CLL Image Processing Tool") | |
| st.write('''This tool allows you to upload microscope images, | |
| adjust the view with zoom and enhancement controls, | |
| and save the processed image along with annotations. | |
| You can also export the processed image, description, | |
| and parameters as a zip file. | |
| ''') | |
| uploaded_files = st.file_uploader("Upload Images", accept_multiple_files=True, type="jpg") | |
| if uploaded_files: | |
| img_index = st.selectbox("Select Image", range(len(uploaded_files))) | |
| x = st.slider("X Coordinate", 0, 500, 205) | |
| y = st.slider("Y Coordinate", 0, 500, 250) | |
| zoom = st.slider("Zoom", 1.0, 10.0, 0.5) | |
| contrast = st.slider("Contrast", 0.0, 5.0, 1.0) | |
| brightness = st.slider("Brightness", 0.0, 5.0, 1.0) | |
| sharpness = st.slider("Sharpness", 0.0, 2.0, 1.0) | |
| save_image = st.checkbox("Save Image") | |
| img_data = uploaded_files[img_index].read() | |
| img = Image.open(io.BytesIO(img_data)).resize((500, 500)) | |
| img_zoomed = zoom_at(img, x, y, zoom) | |
| img_contrast = ImageEnhance.Contrast(img_zoomed).enhance(contrast) | |
| img_bright = ImageEnhance.Brightness(img_contrast).enhance(brightness) | |
| img_sharp = ImageEnhance.Sharpness(img_bright).enhance(sharpness) | |
| if save_image: | |
| processed_image_path = "image-processed.jpg" | |
| img_sharp.save(processed_image_path) | |
| st.session_state['processed_image_path'] = processed_image_path | |
| st.success(f"Image saved as {processed_image_path}") | |
| st.image(img_sharp, caption="Processed Image", use_container_width=True) | |
| description = st.text_area("Describe the image", "") | |
| if st.button("Save Description"): | |
| with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt') as f: | |
| f.write(description) | |
| desc_file = f.name | |
| st.session_state['desc_file'] = desc_file | |
| st.success("Description saved.") | |
| if st.button("Save Image Parameters"): | |
| params = { | |
| "coordinates_x": x, | |
| "coordinates_y": y, | |
| "zoom": zoom, | |
| "contrast": contrast, | |
| "brightness": brightness, | |
| "sharpness": sharpness | |
| } | |
| with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.json') as f: | |
| json.dump(params, f) | |
| params_file = f.name | |
| st.session_state['params_file'] = params_file | |
| st.success("Parameters saved.") | |
| if st.button("Rename Files"): | |
| file_ext = str(np.random.randint(100)) | |
| processed_image_path = st.session_state.get('processed_image_path', None) | |
| desc_file = st.session_state.get('desc_file', None) | |
| params_file = st.session_state.get('params_file', None) | |
| if processed_image_path and os.path.exists(processed_image_path): | |
| try: | |
| new_image_name = f"img_processed{file_ext}.jpg" | |
| os.rename(processed_image_path, new_image_name) | |
| st.session_state['processed_image_path'] = new_image_name # Update session state | |
| st.success(f"Image renamed to {new_image_name}") | |
| except FileNotFoundError: | |
| st.error(f"{processed_image_path} not found.") | |
| else: | |
| st.error("Processed image not found.") | |
| if params_file and os.path.exists(params_file): | |
| try: | |
| new_params_name = f"saved_image_parameters{file_ext}.json" | |
| os.rename(params_file, new_params_name) | |
| st.session_state['params_file'] = new_params_name # Update session state | |
| st.success(f"Parameters file renamed to {new_params_name}") | |
| except FileNotFoundError: | |
| st.error(f"{params_file} not found.") | |
| else: | |
| st.error("Saved image parameters file not found.") | |
| if desc_file and os.path.exists(desc_file): | |
| try: | |
| new_desc_name = f"saved_image_description{file_ext}.txt" | |
| os.rename(desc_file, new_desc_name) | |
| st.session_state['desc_file'] = new_desc_name # Update session state | |
| st.success(f"Description file renamed to {new_desc_name}") | |
| except FileNotFoundError: | |
| st.error(f"{desc_file} not found.") | |
| else: | |
| st.error("Saved image description file not found.") | |
| st.success("Files renamed successfully") | |
| if st.button("Export to ZIP"): | |
| desc_file = st.session_state.get('desc_file', None) | |
| params_file = st.session_state.get('params_file', None) | |
| processed_image_path = st.session_state.get('processed_image_path', None) | |
| with tempfile.NamedTemporaryFile(delete=False, suffix='.zip') as zipf: | |
| with zipfile.ZipFile(zipf.name, 'w') as z: | |
| files_added = False # Flag to check if any file is added | |
| if desc_file and os.path.exists(desc_file): | |
| z.write(desc_file, os.path.basename(desc_file)) | |
| files_added = True | |
| else: | |
| st.warning("Description file not found and was not added to the ZIP.") | |
| if params_file and os.path.exists(params_file): | |
| z.write(params_file, os.path.basename(params_file)) | |
| files_added = True | |
| else: | |
| st.warning("Parameters file not found and was not added to the ZIP.") | |
| if processed_image_path and os.path.exists(processed_image_path): | |
| z.write(processed_image_path, os.path.basename(processed_image_path)) | |
| files_added = True | |
| else: | |
| st.warning("Processed image not found and was not added to the ZIP.") | |
| # Check if the ZIP file has any content | |
| if os.path.getsize(zipf.name) > 0 and files_added: | |
| with open(zipf.name, 'rb') as f: | |
| st.download_button("Download ZIP", f, "annotations.zip") | |
| else: | |
| st.error("No files were added to the ZIP. Please ensure files are saved before exporting.") | |