#!/usr/bin/env python # coding: utf-8 # In[2]: import streamlit as st from PIL import Image import numpy as np import os import pydicom as dicom import io import matplotlib.pyplot as plt from Segment_Stack_without_gpu import SegBScan, SegShrinkBScan # In[7]: st.set_page_config(layout="wide") def main(): selected_box = st.sidebar.selectbox( 'Choose one of the following', ('Welcome','LC-OCT image analysis') ) if selected_box == 'Welcome': welcome() if selected_box == 'LC-OCT image analysis': #selected_radio = st.sidebar.radio("Select analysis:", ["Visualisation", "Segmentation"]) #if selected_radio == "Visualisation": lcoct() def welcome(): st.title('3D Stack LCOCT images Visualisation and Processing') st.subheader("This app is designed to swiftly visualize and analyze LCOCT images, specifically focusing on segmentation." + " The application is currently in deployment, and additional tools will be incorporated in the future.") st.image('LCOCT_Stack.png',use_column_width=True) def lcoct(): st.title('Visualisation') allowed_extensions = ["dcm"] uploaded_files = st.file_uploader("Choose LCOCT files", type=allowed_extensions, accept_multiple_files=True) #file_contents = uploaded_file.read() # Display the contents count = 0 if uploaded_files: st.text("Uploaded LCOCT data:") for i, file in enumerate(uploaded_files): file_size = len(file.read()) #if (file_size//1024)>2000 : st.text(f"{i}, {file.name}") count+=1 #st.text(file_size) if uploaded_files: stack = st.slider('Which stack do you whant to visualize?', 0, count, 0) st.write("Current Selected Stack: ", stack) if uploaded_files: selected_file = uploaded_files[stack] data = dicom.dcmread(io.BytesIO(selected_file.getvalue())).pixel_array if data.ndim == 3 : data = data else : data = np.transpose(data[np.newaxis,...], (1,0,2)) selected_slice = st.slider("Select Slice", 0, data.shape[1] - 1, 0) selected_image_slice = data[:, selected_slice, :] st.image(selected_image_slice, caption=f"Slice {selected_slice}", use_column_width=True) save_directory1 = st.text_input("Enter the download directory path:", key="file_uploader1") # Button to save the current slice if st.button("Save Slice", key="save_button1"): #save_directory1 = st.file_uploader("Choose a directory to save the slice", type=["directory"], key="file_uploader1") # Check if the directory is selected if save_directory1 is not None: # Get the selected directory path directory_path = os.path.abspath(save_directory1) # Create the directory if it doesn't exist os.makedirs(directory_path, exist_ok=True) # Save the slice as an image using matplotlib with a custom filename and selected directory filename = f"dicom_slice_{selected_slice}.png" full_path = os.path.join(directory_path, filename) plt.imsave(full_path, selected_image_slice, cmap='gray') st.success(f"Slice {selected_slice} saved successfully.") else: st.warning("Please choose a directory to save the image.") #if st.button("Save Slice"): # plt.imsave(f"lcoct_slice_{selected_slice}.png", selected_image_slice, cmap='gray') # st.success(f"Slice {selected_slice} saved successfully.") if uploaded_files: selected_file = uploaded_files[stack] data = dicom.dcmread(io.BytesIO(selected_file.getvalue())).pixel_array if data.ndim == 3 : data = data else : data = np.transpose(data[np.newaxis,...], (1,0,2)) selected_slice = st.slider("Select Slice", 0, data.shape[0] - 1, 0) selected_image_slice = data[selected_slice, :, :] st.image(selected_image_slice, caption=f"Slice {selected_slice}", use_column_width=True) #save_directory2 = st.file_uploader("Choose a directory to save the slice", type=["directory"], key="file_uploader2") save_directory2 = st.text_input("Enter the download directory path:", key="file_uploader2") # Button to save the current slice if st.button("Save Slice", key="save_button2"): # Check if the directory is selected if save_directory2 is not None: # Get the selected directory path directory_path = os.path.abspath(save_directory2) # Create the directory if it doesn't exist os.makedirs(directory_path, exist_ok=True) # Save the slice as an image using matplotlib with a custom filename and selected directory filename = f"dicom_slice_{selected_slice}.png" full_path = os.path.join(directory_path, filename) plt.imsave(full_path, selected_image_slice, cmap='gray') st.success(f"Slice {selected_slice} saved successfully.") else: st.warning("Please choose a directory to save the image.") if uploaded_files: selected_file = uploaded_files[stack] data = dicom.dcmread(io.BytesIO(selected_file.getvalue())).pixel_array if data.ndim == 3 : data = data else : data = np.transpose(data[np.newaxis,...], (1,0,2)) selected_slice = st.slider("Select Slice", 0, data.shape[2] - 1, 0) selected_image_slice = data[:, :, selected_slice] st.image(selected_image_slice, caption=f"Slice {selected_slice}", use_column_width=True) #save_directory3 = st.file_uploader("Choose a directory to save the slice", type=["directory"], key="file_uploader3") save_directory3 = st.text_input("Enter the download directory path:", key="file_uploader3") # Button to save the current slice if st.button("Save Slice", key="save_button3"): # Check if the directory is selected if save_directory3 is not None: # Get the selected directory path directory_path = os.path.abspath(save_directory3) # Create the directory if it doesn't exist os.makedirs(directory_path, exist_ok=True) # Save the slice as an image using matplotlib with a custom filename and selected directory filename = f"dicom_slice_{selected_slice}.png" full_path = os.path.join(directory_path, filename) plt.imsave(full_path, selected_image_slice, cmap='gray') st.success(f"Slice {selected_slice} saved successfully.") else: st.warning("Please choose a directory to save the image.") ##################################Segmentation######################################## st.title('Segmentation of Stratum Corneum') st.write("This will take a few minitues ") @st.cache_data def segmentation(data1, remove1, disk1) : #if uploaded_files: result = SegBScan(data1, remove_num=remove1, disk_num=disk1) contours1, denoised_med1, epaiss1 = result.return_im_cont() epaiss1mean = result.sc_shrink() epaiss1std = result.image_std() return contours1, denoised_med1, epaiss1, epaiss1mean, epaiss1std @st.cache_data def segmentation1(data2, remove2, disk2): #if uploaded_files: result2 = SegShrinkBScan(data2, remove_num=remove2, disk_num=disk2) contours2, denoised_med2, epaiss2 = result2.return_im_cont() epaiss2mean = result2.sc_shrink() epaiss2std = result2.image_std() return contours2, denoised_med2, epaiss2, epaiss2mean, epaiss2std @st.cache_data def segmentation2(data1, disk1, disk2, octagon1, octagon2) : #if uploaded_files: result = SegBScan(data1, disk_num1 = disk1, disk_num2 = disk2, octagon_num1 = octagon1, octagon_num2 = octagon2) contours1, denoised_med1, epaiss1 = result.return_im_cont() epaiss1mean = result.sc_shrink() epaiss1std = result.image_std() return contours1, denoised_med1, epaiss1, epaiss1mean, epaiss1std @st.cache_data def segmentation3(data2, disk1, disk2, octagon1, octagon2): #if uploaded_files: result2 = SegShrinkBScan(data2, disk_num1 = disk1, disk_num2 = disk2, octagon_num1 = octagon1, octagon_num2 = octagon2) contours2, denoised_med2, epaiss2 = result2.return_im_cont() epaiss2mean = result2.sc_shrink() epaiss2std = result2.image_std() return contours2, denoised_med2, epaiss2, epaiss2mean, epaiss2std selected_box = st.sidebar.selectbox( 'Choose one of the following postprocessing', ('1st way','2nd way') ) if selected_box == '2nd way': st.text("This postprocessing uses morphology.remove_small_objects followed by morphology.dilatation") if uploaded_files: selected_remove = st.slider("Select the smallest allowable object size. Choosing a value will rerun the whole segmentation", 0, 500, 50, key='remove') selected_disk = st.slider("Select the radius of the disk-shaped footprint. Choosing a value will rerun the whole segmentation", 0, 10, 3, key='disk') contours, denoised_med, epaiss, epaiss_mean, epaiss_std = segmentation(data,selected_remove, selected_disk) denoised_med_get = denoised_med.copy() selected_slice = st.slider("Select Slice", 0, denoised_med.shape[1] - 1, 0) selected_image_slice = denoised_med_get[:, selected_slice,:] #st.image(selected_image_slice, caption=f"Slice {selected_slice}", use_column_width=True) fig, ax = plt.subplots() ax.imshow(selected_image_slice, cmap='gray') ax.set_title(f"Slice N°{selected_slice} ; Epaisseur du Stratum Corneum : {np.round(epaiss[selected_slice],3)}µm, (Epaisseur du stack {np.round(epaiss_mean,3)}µm +/- {np.round(epaiss_std,3)})", fontsize=6) ax.axis('off') for i in contours[selected_slice] : if (len(i)> 200): ax.plot(i[:,1],i[:,0]) st.pyplot(fig) if uploaded_files: selected_remove = st.slider("Select the smallest allowable object size. Choosing a value will rerun the whole segmentation", 0, 500, 50, key='remove2') selected_disk = st.slider("Select the radius of the disk-shaped footprint. Choosing a value will rerun the whole segmentation", 0, 10, 2, key='disk2') contours1, denoised_med1, epaiss1, epaiss_mean1, epaiss_std1 = segmentation1(data, selected_remove, selected_disk) denoised_med_get1 = denoised_med1.copy() selected_slice = st.slider("Select Slice", 0, denoised_med1.shape[2] - 1, 0, key =6) selected_image_slice = denoised_med_get1[:, :,selected_slice] #st.image(selected_image_slice, caption=f"Slice {selected_slice}", use_column_width=True) fig, ax = plt.subplots() ax.imshow(selected_image_slice, cmap='gray') ax.set_title(f"Slice N°{selected_slice} ; Epaisseur du Stratum Corneum : {np.round(epaiss1[selected_slice],3)}µm, (Epaisseur du stack {np.round(epaiss_mean1,3)}µm +/- {np.round(epaiss_std1,3)})", fontsize=6) ax.axis('off') for i in contours1[selected_slice] : if (len(i)> 200): ax.plot(i[:,1],i[:,0]) st.pyplot(fig) if selected_box == '1st way': st.text("This postprocessing uses morphology.erosion followed by dilation and binary.closing") if uploaded_files: selected_disk11 = st.slider("Select the radius of the disk-shaped footprint. Choosing a value will rerun the whole segmentation", 0, 10, 3, key='disk11') selected_disk12 = st.slider("Select the radius of the disk-shaped footprint. Choosing a value will rerun the whole segmentation", 0, 20, 0, key='disk12') st.text("Generates an octagon shaped footprint") selected_octagon1 = st.slider("The size of the horizontal and vertical sides. Choosing a value will rerun the whole segmentation", 0, 5, 0, key='octagon1') selected_octagon2 = st.slider("The height or width of the slanted sides. Choosing a value will rerun the whole segmentation", 0, 5, 1, key='octagon2') contours, denoised_med, epaiss, epaiss_mean, epaiss_std = segmentation2(data,selected_disk11, selected_disk12, selected_octagon1, selected_octagon2) denoised_med_get = denoised_med.copy() selected_slice = st.slider("Select Slice", 0, denoised_med.shape[1] - 1, 0) selected_image_slice = denoised_med_get[:, selected_slice,:] #st.image(selected_image_slice, caption=f"Slice {selected_slice}", use_column_width=True) fig, ax = plt.subplots() ax.imshow(selected_image_slice, cmap='gray') ax.set_title(f"Slice N°{selected_slice} ; Epaisseur du Stratum Corneum : {np.round(epaiss[selected_slice],3)}µm, (Epaisseur du stack {np.round(epaiss_mean,3)}µm +/- {np.round(epaiss_std,3)})", fontsize=6) ax.axis('off') for i in contours[selected_slice] : if (len(i)> 500): ax.plot(i[:,1],i[:,0]) st.pyplot(fig) if uploaded_files: selected_disk11 = st.slider("Select the radius of the disk-shaped footprint. Choosing a value will rerun the whole segmentation", 0, 10, 3, key='disk13') selected_disk12 = st.slider("Select the radius of the disk-shaped footprint. Choosing a value will rerun the whole segmentation", 0, 20, 0, key='disk14') st.text("Generates an octagon shaped footprint") selected_octagon1 = st.slider("The size of the horizontal and vertical sides. Choosing a value will rerun the whole segmentation", 0, 5, 0, key='octagon3') selected_octagon2 = st.slider("The height or width of the slanted sides. Choosing a value will rerun the whole segmentation", 0, 5, 1, key='octagon4') contours1, denoised_med1, epaiss1, epaiss_mean1, epaiss_std1 = segmentation3(data,selected_disk11, selected_disk12, selected_octagon1, selected_octagon2) denoised_med_get1 = denoised_med1.copy() selected_slice = st.slider("Select Slice", 0, denoised_med1.shape[2] - 1, 0, key =6) selected_image_slice = denoised_med_get1[:, :,selected_slice] #st.image(selected_image_slice, caption=f"Slice {selected_slice}", use_column_width=True) fig, ax = plt.subplots() ax.imshow(selected_image_slice, cmap='gray') ax.set_title(f"Slice N°{selected_slice} ; Epaisseur du Stratum Corneum : {np.round(epaiss1[selected_slice],3)}µm, (Epaisseur du stack {np.round(epaiss_mean1,3)}µm +/- {np.round(epaiss_std1,3)})", fontsize=6) ax.axis('off') for i in contours1[selected_slice] : if (len(i)> 200): ax.plot(i[:,1],i[:,0]) st.pyplot(fig) if __name__ == "__main__": main()