CoolFace
Apppublic

Tdanyim/Kspace_App

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
app.py279 linesDownload Raw Back to root
1import gradio as gr2import pydicom3import numpy as np4import matplotlib.pyplot as plt5 6# Image to K-space Conversion via FFT Functions & Vice-versa7def fft2c(image):8    """ Computes the centered 2D FFT of an image in NumPy. """9    return np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(image, axes=(-2, -1))), axes=(-2, -1))10 11def ifft2c(kspace):12    """ Computes the centered 2D IFFT of k-space data using NumPy. """13    return np.fft.ifftshift(np.fft.ifft2(np.fft.fftshift(kspace, axes=(-2, -1))), axes=(-2, -1))14 15# Function to process the DICOM file16def dicomMatrix(path, apply_rescale=True):17    ds = pydicom.dcmread(path)18    arr = ds.pixel_array.astype(np.float32)  # 2D for single-slice images19 20    # Apply HU/intensity rescale if present (common for CT)21    if apply_rescale and hasattr(ds, "RescaleSlope") and hasattr(ds, "RescaleIntercept"):22        arr = arr * float(ds.RescaleSlope) + float(ds.RescaleIntercept)23    return arr, ds24 25# Function to display the DICOM image26def show_dicom_image(dicom_file):27    # Load and process the DICOM file28    M, ds = dicomMatrix(dicom_file.name)29 30    # Display the DICOM image31    plt.figure(figsize=(8, 8))32    plt.imshow(M, cmap='gray')33    plt.title("DICOM Image")34    plt.axis("off")35 36    # Return the image plot as output37    return plt38 39# Function to create the low-pass filter40def createLowPass(shape, cutoff_radius):41    """ Create a 2D low-pass filter mask based on the cutoff radius. """42    y, x = np.indices(shape)43    center = np.array(shape) // 244    dist_sq = (x - center[1])**2 + (y - center[0])**245    lowPassFilter = np.where(dist_sq <= cutoff_radius**2, 1, 0)46    return lowPassFilter47 48# Low-pass filter function49def lowFilter(MRIsam, cutoff_radius):50    """Computes the 2D FFT, applies a low-pass filter, and reconstructs the image."""51    lowPassFilter = createLowPass(MRIsam.shape, cutoff_radius)52    kspMRI = fft2c(MRIsam)53    kspMRI_L = kspMRI * lowPassFilter54    spaMRI_L = np.abs(ifft2c(kspMRI_L))55    return kspMRI, kspMRI_L, spaMRI_L56 57# High-pass filter function58def highFilter(MRIsam, cutoff_radius):59    """Computes the 2D FFT, applies a high-pass filter, and reconstructs the image."""60    lowPassFilter = createLowPass(MRIsam.shape, cutoff_radius)61    highPassFilter = 1 - lowPassFilter62    kspMRI = fft2c(MRIsam)63    kspMRI_H = kspMRI * highPassFilter64    spaMRI_H = np.abs(ifft2c(kspMRI_H))65    return kspMRI, kspMRI_H, spaMRI_H66 67# Function to apply the undersampling mask to the k-space data68def undersample(kspace: np.ndarray, factor: int, compress: bool):69    """ Skipping every nth kspace line, starting from the midline.70    Simulates acquiring every nth (where n is the acceleration factor) line71    of kspace, common in SENSE algorithm.72    73    Parameters:74        kspace: Complex k-space numpy.ndarray75        factor: Only scan every nth line (n=factor) starting from midline76        compress: compress kspace by removing empty lines (rectangular FOV)77    """78    if factor > 1:79        mask = np.ones(kspace.shape, dtype=bool)80        midline = kspace.shape[0] // 281        mask[midline::factor] = 082        mask[midline::-factor] = 083 84        if compress:85            # Remove empty lines and compress86            q = kspace[~mask]87            q = q.reshape(q.size // kspace.shape[1], kspace.shape[1])88            kspace[:] = q[:]89        else:90            kspace[mask] = 091    return kspace92 93# Function to convert to k-space and apply undersampling94def undersampling_function(dicom_file, undersampling_factor, compress=False):95    # Load and process the DICOM file96    M, ds = dicomMatrix(dicom_file.name)97 98    # Perform K-space conversion99    kspMRI = fft2c(M)100 101    # Apply undersampling102    kspMRI_us = undersample(kspMRI.copy(), undersampling_factor, compress)103    spaMRI_us = np.abs(ifft2c(kspMRI_us))104 105    # Plot the original k-space, image, undersampled k-space, and undersampled image106    fig, axs = plt.subplots(1, 4, figsize=(20, 6))107 108    # Original Image109    axs[0].imshow(M, cmap='gray')110    axs[0].set_title("Original Image")111    axs[0].axis("off")112 113    # Original K-space (Magnitude)114    axs[1].imshow(np.log(np.abs(kspMRI) + 1e-9), cmap='gray')115    axs[1].set_title("Original K-space")116    axs[1].axis("off")117 118    # Undersampled K-space (Magnitude)119    axs[2].imshow(np.log(np.abs(kspMRI_us) + 1e-9), cmap='gray')120    axs[2].set_title(f"Undersampled K-space (R={undersampling_factor})")121    axs[2].axis("off")122 123    # Reconstructed Image from Undersampled K-space124    axs[3].imshow(spaMRI_us, cmap='gray')125    axs[3].set_title("Undersampled Image")126    axs[3].axis("off")127 128    plt.tight_layout()129    return fig130 131# Function to convert to k-space and plot the K-space visualization132def convert_to_kspace_and_plot(dicom_file):133    # Load and process the DICOM file134    M, ds = dicomMatrix(dicom_file.name)135 136    # Perform the K-space conversion137    kspMRI = fft2c(M)138    spaMRI = np.abs(ifft2c(kspMRI))139 140    # Plot original image, k-space, and reconstructed image141    fig, axs = plt.subplots(1, 3, figsize=(20, 6))142 143    # Original Image144    axs[0].imshow(M, cmap='gray')145    axs[0].set_title("Original Image")146    axs[0].axis("off")147 148    # K-space (Magnitude)149    axs[1].imshow(np.log(np.abs(kspMRI) + 1e-9), cmap='gray')150    axs[1].set_title("K-space (Original)")151    axs[1].axis("off")152 153    # Reconstructed Image from K-space154    axs[2].imshow(spaMRI, cmap='gray')155    axs[2].set_title("Reconstructed Image")156    axs[2].axis("off")157 158    plt.tight_layout()159    return fig160 161# Function to apply the filter (low-pass or high-pass) to K-space and plot162def convert_to_kspace_with_filter(dicom_file, filter_type, cutoff_radius):163    # Load and process the DICOM file164    M, ds = dicomMatrix(dicom_file.name)165 166    # Apply either low-pass or high-pass filtering based on user selection167    if filter_type == "Low-pass":168        kspMRI, kspMRI_L, spaMRI_L = lowFilter(M, cutoff_radius)169    elif filter_type == "High-pass":170        kspMRI, kspMRI_H, spaMRI_H = highFilter(M, cutoff_radius)171 172    # Plot original image, k-space, filtered k-space, and reconstructed image173    fig, axs = plt.subplots(1, 4, figsize=(20, 6))174 175    # Original Image176    axs[0].imshow(M, cmap='gray')177    axs[0].set_title("Original Image")178    axs[0].axis("off")179 180    # Original K-space (Magnitude)181    axs[1].imshow(np.log(np.abs(kspMRI) + 1e-9), cmap='gray')182    axs[1].set_title("K-space (Original)")183    axs[1].axis("off")184 185    # Filtered K-space (Magnitude)186    if filter_type == "Low-pass":187        axs[2].imshow(np.log(np.abs(kspMRI_L) + 1e-9), cmap='gray')188        axs[2].set_title(f"K-space ({filter_type} Filtered)")189    elif filter_type == "High-pass":190        axs[2].imshow(np.log(np.abs(kspMRI_H) + 1e-9), cmap='gray')191        axs[2].set_title(f"K-space ({filter_type} Filtered)")192    axs[2].axis("off")193 194    # Reconstructed Image from Filtered K-space195    if filter_type == "Low-pass":196        axs[3].imshow(spaMRI_L, cmap='gray')197        axs[3].set_title(f"Image ({filter_type} Reconstructed)")198    elif filter_type == "High-pass":199        axs[3].imshow(spaMRI_H, cmap='gray')200        axs[3].set_title(f"Image ({filter_type} Reconstructed)")201    axs[3].axis("off")202 203    plt.tight_layout()204    return fig205 206# Build the Gradio interface with improved aesthetics and navigation207def build_dicom_interface():208    with gr.Blocks() as demo:209        gr.Markdown("""210        # ๐Ÿง  MRI Processing Tool ๐Ÿง‘โ€๐Ÿ”ฌ211        Welcome to the MRI processing interface! 212        Use the tabs below to upload a DICOM file and explore different MRI processing features:213        - **MRI Visualization** ๐Ÿ“ท214        - **K-space Conversion** โš™๏ธ215        - **Filtering** ๐Ÿงฐ216        - **Undersampling** ๐Ÿฉป217        """)218 219        with gr.Tab("MRI Visualization ๐Ÿ“ท"):220            with gr.Row():221                dicom_input = gr.File(label="Upload DICOM File")222                example_button = gr.Button("๐Ÿ’ก Use Example DICOM File", variant="primary")223 224            with gr.Row():225                show_image_button = gr.Button("Show Image")226 227            with gr.Row():228                image_output = gr.Plot(label="DICOM Image Visualization")229 230            example_button.click(fn=lambda: "13660", inputs=[], outputs=[dicom_input])231            show_image_button.click(fn=show_dicom_image, inputs=dicom_input, outputs=image_output)232 233        with gr.Tab("K-space Conversion โš™๏ธ"):234            with gr.Row():235                view_kspace_button = gr.Button("View K-space Conversion")236 237            with gr.Row():238                kspace_output = gr.Plot(label="K-space and Reconstructed Image")239 240            view_kspace_button.click(fn=convert_to_kspace_and_plot, inputs=dicom_input, outputs=kspace_output)241 242        with gr.Tab("Filtering ๐Ÿงฐ"):243            with gr.Row():244                filter_type = gr.Radio(["Low-pass", "High-pass"], value="Low-pass", label="Select Filter Type")245                cutoff_radius_slider = gr.Slider(minimum=0, maximum=50, step=1, value=10, label="Cut-off Radius")246 247            with gr.Row():248                convert_button = gr.Button("Convert to K-space with Filtering")249 250            with gr.Row():251                filter_output = gr.Plot(label="Filtered K-space and Reconstructed Image")252 253            convert_button.click(fn=convert_to_kspace_with_filter, inputs=[dicom_input, filter_type, cutoff_radius_slider], outputs=filter_output)254 255        with gr.Tab("Undersampling ๐Ÿฉป"):256            with gr.Row():257                undersampling_factor_slider = gr.Slider(minimum=1, maximum=10, step=1, value=2, label="Undersampling Factor")258 259            with gr.Row():260                undersample_button = gr.Button("Apply Undersampling")261 262            with gr.Row():263                undersample_output = gr.Plot(label="Undersampled K-space and Image")264 265            undersample_button.click(fn=undersampling_function, inputs=[dicom_input, undersampling_factor_slider], outputs=undersample_output)266        267        # Corrected link placement at the bottom, outside of the tabs268        with gr.Row():269            gr.Markdown("""270            ---271            ## For a detailed tutorial and more code examples:272            [Explore the Jupyter Notebook Tutorial](https://www.kaggle.com/code/danieltweneboaha/imageformation)273            """)274            275    return demo276 277# Launch the interface278demo = build_dicom_interface()279demo.launch(share=True)