{"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>Bounding boxes on cropped images</h1>\n    - yet another chest x-ray processing notebook -\n</div>\n\n#### In this notebook, I'll show how to maintain BB placement when cropping images by subtracting the crop amounts from the BB coords.","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport seaborn as sns\nimport pydicom\nimport matplotlib.pyplot as plt\nimport os\nfrom os import listdir\nfrom os.path import isfile, join\nimport json\nimport cv2","metadata":{"execution":{"iopub.status.busy":"2021-07-02T17:01:28.308045Z","iopub.execute_input":"2021-07-02T17:01:28.308564Z","iopub.status.idle":"2021-07-02T17:01:28.317551Z","shell.execute_reply.started":"2021-07-02T17:01:28.308502Z","shell.execute_reply":"2021-07-02T17:01:28.316295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load the image dataframe so we can get BB coords\nbase_path = \"/kaggle/input/siim-covid19-detection/\"\nimages_df = pd.read_csv(os.path.join(base_path,\"train_image_level.csv\"))","metadata":{"execution":{"iopub.status.busy":"2021-07-02T17:01:28.319275Z","iopub.execute_input":"2021-07-02T17:01:28.319813Z","iopub.status.idle":"2021-07-02T17:01:28.392776Z","shell.execute_reply.started":"2021-07-02T17:01:28.319764Z","shell.execute_reply":"2021-07-02T17:01:28.391675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Define some methods","metadata":{}},{"cell_type":"code","source":"# Function to get the BB data from the images DF\ndef get_boxes(image_id):\n    image = image_id.replace('.dcm','_image')\n    ti = images_df[images_df['id'] == image]\n    bx = [[],[]]\n    bx[0] = [0,0,0,0,\"\"]\n    bx[1] = [0,0,0,0,\"\"]\n    \n    if str(ti['boxes'].values[0]) != \"nan\":\n        box = str(ti['boxes'].values[0]).replace(\"'\",\"\\\"\")\n        boxes = json.loads(box)\n        lab = ti['label'].values[0].split(\" \")\n        i = 0\n        for b in boxes:\n            bx[i] = [int(b['x']), int(b['y']), int(b['width']),int(b['height']),lab[0]]\n            i = i+1\n    return bx","metadata":{"execution":{"iopub.status.busy":"2021-07-02T17:01:28.394865Z","iopub.execute_input":"2021-07-02T17:01:28.39522Z","iopub.status.idle":"2021-07-02T17:01:28.405669Z","shell.execute_reply.started":"2021-07-02T17:01:28.39518Z","shell.execute_reply":"2021-07-02T17:01:28.404519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# This function applies the crop offsets to BB coords\n# We just subtract the amount cropped from the top and left from the BB coords.\ndef crop_offset(x,y, offset):\n    x = [i - (offset[0] + offset[2]) for i in x]\n    y = [i - (offset[1] + offset[3]) for i in y]\n    return x, y","metadata":{"execution":{"iopub.status.busy":"2021-07-02T17:01:28.40742Z","iopub.execute_input":"2021-07-02T17:01:28.408079Z","iopub.status.idle":"2021-07-02T17:01:28.419947Z","shell.execute_reply.started":"2021-07-02T17:01:28.408025Z","shell.execute_reply":"2021-07-02T17:01:28.418719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# This function draws boxes on images, one line at a time\ndef draw_boxes(boxes, z):\n\n    for i in boxes:     \n        # Top\n        x = [i[0] - z[0], i[0] + i[2] - z[0]]        # [ x1 , x2 ]\n        y = [i[1] - z[1], i[1] - z[1]]               # [ y1 , y2 ]\n        plt.plot(x,y, color='#ff8838', linewidth=2)\n        \n        # Bottom\n        y = [i[1] + i[3] - z[1], i[1] + i[3] - z[1]]\n        plt.plot(x,y, color='#ff8838', linewidth=2)\n        \n        # Left\n        x = [i[0] - z[0], i[0] - z[0]]\n        y = [i[1] - z[1], i[1] + i[3] - z[1]]\n        plt.plot(x,y, color='#ff8838', linewidth=2)\n\n        # Right         \n        x = [i[0] + i[2] - z[0], i[0] + i[2] - z[0]]\n        plt.plot(x,y, color='#ff8838', linewidth=2)","metadata":{"execution":{"iopub.status.busy":"2021-07-02T17:01:28.42145Z","iopub.execute_input":"2021-07-02T17:01:28.421818Z","iopub.status.idle":"2021-07-02T17:01:28.43505Z","shell.execute_reply.started":"2021-07-02T17:01:28.421781Z","shell.execute_reply":"2021-07-02T17:01:28.433734Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Load an image","metadata":{}},{"cell_type":"code","source":"# Load a random DICOM file\nfilename = '../input/siim-covid19-detection/train/00086460a852/9e8302230c91/65761e66de9f.dcm'\n    \nimg = pydicom.dcmread(filename)\npixels = img.pixel_array\n\n# Invert MONOCHROME1 the easy way for demo purposes\ncmap = \"gray\"\nif (img.PhotometricInterpretation == \"MONOCHROME1\"):\n    cmap = \"gray_r\"","metadata":{"execution":{"iopub.status.busy":"2021-07-02T17:01:28.436769Z","iopub.execute_input":"2021-07-02T17:01:28.437232Z","iopub.status.idle":"2021-07-02T17:01:28.507015Z","shell.execute_reply.started":"2021-07-02T17:01:28.437184Z","shell.execute_reply":"2021-07-02T17:01:28.506183Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Crop the left by 200 pixels and the top by 500 pixels","metadata":{}},{"cell_type":"code","source":"# Make a cropped copy of the image\ncrop = [200,500,0,0]   # left, top, right, bottom\n\nw = pixels.shape[1] - (crop[0] + crop[2])\nh = pixels.shape[0] - (crop[1] + crop[3])\n\ncropped = pixels[crop[1]:crop[1] + h, crop[0]:crop[0] + w]\n\nprint(\"Orig size: \" + str(pixels.shape[1]) + \" x \" + str(pixels.shape[0]))\nprint(\"Crop size: \" + str(cropped.shape[1]) + \" x \" + str(cropped.shape[0]))","metadata":{"execution":{"iopub.status.busy":"2021-07-02T17:01:28.508248Z","iopub.execute_input":"2021-07-02T17:01:28.508715Z","iopub.status.idle":"2021-07-02T17:01:28.519463Z","shell.execute_reply.started":"2021-07-02T17:01:28.50868Z","shell.execute_reply":"2021-07-02T17:01:28.518161Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Grab the BB coordinates, apply the crop offsets and draw them on the images.","metadata":{}},{"cell_type":"code","source":"# Get the BB coordinates\nboxes = get_boxes(str(os.path.basename(filename)))\n\nplt.figure(figsize=(15,5)) \n\n# Display the original image with no cropping\nplt.subplot(1, 2, 1)\nplt.title(\"Original: \" + str(pixels.shape[1]) + \" x \" + str(pixels.shape[0]))\n\n# Draw BB's. Pass the cropping values of zero.\ndraw_boxes(boxes, [0,0,0,0])\nplt.imshow(pixels,cmap=cmap)      \nplt.subplot(1, 2, 2)\n\n# Display the cropped image\nplt.title(\"Cropped: \" + str(cropped.shape[1]) + \" x \" + str(cropped.shape[0]))\n\n# Draw BB's, pass the 'crop' value we used earlier to crop the image\ndraw_boxes(boxes, crop)\nplt.imshow(cropped,cmap=cmap)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-02T17:01:28.522973Z","iopub.execute_input":"2021-07-02T17:01:28.523839Z","iopub.status.idle":"2021-07-02T17:01:30.047624Z","shell.execute_reply.started":"2021-07-02T17:01:28.523782Z","shell.execute_reply":"2021-07-02T17:01:30.046571Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### As you can see, the BB's are still in the correct place even though we cropped the top and left side of the image.\n\n**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- Visualizing Chest X-Ray bit planes -> https://www.kaggle.com/davidbroberts/visualizing-chest-x-ray-bitplanes\n- DICOM full range pixels as CNN input -> https://www.kaggle.com/davidbroberts/dicom-full-range-pixels-as-cnn-input","metadata":{}}]}