Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| import plotly.graph_objects as go | |
| from mpl_toolkits.mplot3d import Axes3D | |
| from skimage import measure | |
| from mpl_toolkits.mplot3d.art3d import Poly3DCollection | |
| from lungmask import LMInferer | |
| import SimpleITK as sitk | |
| import os | |
| # --- Lung Segmentation Functions --- | |
| def process_dcm_file(file_path, inferer): | |
| """Loads a DCM file, performs lung segmentation, and returns the mask.""" | |
| input_image = sitk.ReadImage(file_path) | |
| segmentation = inferer.apply(input_image) | |
| newseg = segmentation.reshape(512, 512) # Assuming 512x512 images | |
| return newseg | |
| def segment_lungs_from_dicom(dcm_folder): | |
| """Segments lungs from DICOM files in a folder and returns a 3D volume.""" | |
| if not os.path.exists(dcm_folder) or not os.path.isdir(dcm_folder): | |
| raise ValueError("Invalid DICOM folder path.") | |
| inferer = LMInferer() | |
| segmentation_masks = [] | |
| for filename in os.listdir(dcm_folder): | |
| if filename.endswith(".dcm"): | |
| file_path = os.path.join(dcm_folder, filename) | |
| mask = process_dcm_file(file_path, inferer) | |
| segmentation_masks.append(mask) | |
| volume = np.stack(segmentation_masks, axis=0) | |
| return volume | |
| # --- 3D Visualization Function --- | |
| def plot_3d_lungs(lungs_volume, threshold=0.5): | |
| """Creates an interactive 3D plot of segmented lungs using Plotly (upright).""" | |
| verts, faces, normals, values = measure.marching_cubes(lungs_volume.transpose(2, 1, 0), threshold) | |
| # Apply rotation to make lungs upright | |
| # Assuming you want to rotate 90 degrees counter-clockwise around the X-axis | |
| rotation_angle_degrees = -90 | |
| rotation_angle_radians = np.radians(rotation_angle_degrees) | |
| rotation_matrix = np.array([[1, 0, 0], | |
| [0, np.cos(rotation_angle_radians), -np.sin(rotation_angle_radians)], | |
| [0, np.sin(rotation_angle_radians), np.cos(rotation_angle_radians)]]) | |
| rotated_verts = np.dot(verts, rotation_matrix) | |
| x, y, z = zip(*rotated_verts) # Use rotated vertices | |
| i, j, k = zip(*faces) | |
| mesh = go.Mesh3d(x=x, y=y, z=z, i=i, j=j, k=k, opacity=0.7, color='lightblue') | |
| fig = go.Figure(data=[mesh]) | |
| fig.update_layout(scene_aspectmode='data') # Maintain aspect ratio | |
| return fig | |
| # --- Create Gradio Interface --- | |
| inputs = gr.Textbox(label="DICOM Folder Path") | |
| output = gr.Plot(label="3D Segmented Lungs") | |
| iface = gr.Interface( | |
| fn=lambda dcm_folder: plot_3d_lungs(segment_lungs_from_dicom(dcm_folder)), | |
| inputs=inputs, | |
| outputs=output, | |
| title="3D Lung Segmentation Visualization", | |
| description="Visualize segmented lungs from DICOM images.", | |
| ) | |
| iface.launch() |