{"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>Visualizing Chest X-Ray Bit Planes</h1>\n    - yet another chest x-ray processing notebook -\n    </div>\n    \n### In this notebook, we'll use manual bit-plane slicing to extract pixel planes from CXR's.\n\n- The goal is to explore the possibility of getting segmentation masks or other useful diagnostic information.\n","metadata":{}},{"cell_type":"markdown","source":"#### Let's grab and image and slice it up!","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pydicom\nimport cv2\nimport matplotlib.pyplot as plt\nfrom skimage.transform import resize","metadata":{"execution":{"iopub.status.busy":"2021-07-05T22:38:55.024212Z","iopub.execute_input":"2021-07-05T22:38:55.024607Z","iopub.status.idle":"2021-07-05T22:38:55.029348Z","shell.execute_reply.started":"2021-07-05T22:38:55.024572Z","shell.execute_reply":"2021-07-05T22:38:55.028307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Grab a random DICOM file from the SIIM Covid-19 Detection set\nimg_file = \"../input/siim-covid19-detection/train/00a76543ed93/4a223cccbe04/ad8d4a5ba8f0.dcm\"\nimg = pydicom.dcmread(img_file)","metadata":{"execution":{"iopub.status.busy":"2021-07-05T22:38:55.032174Z","iopub.execute_input":"2021-07-05T22:38:55.032513Z","iopub.status.idle":"2021-07-05T22:38:55.071758Z","shell.execute_reply.started":"2021-07-05T22:38:55.032476Z","shell.execute_reply":"2021-07-05T22:38:55.070683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Resize the pixels\nw = int(img.pixel_array.shape[0] * .25)\nh = int(img.pixel_array.shape[1] * .25)\nimg = resize(img.pixel_array, (w, h), anti_aliasing=True).astype(float)\n\n# scale the pixels\nimg = (np.maximum(img,0) / img.max()) * 255.0\nimg = np.uint8(img)","metadata":{"execution":{"iopub.status.busy":"2021-07-05T22:38:55.073221Z","iopub.execute_input":"2021-07-05T22:38:55.073521Z","iopub.status.idle":"2021-07-05T22:38:55.643782Z","shell.execute_reply.started":"2021-07-05T22:38:55.073492Z","shell.execute_reply":"2021-07-05T22:38:55.642856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**We'll do this manually for demo purposes. There are libraries for this. I'll explore them here in a later update ..**","metadata":{}},{"cell_type":"code","source":"# Get the pixels in a list in binary format\nlst = []\nfor i in range(img.shape[0]):\n    for j in range(img.shape[1]):\n         lst.append(np.binary_repr(int(img[i][j]),width=8))\n            \n# grab the MSB at each level, ignoring the lower four for this demo\nbit_8 = (np.array([int(i[0]) for i in lst],dtype = np.uint8) * 128).reshape(img.shape[0],img.shape[1])\nbit_7 = (np.array([int(i[0]) for i in lst],dtype = np.uint8) * 64).reshape(img.shape[0],img.shape[1])\nbit_6 = (np.array([int(i[2]) for i in lst],dtype = np.uint8) * 32).reshape(img.shape[0],img.shape[1])\nbit_5 = (np.array([int(i[3]) for i in lst],dtype = np.uint8) * 16).reshape(img.shape[0],img.shape[1])","metadata":{"execution":{"iopub.status.busy":"2021-07-05T22:38:55.645428Z","iopub.execute_input":"2021-07-05T22:38:55.645732Z","iopub.status.idle":"2021-07-05T22:38:59.702383Z","shell.execute_reply.started":"2021-07-05T22:38:55.645702Z","shell.execute_reply":"2021-07-05T22:38:59.701275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Display the pixel planes\nfig, axes = plt.subplots(nrows=2, ncols=2,sharex=True, sharey=True, figsize=(12, 12))\nax = axes.ravel()\nax[0].imshow(bit_8, cmap='gray')\nax[1].imshow(bit_7, cmap='gray')\nax[2].imshow(bit_6, cmap='gray')\nax[3].imshow(bit_5, cmap='gray')\n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-05T22:38:59.703787Z","iopub.execute_input":"2021-07-05T22:38:59.704082Z","iopub.status.idle":"2021-07-05T22:39:00.837941Z","shell.execute_reply.started":"2021-07-05T22:38:59.704053Z","shell.execute_reply":"2021-07-05T22:39:00.836989Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Conclusion\n\n- Bit plane slices could be used as masks. When combined with thresholding and other filter techniques, they might prove useful. ","metadata":{}},{"cell_type":"markdown","source":"#### Here are some other processing notebooks I made:\n- Lung Segmentation Without CNN -> https://www.kaggle.com/davidbroberts/lung-segmentation-without-cnn\n- Applying filters to x-rays -> https://www.kaggle.com/davidbroberts/applying-filters-to-chest-x-rays\n- Rib supression on Chest X-Rays -> https://www.kaggle.com/davidbroberts/rib-suppression-poc\n- Manual DICOM VOI LUT -> https://www.kaggle.com/davidbroberts/manual-dicom-voi-lut\n- Apply Unsharp Mask to Chest X-Rays -> https://www.kaggle.com/davidbroberts/unsharp-masking-chest-x-rays\n- Cropping Chest X-Rays -> https://www.kaggle.com/davidbroberts/cropping-chest-x-rays\n- Bounding Boxes on Cropped Images -> https://www.kaggle.com/davidbroberts/bounding-boxes-on-cropped-images\n- DICOM full range pixels as CNN input -> https://www.kaggle.com/davidbroberts/dicom-full-range-pixels-as-cnn-input\n- Standardizing Chest X-Ray Dataset Exports -> https://www.kaggle.com/davidbroberts/standardizing-cxr-datasets","metadata":{}}]}