{"cells":[{"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","trusted":true},"cell_type":"code","source":"import os\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport pydicom\n\nfrom skimage.measure import label,regionprops\nfrom skimage.segmentation import clear_border\nimport matplotlib.pyplot as plt","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Raw image","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# https://www.kaggle.com/currypurin/osic-image-shape-eda-and-preprocess\ndef crop_image(img: np.ndarray):\n    edge_pixel_value = img[0, 0]\n    mask = img != edge_pixel_value\n    return img[np.ix_(mask.any(1),mask.any(0))]","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"#d = pydicom.dcmread('../input/osic-pulmonary-fibrosis-progression/train/ID00030637202181211009029/100.dcm')\nd = pydicom.dcmread('../input/osic-pulmonary-fibrosis-progression/test/ID00419637202311204720264/21.dcm')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"img = crop_image(d.pixel_array)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig = plt.figure(figsize=(12, 12))\n\nplt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Rescale and create binary mask\nThe bright region inside the lungs are the blood vessels or air. A threshold of -600--850 HU is used at all places because it was found in experiments. ","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"right_mask = cv2.imread('../input/osic-generalized-lung-mask/mask/right_mask_simetric.jpg', 0)\nleft_mask = cv2.imread('../input/osic-generalized-lung-mask/mask/left_mask_simetric.jpg', 0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img = (crop_image(d.pixel_array) + d.RescaleIntercept) / d.RescaleSlope\ndim = min(img.shape)\ncancer_mask = (img > 10) & (img < 400)\nlung_mask = (img > -850) & (img < -600)\nlung_mask = cv2.bilateralFilter(lung_mask.astype('float32'),int(dim*0.05),int(dim*0.2),int(dim*0.2)) > 0.1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cancer_mask[~lung_mask] = 0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig = plt.figure(figsize=(12, 12))\n\nplt.imshow(cancer_mask)\nplt.imshow(lung_mask, alpha=0.3)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Based on the previous mask I created a generic lung mask for right and left lung.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"fig = plt.figure(figsize=(12, 12))\n\nplt.imshow(right_mask, alpha=0.75)\nplt.imshow(left_mask, alpha=0.75);","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"right_mask = cv2.resize(right_mask, lung_mask.shape[::-1]).astype('uint8')\nleft_mask = cv2.resize(left_mask, lung_mask.shape[::-1]).astype('uint8')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig = plt.figure(figsize=(12, 12))\n\nplt.imshow(cancer_mask)\nplt.imshow(lung_mask, alpha=0.4)\nplt.imshow(cv2.resize(right_mask, lung_mask.shape[::-1]), alpha=0.25)\nplt.imshow(cv2.resize(left_mask, lung_mask.shape[::-1]), alpha=0.25)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Cleaning border","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"cancer_mask = clear_border(cancer_mask)\nlung_mask = clear_border(lung_mask)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig = plt.figure(figsize=(12, 12))\n\nplt.imshow(cancer_mask)\nplt.imshow(lung_mask, alpha=0.4)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Remove small and select nearest to generic lung mask region","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.metrics import jaccard_score","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"lung_mask_labeled = label(lung_mask)\n\nfig = plt.figure(figsize=(12, 12))\n\nplt.imshow(lung_mask_labeled)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for i, r in enumerate(regionprops(lung_mask_labeled)):\n    _lung_mask = lung_mask.copy()\n    m = np.zeros_like(_lung_mask)\n    m[r.slice] = 1\n    _lung_mask = _lung_mask * m > 0\n    riou = jaccard_score(_lung_mask, right_mask > 0, average='micro')\n    liou = jaccard_score(_lung_mask, left_mask > 0, average='micro')\n    print(f\"Region {i}\")\n    print(\"\\tRight: \", riou, \"\\n\\tLeft: \", liou)\n    if liou < 0.1 and riou < 0.1:\n        for coordinates in r.coords:                \n            lung_mask_labeled[coordinates[0], coordinates[1]] = 0","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig = plt.figure(figsize=(12, 12))\n\nplt.imshow(cancer_mask)\nplt.imshow(lung_mask_labeled, alpha=0.5);","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig = plt.figure(figsize=(12, 12))\n\nplt.imshow((crop_image(d.pixel_array) + d.RescaleIntercept) / d.RescaleSlope)\nplt.imshow(lung_mask_labeled, alpha=0.5);","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Conclusion \nThe determining of a mask for the lungs is the starting point in the algorithm for determining the volume of the lungs by CT images. The next step is the correct integration of all CT images to determine the volume of the lungs and volume posible cancer regions. \n\nI trying current approach for many patients and taking a good lungs of mask in a result.","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Reference\n* [OSIC / image shape EDA and preprocess](https://www.kaggle.com/currypurin/osic-image-shape-eda-and-preprocess)\n* [Unsupervise Lung Detection](https://www.kaggle.com/miklgr500/unsupervise-lung-detection)","execution_count":null}],"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":4,"nbformat_minor":4}