import gradio as gr import numpy as np import polars as pl import pydicom from PIL import Image def read_and_preprocess_dicom(file_path: str): """ Function to read and preprocess DICOM files :param file_path: Path to the DICOM file :return: Image data (in PIL format) and metadata (in pandas DataFrame format) """ # Read the DICOM file dicom_data = pydicom.dcmread(file_path) # Get the pixel data pixel_array = dicom_data.pixel_array # Normalize the pixel data to 8-bit and convert to a PIL image if pixel_array.dtype != np.uint8: pixel_array = ((pixel_array - np.min(pixel_array)) / (np.max(pixel_array) - np.min(pixel_array)) * 255).astype( np.uint8) image = Image.fromarray(pixel_array) # Collect metadata in dictionary format and convert to DataFrame metadata_dict = {elem.name: str(elem.value) for elem in dicom_data.iterall() if elem.name != 'Pixel Data'} df_metadata = pl.DataFrame({ "Key": list(metadata_dict.keys()), "Value": list(metadata_dict.values()) }) return image, df_metadata.to_pandas() # Convert to pandas DataFrame for Gradio compatibility def build_interface(): """ Function to build the Gradio interface """ theme = gr.themes.Soft( primary_hue=gr.themes.colors.emerald, secondary_hue=gr.themes.colors.emerald ) with gr.Blocks(title='DICOM Viewer', theme=theme) as demo: gr.Markdown( """ # DICOM Viewer This app reads a DICOM file and displays the image and metadata. """ ) with gr.Column(): file_path = gr.File(label="Input DICOM Data") with gr.Row(): dicom_image = gr.Image(type="pil", label="DICOM Image") dicom_meta = gr.Dataframe(headers=None, label="Metadata") inputs = [file_path] outputs = [dicom_image, dicom_meta] file_path.upload(fn=read_and_preprocess_dicom, inputs=inputs, outputs=outputs) clear_button = gr.ClearButton(components=inputs + outputs, ) return demo if __name__ == '__main__': demo = build_interface() demo.launch()