{"cells":[{"metadata":{},"cell_type":"markdown","source":"This notebook is just me working my way through fast.ai v2 courses. \n\nSpecifically:\n* The medical imaging tutorial https://docs.fast.ai/tutorial.medical_imaging.html\n* The bounding boxes tutorial: https://docs.fast.ai/tutorial.datablock.html#Bounding-boxes\n* useful: https://github.com/muellerzr/Practical-Deep-Learning-for-Coders-2.0/blob/master/Computer%20Vision/06_Object_Detection.ipynb\n* https://www.kaggle.com/muellerzr/fastai2-starter-kernel\n\nShout out to this notebook who did it in Fastai v1. I copied a bunch of code from it\nhttps://www.kaggle.com/robertlangdonvinci/vinbigdata-chest-abnormalities-detection-fastai\n<br>(If you can give me an upvote give him an up-vote too...)"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"from fastai.basics import *\nfrom fastai.callback.all import *\nfrom fastai.vision.all import *\nfrom fastai.medical.imaging import *\n\nimport pydicom\nimport matplotlib.image as immg\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Handy fast.ai function to pull all DICOM file names into a list\n#items = get_dicom_files(\"../input/vinbigdata-chest-xray-abnormalities-detection/train\") #full images\nitems = get_image_files('../input/vinbigdata-resized-image-512/train') #using the 512 images\nitems[0:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# another handy fast.ai funciton to split items randomly...\ntrn,val = RandomSplitter()(items)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#xray_sample.pixel_array, xray_sample.pixel_array.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#xray_sample.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time \n# takes 7-8 minutes, so load from pickle\n'''dicom_dataframe = pd.DataFrame.from_dicoms(items, window=dicom_windows.lungs, px_summ=False)\n\ndicom_dataframe.to_pickle('dicom_dataframe_pickle.pkl')\ndicom_dataframe.shape'''","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# long time to extract the DICOM information, so extracted into pickle for easy loading\ndicom_dataframe = pd.read_pickle('../input/vinbigdata-chest-xray-dicom-data-frame/dicom_dataframe_pickle.pkl')\ndicom_dataframe.shape # should be 15k by 29","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dicom_dataframe.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = pd.read_csv('../input/vinbigdata-chest-xray-abnormalities-detection/train.csv')\nimg_dim = pd.read_csv('../input/vinbigdata-resized-image-512/train_meta.csv')\ntr_img_dir = Path('../input/vinbigdata-resized-image-512/train')\nts_img_dir = Path('../input/vinbigdata-resized-image-512/test')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tr_df = df.merge(img_dim,on='image_id',how='left')\ntr_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Create a df without class 14, the no finding class\ntr_df1 = tr_df[tr_df['class_id']!=14].copy()\ntr_df1.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Rescale bounding boxes to use the resized images\ntr_df1['x_min'] = tr_df1['x_min']*512/tr_df['dim1']\ntr_df1['x_max'] = tr_df1['x_max']*512/tr_df['dim1']\ntr_df1['y_min'] = tr_df1['y_min']*512/tr_df['dim0']\ntr_df1['y_max'] = tr_df1['y_max']*512/tr_df['dim0']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Creating a group by dataframe to pass the images in later\ndf_grp = tr_df1.groupby(['image_id'])\ndf_grp.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# taking a look at the values of one image, and the different classes in them\ndf_grp.get_group('f8c4ffc718ece871a52ab5f63b04b41c')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# take a look at one image from the training set with bounding boxes\nb_fea = ['x_min', 'y_min', 'x_max', 'y_max']\nname = '9a5094b2563a1ef3ff50dc5c7ff71345'\nloc = '../input/vinbigdata-resized-image-512/train/'+name+'.png'\naaa = df_grp.get_group(name)\nbbx = aaa.loc[:,b_fea] #get x and y coordinates for all rows\nimg = immg.imread(loc) # tensor representation for the image\nfig,ax = plt.subplots(figsize=(18,10))\nax.imshow(img,cmap='binary')\n\n# Find how many lines there are for an image in the df\n# Draw a box for each time\nfor i in range(len(bbx)): \n    box = bbx.iloc[i].values\n    x,y,w,h = box[0], box[1], box[2]-box[0], box[3]-box[1]\n    rect = patches.Rectangle((x,y),w,h,linewidth=1,edgecolor='r',facecolor='none',)\n    ax.text(*box[:2], aaa['class_name'].iloc[i], verticalalignment='top', color='white', fontsize=12, weight='bold')\n    ax.add_patch(rect)\nplt.show()\n\n# thanks again: https://www.kaggle.com/robertlangdonvinci/vinbigdata-chest-abnormalities-detection-fastai","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#tr_df1.head()\nnofinding_df = tr_df[tr_df['class_id']==14].copy()\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tr_df1.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"values = {'x_min': 0, 'y_min':0, 'x_max':1, 'y_max':1}\nnofinding_df.fillna(value=values, inplace = True)\n\n\nframes = [nofinding_df, tr_df1]\ntr_df2= pd.concat(frames)\ntr_df2.tail()\nnofinding_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_lbl_img(train):\n    chest2bbox = {}\n    grp = train.image_id.unique()\n    tr_gr = train.groupby(['image_id'])\n    from tqdm.notebook import tqdm\n    for i in tqdm(range(len(grp))):\n        name = str(grp[i])+'.png'\n        bbox = []\n        lbls = []\n        temp_b = []\n        temp = tr_gr.get_group(grp[i])\n        tt = temp.loc[:, (['class_id','x_min', 'y_min', 'x_max', 'y_max'])].values\n        for j in range(len(temp)):\n            lbls.append(tt[j][0].astype(int))\n            b = list(np.round(tt[j][1:]))   # x,y, width, height\n            # Currently our coordinates are x,w,l,h and we want x1,y1,x2,y2\n            # To convert it, we need to add our width and height to the respective x and y.\n            t1 = [b[1],b[0],b[3],b[2]]\n\n            temp_b.append(t1)\n        bbox.append(temp_b)\n        bbox.append(lbls)\n        chest2bbox[name] = bbox\n    return chest2bbox","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"chest2bbox = get_lbl_img(tr_df2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"coco_source = untar_data(URLs.COCO_TINY)\nimages, lbl_bbox = get_annotations(coco_source/'train.json')\nimg2bbox = dict(zip(images, lbl_bbox))\nimg2bbox","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"chest2bbox","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"getters = [lambda o: '../input/vinbigdata-resized-image-512/train'/o, lambda o: chest2bbox[o][0], lambda o: chest2bbox[o][1]]\nxray_dblk = DataBlock(blocks=(ImageBlock, BBoxBlock, BBoxLblBlock),\n                      get_items=get_image_files,\n                      splitter=RandomSplitter(),\n                      #getters = getters,\n                      get_y=[lambda o: chest2bbox[o.name][0], lambda o: chest2bbox[o.name][1]],\n                      #get_y = lambda o: chest2bbox[Path(o).name] ,\n                      item_tfms=Resize(128),\n                      batch_tfms=aug_transforms(),\n                 n_inp=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dls = xray_dblk.dataloaders('../input/vinbigdata-resized-image-512/train')\ndls.show_batch(max_n=9)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## And the data loader is working!\n\nThe above code blocks are way messy, will clean it up later.\n\n\n## I'm having trouble working through the learner... \n\nBounding boxes are a bit complex, so I was trying to get the code from the below tutorial working, but no luck so far. Hoping to have some more time over the weekend (Feb 27-28), so hopefully I can get the below code working.\n\nhttps://github.com/muellerzr/Practical-Deep-Learning-for-Coders-2.0/blob/master/Computer%20Vision/06_Object_Detection.ipynb"},{"metadata":{"trusted":true},"cell_type":"code","source":"!git clone https://github.com/muellerzr/Practical-Deep-Learning-for-Coders-2.0.git\n%cd \"Practical-Deep-Learning-for-Coders-2.0/Computer Vision\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from imports import *","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"encoder = create_body(resnet34, pretrained=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"get_c(dls) #how many classes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"arch = RetinaNet(encoder, get_c(dls), final_bias=-4)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"create_head(124, 4)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"arch.smoothers","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"arch.classifier","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"arch.box_regressor","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ratios = [1/2,1,2]\nscales = [1,2**(-1/3), 2**(-2/3)]\ncrit = RetinaNetFocalLoss(scales=scales, ratios=ratios)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def _retinanet_split(m): return L(m.encoder,nn.Sequential(m.c5top6, m.p6top7, m.merges, m.smoothers, m.classifier, m.box_regressor)).map(params)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn = Learner(dls, arch, loss_func=crit, splitter=_retinanet_split)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.freeze()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%cd -","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#learn.fit_one_cycle(10, slice(le-5, le-4))\nlearn.lr_find()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}