{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import plotly.offline as pyo\npyo.init_notebook_mode()\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport os\nimport math\nimport cv2 \nfrom plotly.subplots import make_subplots\nimport plotly.graph_objects as go\nfrom sklearn import preprocessing\nimport random\nimport tensorflow as tf\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport warnings\nwarnings.filterwarnings(\"ignore\")\nimport pydicom as dicom\n!pip install visualkeras","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# EDA"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"path = '/kaggle/input/vinbigdata-chest-xray-abnormalities-detection/'\nos.listdir(path)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data = pd.read_csv(path+'train.csv')\nsamp_subm = pd.read_csv(path+'sample_submission.csv')\nprint('Number train samples:', len(train_data.index))\nprint('Number test samples:', len(samp_subm.index))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, ax = plt.subplots(1, 1, figsize=(12, 4))\nx = train_data['class_name'].value_counts().keys()\ny = train_data['class_name'].value_counts().values\nax.bar(x, y)\nax.set_xticklabels(x, rotation=90)\nax.set_title('Distribution of the labels')\nplt.grid()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Lets Visualize"},{"metadata":{},"cell_type":"markdown","source":"1. Read Dimcom data \n2. Visualize all classes in a grid\n3. Visualize one input image per call "},{"metadata":{},"cell_type":"markdown","source":"Converting dicom data to png/jpg may look straightforward and there is going to be many notebooks doing it simple way - just rescaling it.\n\nHowever, you must consider, that raw dicom data is not actually linearly convertable to \"human-friendly\" png/jpg. In fact, most of DICOM's store pixel values in exponential scale, which is resolved by standard standard DICOM viewers.\n\nSo in order to get jpg/png as radiologists would initially see in their workspace, you need to apply some transformations. DICOM metadata stores information how to make such \"human-friendly\" transformations.\n\nAn example code I use daily can be found below:\n~ [Please Upvote Here](https://www.kaggle.com/raddar/convert-dicom-to-np-array-the-correct-way)"},{"metadata":{"trusted":true},"cell_type":"code","source":"def read_xray(path, voi_lut = True, fix_monochrome = True):\n    dicom = pydicom.read_file(path)\n    # VOI LUT (if available by DICOM device) is used to transform raw DICOM data to \"human-friendly\" view\n    if voi_lut:\n        data = apply_voi_lut(dicom.pixel_array, dicom)\n    else:\n        data = dicom.pixel_array           \n    # depending on this value, X-ray may look inverted - fix that:\n    if fix_monochrome and dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        data = np.amax(data) - data  \n    data = data - np.min(data)\n    data = data / np.max(data)\n    data = (data * 255).astype(np.uint8)   \n    return data","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"count = 1\nf = plt.figure(figsize=(50,20))\nfor Class in train_data['class_name'].unique():\n    seg = train_data[train_data['class_name']==Class]\n    image_id =  seg.sample().iloc[0]['image_id']\n    img = read_xray(path+'train/'+image_id+'.dicom')\n    ax = f.add_subplot(3, 5,count)\n    ax = plt.imshow(img)\n    ax = plt.title(Class,fontsize= 30)\n    count = count + 1\nplt.suptitle(\"Chest X ray\", size = 32)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.rcParams[\"figure.figsize\"] = (20,10)\ndef look(id):\n    idnum = id\n    image_id = train_data.loc[idnum, 'image_id']\n    img = read_xray(path+'train/'+image_id+'.dicom')\n    x1,y1,x2,y2 = train_data.loc[idnum, 'x_min'] , train_data.loc[idnum, 'y_min'] , train_data.loc[idnum, 'x_max'] , train_data.loc[idnum, 'y_max']\n    if(math.isnan(x1) or math.isnan(y1) or math.isnan(x2) or math.isnan(y2)):\n        return img , (-1,-1,-1,-1)\n    x1 = int(x1)\n    y1 = int(y1)\n    x2 = int(x2)\n    y2 = int(y2)\n    \n    return img , (x1,y1,x2,y2)\n    \nlook(825)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Make all imags of same size and bounding box resizing"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_data.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.rcParams[\"figure.figsize\"] = (20,10)\ndef show(img , bbox, title,resized = False):\n    start_point = (bbox[0],bbox[1]) \n    end_point = (bbox[2],bbox[3]) \n    color = (0, 0, 0)\n    if not resized :\n        thickness = 30\n    else :\n        thickness = 1\n    img = cv2.rectangle(img, start_point, end_point, color, thickness) \n    plt.imshow(img)\n    plt.title(title,fontsize= 30)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"idnum = 2\nimage_id = train_data.loc[idnum, 'image_id']\ntitle = train_data.loc[idnum, 'class_name']\nimg = read_xray(path+'train/'+image_id+'.dicom')\nprint(img.shape)\nx1,y1,x2,y2 = train_data.loc[idnum, 'x_min'] , train_data.loc[idnum, 'y_min'] , train_data.loc[idnum, 'x_max'] , train_data.loc[idnum, 'y_max']\nx1 = int(x1)\ny1 = int(y1)\nx2 = int(x2)\ny2 = int(y2)\nprint(x1,y1,x2,y2)\nshow(img , [x1,y1,x2,y2],title)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y_ = img.shape[0]\nx_ = img.shape[1]\ntargetSize = 224\nx_scale = targetSize / x_\ny_scale = targetSize / y_\nprint(x_scale, y_scale)\nimg = cv2.resize(img, (targetSize, targetSize));\nimg = img.reshape(targetSize, targetSize,1)\nprint(img.shape)\n(origLeft, origTop, origRight, origBottom) = (x1,y1,x2,y2)\nx = int(np.round(origLeft * x_scale))\ny = int(np.round(origTop * y_scale))\nxmax = int(np.round(origRight * x_scale))\nymax = int(np.round(origBottom * y_scale))\nprint(x,y,xmax,ymax)\nshow(img.reshape(targetSize,targetSize) , [x,y,xmax,ymax],title,True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Now lets create a function\n1. Arg : Image and BBOX\n2. Output resized 224 * 224 image and bbox"},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_image(img , bbox):\n    y_ = img.shape[0]\n    x_ = img.shape[1]\n    targetSize = 224\n    x_scale = targetSize / x_\n    y_scale = targetSize / y_\n    img = cv2.resize(img, (targetSize, targetSize));\n    img = img.reshape(targetSize, targetSize,1)\n    if(bbox[0] == -1):\n        return img ,[-1,-1,-1,-1]\n    (origLeft, origTop, origRight, origBottom) = (bbox[0],bbox[1],bbox[2],bbox[3])\n    x = int(np.round(origLeft * x_scale))\n    y = int(np.round(origTop * y_scale))\n    xmax = int(np.round(origRight * x_scale))\n    ymax = int(np.round(origBottom * y_scale))\n    return img , (x,y,xmax,ymax)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Lets test with image id 2 and 1"},{"metadata":{"trusted":true},"cell_type":"code","source":"img , bbox = look(2)\nprint(img.shape , bbox)\nimg , bbox = create_image(img , bbox)\nprint(img.shape , bbox)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img , bbox = look(0)\nprint(img.shape , bbox)\nimg , bbox = create_image(img , bbox)\nprint(img.shape , bbox)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Load Data"},{"metadata":{},"cell_type":"markdown","source":"Here we have created train images , y_bb for bounding boxes and y_class for class labelling.\nfrom here w can proceed to model building"},{"metadata":{"trusted":true},"cell_type":"code","source":"from tqdm import tqdm\nfrom sklearn.preprocessing import OneHotEncoder\ntrain_image = []\ntrain_bb = []\nfor image_id in tqdm(range(len(train_data.iloc[:]['image_id']))):\n    img , bbox= look(image_id)\n    img , bbox = create_image(img , bbox)\n    train_image.append(img)\n    train_bb.append(bbox)\nX = np.array(train_image)\ny_bb = np.array(train_bb)\ny_class = np.array(train_data.iloc[:]['class_name'])\ny_class = y_class.reshape(y_class.shape[0],1)\nenc = OneHotEncoder(handle_unknown='ignore')\nenc.fit(y_class)\nprint(enc.categories_)\ny_class = enc.transform(y_class).toarray()\nprint('Data   :   '+str(X.shape))\nprint('Output :   '+str(y_class.shape))\nprint('Data   :   '+str(y_bb.shape))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y_bb","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Transfer Learning"},{"metadata":{"trusted":true,"collapsed":true},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nX_train, X_test, y_train, y_test = train_test_split(X, y_class, random_state=42, test_size=0.1)\nprint('Train data    :'+str(X_train.shape))\nprint('Test data     :'+str(X_test.shape))\nprint('Train Output  :'+str(y_train.shape))\nprint('Test Output   :'+str(y_test.shape))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import visualkeras\nfrom keras.applications.vgg16 import VGG16\nmodel = VGG16()\nvisualkeras.layered_view(model)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.utils import plot_model\nplot_model(model, to_file='model.png',show_shapes=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"Training_Output_Results =pd.DataFrame(columns=['Epochs','Learning Rate','Train_Loss','Train_Accuracy','Train_Precision','Val_Loss','Val_Accuracy','Val_Precision'])\n\nMETRICS = [\n            'accuracy',\n            tf.keras.metrics.Precision(name='precision')\n]  \nmodel.compile(\n                optimizer=tf.keras.optimizers.Adam(),\n                loss='categorical_crossentropy',\n                metrics=METRICS\n            )\nhistory = model.fit(X_train, y_train, epochs=200, validation_split=0.3, batch_size=15,verbose=1,shuffle=True)","execution_count":null,"outputs":[]}],"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}