{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":71549,"databundleVersionId":8561470,"sourceType":"competition"}],"dockerImageVersionId":30732,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport matplotlib.pyplot as plt\nimport cv2\nimport pydicom\nimport numpy as np\nimport os\nimport glob\nfrom tqdm import tqdm\nimport SimpleITK as sitk\nimport re\nfrom PIL import Image","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-07-02T00:58:34.960898Z","iopub.execute_input":"2024-07-02T00:58:34.961321Z","iopub.status.idle":"2024-07-02T00:58:36.354725Z","shell.execute_reply.started":"2024-07-02T00:58:34.961283Z","shell.execute_reply":"2024-07-02T00:58:36.353359Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# \ndef bias_field_correction(image):\n    corrector = sitk.N4BiasFieldCorrectionImageFilter()\n    image = sitk.Cast(image, sitk.sitkFloat32)  # Cast to float32\n    corrected_image = corrector.Execute(image)\n    return corrected_image    \n    \ndef z_score_normalization(image):\n    # Convert the image to an array\n    image_array = sitk.GetArrayFromImage(image)\n    \n    # Calclulate needed starts\n    mean = np.mean(image_array)\n    std = np.std(image_array)\n    \n    # Normalize the array and covert it back to an image\n    normalized_array = (image_array - mean) / std\n    normalized_image = sitk.GetImageFromArray(normalized_array)\n    normalized_image.CopyInformation(image)\n    return normalized_image    \n\ndef discretize_image(image, num_bins=32):\n    # \n    image_array = sitk.GetArrayFromImage(image)\n    min_val = np.min(image_array)\n    max_val = np.max(image_array)\n    bin_width = (max_val - min_val) / num_bins\n    discretized_array = np.floor((image_array - min_val) / bin_width).astype(np.int32)\n    discretized_array[discretized_array >= num_bins] = num_bins - 1\n    discretized_image = sitk.GetImageFromArray(discretized_array)\n    discretized_image.CopyInformation(image)\n    return discretized_image\n\ndef resize_image(image, new_size=(512, 512)):\n    resampler = sitk.ResampleImageFilter()\n    original_size = image.GetSize()\n    original_spacing = image.GetSpacing()\n    new_spacing = [\n        original_spacing[i] * (original_size[i] / new_size[i]) for i in range(2)\n    ]\n    \n    resampler.SetSize(new_size)\n    resampler.SetOutputSpacing(new_spacing)\n    resampler.SetOutputDirection(image.GetDirection())\n    resampler.SetOutputOrigin(image.GetOrigin())\n    resampler.SetTransform(sitk.Transform())\n    resampler.SetDefaultPixelValue(image.GetPixelIDValue())\n    resampler.SetInterpolator(sitk.sitkLinear)\n    \n    resized_image = resampler.Execute(image)\n    return resized_image\n\n\ndef resize_image_opencv(image, new_size=(512, 512)):\n    image_array = np.array(image)\n    resized_image_array = cv2.resize(image_array, new_size, interpolation=cv2.INTER_CUBIC)\n    resize_image = Image.fromarray(resized_image_array)\n    return image\n\ndef convert_to_png(image):\n    image_array = sitk.GetArrayFromImage(image)\n    image_array = (image_array - np.min(image_array)) / (np.max(image_array) - np.min(image_array) + 1e-6) * 255  # Normalize to 0-255\n\n    image_pil = Image.fromarray(image_array)\n    return image_pil\n    \ndef preprocess_mri_image(src_path, option):\n    dicom_data = pydicom.dcmread(src_path)\n    pixel_spacing = list(dicom_data.PixelSpacing) + [dicom_data.SliceThickness]\n    image = sitk.GetImageFromArray(dicom_data.pixel_array)\n    image.SetSpacing(pixel_spacing)\n\n    if option == 'dcm_to_png':\n        dcm_to_png_image = convert_to_png(image) \n        dcm_to_png_image = resize_image_opencv(dcm_to_png_image)\n        return dcm_to_png_image\n    \n    elif option == 'without_bias_correction':\n        wo_bias_image = z_score_normalization(image)\n        wo_bias_image = discretize_image(wo_bias_image)\n        wo_bias_image = convert_to_png(wo_bias_image)\n        wo_bias_image = resize_image_opencv(wo_bias_image)\n        return wo_bias_image\n    \n    else:\n        full_preprocessed_image = bias_field_correction(image)\n        full_preprocessed_image = z_score_normalization(full_preprocessed_image)\n        full_preprocessed_image = discretize_image(full_preprocessed_image)\n        full_preprocessed_image = convert_to_png(full_preprocessed_image)\n        full_preprocessed_image = resize_image_opencv(full_preprocessed_image)\n        return full_preprocessed_image\n\ndef imread_imsave(src_path, dst_path, option):\n    # Preprocess and save the image \n    image = preprocess_mri_image(src_path, option)\n    image_array = np.array(image)\n    cv2.imwrite(dst_path, image_array)\n    \n    ","metadata":{"execution":{"iopub.status.busy":"2024-07-02T00:58:38.736469Z","iopub.execute_input":"2024-07-02T00:58:38.736965Z","iopub.status.idle":"2024-07-02T00:58:38.755577Z","shell.execute_reply.started":"2024-07-02T00:58:38.736927Z","shell.execute_reply":"2024-07-02T00:58:38.754139Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Reading CSV\n","metadata":{}},{"cell_type":"code","source":"rd = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification'\n","metadata":{"execution":{"iopub.status.busy":"2024-07-02T00:58:44.795043Z","iopub.execute_input":"2024-07-02T00:58:44.795559Z","iopub.status.idle":"2024-07-02T00:58:44.800698Z","shell.execute_reply.started":"2024-07-02T00:58:44.795519Z","shell.execute_reply":"2024-07-02T00:58:44.799575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dfc = pd.read_csv(f'{rd}/train_label_coordinates.csv')","metadata":{"execution":{"iopub.status.busy":"2024-07-02T00:58:50.967926Z","iopub.execute_input":"2024-07-02T00:58:50.968328Z","iopub.status.idle":"2024-07-02T00:58:51.085849Z","shell.execute_reply.started":"2024-07-02T00:58:50.968294Z","shell.execute_reply":"2024-07-02T00:58:51.084546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(f'{rd}/train_series_descriptions.csv')\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2024-07-02T00:58:51.928546Z","iopub.execute_input":"2024-07-02T00:58:51.928945Z","iopub.status.idle":"2024-07-02T00:58:51.965092Z","shell.execute_reply.started":"2024-07-02T00:58:51.928914Z","shell.execute_reply":"2024-07-02T00:58:51.963853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['series_description'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2024-07-02T00:58:52.919415Z","iopub.execute_input":"2024-07-02T00:58:52.919824Z","iopub.status.idle":"2024-07-02T00:58:52.934826Z","shell.execute_reply.started":"2024-07-02T00:58:52.919793Z","shell.execute_reply":"2024-07-02T00:58:52.933518Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"st_ids = df['study_id'].unique()\nst_ids, len(st_ids)","metadata":{"execution":{"iopub.status.busy":"2024-07-02T00:58:53.779698Z","iopub.execute_input":"2024-07-02T00:58:53.780090Z","iopub.status.idle":"2024-07-02T00:58:53.790986Z","shell.execute_reply.started":"2024-07-02T00:58:53.780054Z","shell.execute_reply":"2024-07-02T00:58:53.789837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"desc = list(df['series_description'].unique())\ndesc","metadata":{"execution":{"iopub.status.busy":"2024-07-02T00:58:54.627705Z","iopub.execute_input":"2024-07-02T00:58:54.628111Z","iopub.status.idle":"2024-07-02T00:58:54.639187Z","shell.execute_reply.started":"2024-07-02T00:58:54.628079Z","shell.execute_reply":"2024-07-02T00:58:54.637283Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"process_option = ['dcm_to_png', 'without_bias_correction', 'full_preprocess']","metadata":{"execution":{"iopub.status.busy":"2024-07-02T00:58:55.394578Z","iopub.execute_input":"2024-07-02T00:58:55.394964Z","iopub.status.idle":"2024-07-02T00:58:55.399947Z","shell.execute_reply.started":"2024-07-02T00:58:55.394932Z","shell.execute_reply":"2024-07-02T00:58:55.398794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def atoi(text):\n    return int(text) if text.isdigit() else text\n\ndef natural_keys(text):\n    return [ atoi(c) for c in re.split(r'(\\d+)', text) ]\n","metadata":{"execution":{"iopub.status.busy":"2024-07-02T00:58:56.551264Z","iopub.execute_input":"2024-07-02T00:58:56.551683Z","iopub.status.idle":"2024-07-02T00:58:56.558159Z","shell.execute_reply.started":"2024-07-02T00:58:56.551649Z","shell.execute_reply":"2024-07-02T00:58:56.556763Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"option = \"without_bias_correction\"\n\nfor idx, st_id in enumerate(tqdm(st_ids, total=len(st_ids))):\n    rows = df[df['study_id']==st_id]\n    for ds in desc:\n        ds_ = ds.replace('/', '_')\n        rows_ = rows[rows['series_description']==ds]\n        dst_dir_path = f'{option}_cvt_png/{st_id}/{ds_}'\n        os.makedirs(dst_dir_path, exist_ok=True)\n        all_imgs = []\n        for i, row in rows_.iterrows():\n            imgs = glob.glob(f'{rd}/train_images/{row[\"study_id\"]}/{row[\"series_id\"]}/*.dcm')\n            imgs = sorted(imgs, key=natural_keys)\n            all_imgs.extend(imgs)\n            \n        if len(all_imgs) == 0:\n            print(f'{st_id} {ds_} has no images')\n            continue\n            \n        if ds == 'Axial T2':\n            for j, impath in enumerate(all_imgs):\n                dst_path = os.path.join(dst_dir_path, f'{j:03d}.png')\n                imread_imsave(impath, dst_path, option)\n            \n        elif ds == 'Sagittal T2/STIR':\n            step = len(all_imgs) / 10.0\n            st = len(all_imgs) / 2.0 - 4.0 * step\n            end = len(all_imgs) + 0.0001\n            for j, i in enumerate(np.arange(st, end, step)):\n                dst_path = os.path.join(dst_dir_path, f'{j:03d}.png')\n                ind2 = max(0, int((i- 0.5001).round()))\n                imread_imsave(all_imgs[ind2], dst_path, option)\n                \n            \n        elif ds == 'Sagittal T1':\n            step = len(all_imgs) / 10.0\n            st = len(all_imgs) / 2.0 - 4.0 * step\n            end = len(all_imgs) + 0.0001\n            for j, i in enumerate(np.arange(st, end, step)):\n                dst_path = os.path.join(dst_dir_path, f'{j:03d}.png')\n                ind2 = max(0, int((i- 0.5001).round()))\n                imread_imsave(all_imgs[ind2], dst_path, option)\n                                                 \n\n                    \n            \n            \n            \n            \n        \n    ","metadata":{"execution":{"iopub.status.busy":"2024-07-02T00:58:58.954837Z","iopub.execute_input":"2024-07-02T00:58:58.955225Z","iopub.status.idle":"2024-07-02T02:00:15.754902Z","shell.execute_reply.started":"2024-07-02T00:58:58.955195Z","shell.execute_reply":"2024-07-02T02:00:15.752743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}