{"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":"<div class='alert alert-info' style='text-align:center'><h1>Remove Mammography Letter Markers</h1>\n- yet another DICOM processing notebook -</div>\n\n### A simple method to reduce noise in mammography images\n\n##### No object detection or classification necessary.","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"code","source":"# Install GDCM and libjeg to handle decoding JPG encoded DICOM files\n!pip install python-gdcm\n!pip install pylibjpeg-libjpeg","metadata":{"execution":{"iopub.status.busy":"2022-12-02T20:51:15.062618Z","iopub.execute_input":"2022-12-02T20:51:15.063104Z","iopub.status.idle":"2022-12-02T20:51:43.107997Z","shell.execute_reply.started":"2022-12-02T20:51:15.063016Z","shell.execute_reply":"2022-12-02T20:51:43.106823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport cv2\nimport pydicom\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2022-12-02T20:51:43.110604Z","iopub.execute_input":"2022-12-02T20:51:43.111015Z","iopub.status.idle":"2022-12-02T20:51:43.529208Z","shell.execute_reply.started":"2022-12-02T20:51:43.110963Z","shell.execute_reply":"2022-12-02T20:51:43.527981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### - Read in a random mammogram with pydicom","metadata":{}},{"cell_type":"code","source":"im = pydicom.dcmread(\"/kaggle/input/rsna-breast-cancer-detection/train_images/16167/970646141.dcm\")\n    \npixels = im.pixel_array\n\nif im.PhotometricInterpretation == \"MONOCHROME1\":\n    pixels = np.amax(pixels) - pixels\nelse:\n    pixels = pixels - np.min(pixels)\n\nif np.max(pixels) != 0:\n    pixels = pixels / np.max(pixels)\n    pixels = (pixels * 255).astype(np.uint8)","metadata":{"execution":{"iopub.status.busy":"2022-12-02T20:51:43.531129Z","iopub.execute_input":"2022-12-02T20:51:43.531976Z","iopub.status.idle":"2022-12-02T20:51:44.878715Z","shell.execute_reply.started":"2022-12-02T20:51:43.531928Z","shell.execute_reply":"2022-12-02T20:51:44.87746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(6,8))\nplt.imshow(pixels,cmap=\"gray\");","metadata":{"execution":{"iopub.status.busy":"2022-12-02T20:51:44.880204Z","iopub.execute_input":"2022-12-02T20:51:44.880624Z","iopub.status.idle":"2022-12-02T20:51:47.739605Z","shell.execute_reply.started":"2022-12-02T20:51:44.880581Z","shell.execute_reply":"2022-12-02T20:51:47.738479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### - Notice the \"R-MLO\" letter marker in the top left corner.\n### - We'll make a mask of the breast and filter it out of the image using CV2's findContours() and drawContours() functions.\n### - Then, we'll use the mask to extract the anatomy and ignore the smaller artifacts.\n##### ** This will elminate some noise from the image for better training.","metadata":{}},{"cell_type":"code","source":"# Binarize the image\nbin_pixels = cv2.threshold(pixels, 20, 255, cv2.THRESH_BINARY)[1]\n\n# Make contours around the binarized image, keep only the largest contour\ncontours, _ = cv2.findContours(bin_pixels, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)\ncontour = max(contours, key=cv2.contourArea)\n\n# Create a mask from the largest contour\nmask = np.zeros(pixels.shape, np.uint8)\ncv2.drawContours(mask, [contour], -1, 255, cv2.FILLED)\n\n# Use bitwise_and to get masked part of the original image\nout = cv2.bitwise_and(pixels,mask)","metadata":{"execution":{"iopub.status.busy":"2022-12-02T20:51:47.741843Z","iopub.execute_input":"2022-12-02T20:51:47.742571Z","iopub.status.idle":"2022-12-02T20:51:47.83452Z","shell.execute_reply.started":"2022-12-02T20:51:47.742535Z","shell.execute_reply":"2022-12-02T20:51:47.833571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(6,8))\nplt.imshow(out,cmap=\"gray\");","metadata":{"execution":{"iopub.status.busy":"2022-12-02T20:51:47.836222Z","iopub.execute_input":"2022-12-02T20:51:47.836711Z","iopub.status.idle":"2022-12-02T20:51:50.615464Z","shell.execute_reply.started":"2022-12-02T20:51:47.836666Z","shell.execute_reply":"2022-12-02T20:51:50.614306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### - The letter marker is gone .. Rejoice!\n### -\n### - Lets do another one.","metadata":{}},{"cell_type":"code","source":"im = pydicom.dcmread(\"/kaggle/input/rsna-breast-cancer-detection/train_images/10011/220375232.dcm\")\n    \npixels = im.pixel_array\n\nif im.PhotometricInterpretation == \"MONOCHROME1\":\n    pixels = np.amax(pixels) - pixels\nelse:\n    pixels = pixels - np.min(pixels)\n\nif np.max(pixels) != 0:\n    pixels = pixels / np.max(pixels)\n    pixels = (pixels * 255).astype(np.uint8)\n    \nplt.figure(figsize=(6,8))\nplt.imshow(pixels,cmap=\"gray\");","metadata":{"execution":{"iopub.status.busy":"2022-12-02T20:51:50.617583Z","iopub.execute_input":"2022-12-02T20:51:50.618435Z","iopub.status.idle":"2022-12-02T20:51:52.191747Z","shell.execute_reply.started":"2022-12-02T20:51:50.618386Z","shell.execute_reply":"2022-12-02T20:51:52.190432Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"bin_pixels = cv2.threshold(pixels, 20, 255, cv2.THRESH_BINARY)[1]\ncontours, _ = cv2.findContours(bin_pixels, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)\ncontour = max(contours, key=cv2.contourArea)\nmask = np.zeros(pixels.shape, np.uint8)\ncv2.drawContours(mask, [contour], -1, 255, cv2.FILLED)\nout = cv2.bitwise_and(pixels,mask)","metadata":{"execution":{"iopub.status.busy":"2022-12-02T20:51:52.193371Z","iopub.execute_input":"2022-12-02T20:51:52.193738Z","iopub.status.idle":"2022-12-02T20:51:52.211413Z","shell.execute_reply.started":"2022-12-02T20:51:52.193707Z","shell.execute_reply":"2022-12-02T20:51:52.210137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(6,8))\nplt.imshow(out,cmap=\"gray\");","metadata":{"execution":{"iopub.status.busy":"2022-12-02T20:51:52.213194Z","iopub.execute_input":"2022-12-02T20:51:52.214081Z","iopub.status.idle":"2022-12-02T20:51:53.278501Z","shell.execute_reply.started":"2022-12-02T20:51:52.214029Z","shell.execute_reply":"2022-12-02T20:51:53.276963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### - Conclusion:\n##### This is a simple method to remove small artifacts, including letter markers from mammography images.\n##### Play around with the CV2 threshold values if you notice parts of the markers not disappearing, or parts of the breast being removed.","metadata":{}}]}