{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Setting ##","metadata":{}},{"cell_type":"code","source":"!pip install -qU python-gdcm pydicom pylibjpeg\n!pip install -U pylibjpeg-libjpeg -v\n!pip install pylibjpeg pylibjpeg-libjpeg pylibjpeg-openjpeg\n!pip install pydicom","metadata":{"execution":{"iopub.status.busy":"2023-02-16T12:29:59.305512Z","iopub.execute_input":"2023-02-16T12:29:59.30602Z","iopub.status.idle":"2023-02-16T12:31:02.925687Z","shell.execute_reply.started":"2023-02-16T12:29:59.305983Z","shell.execute_reply":"2023-02-16T12:31:02.923792Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Import Lib ##","metadata":{}},{"cell_type":"code","source":"import os\nimport cv2\nimport glob\nimport gdcm\n\nimport pydicom\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nimport json\n\nfrom tqdm.notebook import tqdm\nfrom joblib import Parallel, delayed","metadata":{"execution":{"iopub.status.busy":"2023-02-16T12:31:02.929904Z","iopub.execute_input":"2023-02-16T12:31:02.930476Z","iopub.status.idle":"2023-02-16T12:31:04.108819Z","shell.execute_reply.started":"2023-02-16T12:31:02.930421Z","shell.execute_reply":"2023-02-16T12:31:04.107099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_images = glob.glob(\"/kaggle/input/rsna-breast-cancer-detection/train_images/*/*.dcm\")\nlen(train_images)  # 54706","metadata":{"execution":{"iopub.status.busy":"2023-02-16T12:31:19.128405Z","iopub.execute_input":"2023-02-16T12:31:19.128877Z","iopub.status.idle":"2023-02-16T12:32:27.393228Z","shell.execute_reply.started":"2023-02-16T12:31:19.128841Z","shell.execute_reply":"2023-02-16T12:32:27.391668Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Image crop function ##","metadata":{}},{"cell_type":"code","source":"def crop_image(img, show=True):\n    # Binarize the image\n    bin_pixels = cv2.threshold(img, 20, 255, cv2.THRESH_BINARY)[1]\n   \n    # Make contours around the binarized image, keep only the largest contour\n    contours, _ = cv2.findContours(bin_pixels, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)\n    contour = max(contours, key=cv2.contourArea)\n\n    # Create a mask from the largest contour\n    mask = np.zeros(img.shape, np.uint8)\n    cv2.drawContours(mask, [contour], -1, 255, cv2.FILLED)\n   \n    # Use bitwise_and to get masked part of the original image\n    out = cv2.bitwise_and(img, mask)\n    \n    # get bounding box of contour\n    y1, y2 = np.min(contour[:, :, 1]), np.max(contour[:, :, 1])\n    x1, x2 = np.min(contour[:, :, 0]), np.max(contour[:, :, 0])\n    \n    x1 = int(0.99 * x1)\n    x2 = int(1.01 * x2)\n    y1 = int(0.99 * y1)\n    y2 = int(1.01 * y2)\n    \n    if show:\n        plt.imshow(out[y1:y2, x1:x2], cmap=\"gray\") ; \n\n    return out[y1:y2, x1:x2]","metadata":{"execution":{"iopub.status.busy":"2023-02-16T12:32:27.396124Z","iopub.execute_input":"2023-02-16T12:32:27.39665Z","iopub.status.idle":"2023-02-16T12:32:27.409836Z","shell.execute_reply.started":"2023-02-16T12:32:27.3966Z","shell.execute_reply":"2023-02-16T12:32:27.408433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Test crop 5 picture ##","metadata":{}},{"cell_type":"code","source":"for f in tqdm(train_images[10:15]):\n\n    patient = f.split('/')[-2]\n    image = f.split('/')[-1][:-4]\n    \n    dicom = pydicom.dcmread(f)\n    img = dicom.pixel_array\n\n    img = (img - img.min()) / (img.max() - img.min())    \n    img *= 255\n    img = np.uint8(img)\n\n    if dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        img = 1 - img\n\n    plt.figure(figsize=(5, 5))\n    plt.imshow(img, cmap=\"gray\")\n    plt.title(f\"original image for {f}\")\n    plt.show()\n        \n    img = crop_image(img, show=False)\n    \n    plt.figure(figsize=(5, 5))\n    plt.imshow(img, cmap=\"gray\")\n    plt.title(f\"after removal / cropping {f}\")\n    plt.show()\n    \n    crop_image(img, show=False)","metadata":{"execution":{"iopub.status.busy":"2023-02-16T12:32:27.41188Z","iopub.execute_input":"2023-02-16T12:32:27.41274Z","iopub.status.idle":"2023-02-16T12:32:37.629163Z","shell.execute_reply.started":"2023-02-16T12:32:27.41268Z","shell.execute_reply":"2023-02-16T12:32:37.627619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Test crop 10 picture ##","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nw = 10\nh = 10\n\nfig = plt.figure(figsize=(15, 15))\ncolumns = 5\nrows = 2\nfor i in tqdm(range(1, columns*rows +1)):\n    f = train_images[i]\n    \n    dicom = pydicom.dcmread(f)\n    img = dicom.pixel_array\n    img = (img - img.min()) / (img.max() - img.min())    \n    img *= 255\n    img = np.uint8(img)\n    if dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        img = 1 - img\n\n    plt.figure(figsize=(5, 5))\n    plt.imshow(img, cmap=\"gray\")\n    plt.title(f\"original image for {f}\")\n    img = crop_image(img, show=False)\n    plt.figure(figsize=(5, 5))\n    plt.imshow(img, cmap=\"gray\")\n    plt.title(f\"after removal / cropping {f}\")\n    plt.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-02-16T12:32:37.633473Z","iopub.execute_input":"2023-02-16T12:32:37.634088Z","iopub.status.idle":"2023-02-16T12:33:13.258011Z","shell.execute_reply.started":"2023-02-16T12:32:37.634037Z","shell.execute_reply":"2023-02-16T12:33:13.256527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Random Picture ##","metadata":{}},{"cell_type":"code","source":"import random\ndv = random.randint(1, 10000)\nprint(dv)","metadata":{"execution":{"iopub.status.busy":"2023-02-16T12:33:13.259724Z","iopub.execute_input":"2023-02-16T12:33:13.260171Z","iopub.status.idle":"2023-02-16T12:33:13.268788Z","shell.execute_reply.started":"2023-02-16T12:33:13.260131Z","shell.execute_reply":"2023-02-16T12:33:13.266909Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Original image uncropped ##\n","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nw = 10\nh = 10\n\nfig = plt.figure(figsize=(15, 15))\ncolumns = 10\nrows = 5\nfor i in tqdm(range(dv, dv + columns*rows)):\n    f = train_images[i]\n    \n    dicom = pydicom.dcmread(f)\n    img = dicom.pixel_array\n    img = (img - img.min()) / (img.max() - img.min())    \n    img *= 255\n    img = np.uint8(img)\n    if dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        img = 1 - img\n\n    fig.add_subplot(rows, columns, i-dv+1)\n    plt.imshow(img, cmap = 'gray')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-02-16T12:33:13.271222Z","iopub.execute_input":"2023-02-16T12:33:13.271756Z","iopub.status.idle":"2023-02-16T12:34:08.667609Z","shell.execute_reply.started":"2023-02-16T12:33:13.271689Z","shell.execute_reply":"2023-02-16T12:34:08.666186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Photo after cropping ##","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nw = 10\nh = 10\n\nfig = plt.figure(figsize=(15, 15))\ncolumns = 10\nrows = 5\nfor i in tqdm(range(dv, dv + columns*rows)):\n    f = train_images[i]\n    \n    dicom = pydicom.dcmread(f)\n    img = dicom.pixel_array\n    img = (img - img.min()) / (img.max() - img.min())    \n    img *= 255\n    img = np.uint8(img)\n    if dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        img = 1 - img\n        \n    img = crop_image(img, show=False)\n\n    fig.add_subplot(rows, columns, i-dv+1)\n    plt.imshow(img, cmap = 'gray')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-02-16T12:34:08.669218Z","iopub.execute_input":"2023-02-16T12:34:08.670451Z","iopub.status.idle":"2023-02-16T12:34:55.872767Z","shell.execute_reply.started":"2023-02-16T12:34:08.670391Z","shell.execute_reply":"2023-02-16T12:34:55.87101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Special cases ##","metadata":{}},{"cell_type":"code","source":"special_case = [\"/kaggle/input/rsna-breast-cancer-detection/train_images/28443/427559566.dcm\",\n    \"/kaggle/input/rsna-breast-cancer-detection/train_images/33084/1990776518.dcm\",\n    \"/kaggle/input/rsna-breast-cancer-detection/train_images/38080/88110813.dcm\",\n    \"/kaggle/input/rsna-breast-cancer-detection/train_images/3280/167999868.dcm\",\n    \"/kaggle/input/rsna-breast-cancer-detection/train_images/3280/288754164.dcm\",\n    \"/kaggle/input/rsna-breast-cancer-detection/train_images/3280/525646440.dcm\",\n    \"/kaggle/input/rsna-breast-cancer-detection/train_images/3280/822885011.dcm\",\n    \"/kaggle/input/rsna-breast-cancer-detection/train_images/3280/951384262.dcm\",\n    \"/kaggle/input/rsna-breast-cancer-detection/train_images/44351/1974129105.dcm\",\n    \"/kaggle/input/rsna-breast-cancer-detection/train_images/822/1942326353.dcm\"]","metadata":{"execution":{"iopub.status.busy":"2023-02-16T12:34:55.874717Z","iopub.execute_input":"2023-02-16T12:34:55.876171Z","iopub.status.idle":"2023-02-16T12:34:55.883268Z","shell.execute_reply.started":"2023-02-16T12:34:55.876114Z","shell.execute_reply":"2023-02-16T12:34:55.881695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for f in tqdm(special_case):\n    dicom = pydicom.dcmread(f)\n    img = dicom.pixel_array\n\n    img = (img - img.min()) / (img.max() - img.min())    \n    img *= 255\n    img = np.uint8(img)\n\n    if dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        img = 1 - img\n\n    plt.figure(figsize=(5, 5))\n    plt.imshow(img, cmap=\"gray\")\n    plt.title(f\"original image for {f}\")\n    plt.show()\n\n    img = crop_image(img, show=False)\n\n    plt.figure(figsize=(5, 5))\n    plt.imshow(img, cmap=\"gray\")\n    plt.title(f\"after removal / cropping {f}\")\n    plt.show()\n\n    crop_image(img, show=False)","metadata":{"execution":{"iopub.status.busy":"2023-02-16T12:34:55.885135Z","iopub.execute_input":"2023-02-16T12:34:55.88563Z","iopub.status.idle":"2023-02-16T12:35:31.386678Z","shell.execute_reply.started":"2023-02-16T12:34:55.885579Z","shell.execute_reply":"2023-02-16T12:35:31.384876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Special cases processing ##","metadata":{}},{"cell_type":"code","source":"def crop_image_high(img, special_value, show=True):\n    # Binarize the image\n    bin_pixels = cv2.threshold(img, special_value, 255, cv2.THRESH_BINARY)[1]\n   \n    # Make contours around the binarized image, keep only the largest contour\n    contours, _ = cv2.findContours(bin_pixels, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)\n    contour = max(contours, key=cv2.contourArea)\n\n    # Create a mask from the largest contour\n    mask = np.zeros(img.shape, np.uint8)\n    cv2.drawContours(mask, [contour], -1, 255, cv2.FILLED)\n   \n    # Use bitwise_and to get masked part of the original image\n    out = cv2.bitwise_and(img, mask)\n    \n    # get bounding box of contour\n    y1, y2 = np.min(contour[:, :, 1]), np.max(contour[:, :, 1])\n    x1, x2 = np.min(contour[:, :, 0]), np.max(contour[:, :, 0])\n    \n    x1 = int(0.99 * x1)\n    x2 = int(1.01 * x2)\n    y1 = int(0.99 * y1)\n    y2 = int(1.01 * y2)\n    \n    if show:\n        plt.imshow(out[y1:y2, x1:x2], cmap=\"gray\") ; \n\n    return out[y1:y2, x1:x2]","metadata":{"execution":{"iopub.status.busy":"2023-02-16T12:35:31.390422Z","iopub.execute_input":"2023-02-16T12:35:31.391083Z","iopub.status.idle":"2023-02-16T12:35:31.405263Z","shell.execute_reply.started":"2023-02-16T12:35:31.391037Z","shell.execute_reply":"2023-02-16T12:35:31.403318Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"special_value = [100, 205, 100, 20, 20, 20, 20, 20, 20, 20]\nfor _ in tqdm(range(len(special_case))):\n    f = special_case[_]\n    dicom = pydicom.dcmread(f)\n    img = dicom.pixel_array\n\n    img = (img - img.min()) / (img.max() - img.min())    \n    img *= 255\n    img = np.uint8(img)\n\n    if dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        img = 1 - img\n\n    plt.figure(figsize=(5, 5))\n    plt.imshow(img, cmap=\"gray\")\n    plt.title(f\"original image for {f} here\")\n    plt.show()\n\n    img = crop_image_high(img, special_value[_], show=False)\n\n    plt.figure(figsize=(5, 5))\n    plt.imshow(img, cmap=\"gray\")\n    plt.title(f\"after removal / cropping {f} here\")\n    plt.show()\n\n# crop_image(img, show=False)\n","metadata":{"execution":{"iopub.status.busy":"2023-02-16T12:35:31.407243Z","iopub.execute_input":"2023-02-16T12:35:31.407727Z","iopub.status.idle":"2023-02-16T12:36:03.282791Z","shell.execute_reply.started":"2023-02-16T12:35:31.407692Z","shell.execute_reply":"2023-02-16T12:36:03.281039Z"},"trusted":true},"execution_count":null,"outputs":[]}]}