{"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":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport os                                   # Iterate over dataset directories\nimport numpy as np                          # Linear algebra\nimport pandas as pd                         # Data processing (read labels CSV)\nimport cv2 as cv                            # Opencv for image files\nimport pydicom                              # Read dcm files\nfrom sklearn.cluster import MiniBatchKMeans # Create bag of visual words\nfrom sklearn.svm import SVC                 # Classifier\nimport pickle                               # Serialize and save features extracted from dataset images","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-09-18T16:43:51.005296Z","iopub.execute_input":"2021-09-18T16:43:51.006027Z","iopub.status.idle":"2021-09-18T16:43:52.37201Z","shell.execute_reply.started":"2021-09-18T16:43:51.005921Z","shell.execute_reply":"2021-09-18T16:43:52.371112Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Helper function","metadata":{}},{"cell_type":"code","source":"# Function to convert dcm pixel array to 8-bit grayscale image\ndef dcmToGray(dcm):\n    image = dcm.pixel_array\n    if np.amax(image) != 0:\n        gray = np.uint8(image/np.amax(image)*255)\n    else:\n        gray = np.uint8(image)\n    return gray","metadata":{"execution":{"iopub.status.busy":"2021-09-18T16:43:52.374197Z","iopub.execute_input":"2021-09-18T16:43:52.374526Z","iopub.status.idle":"2021-09-18T16:43:52.381607Z","shell.execute_reply.started":"2021-09-18T16:43:52.374484Z","shell.execute_reply":"2021-09-18T16:43:52.380912Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Important constants","metadata":{}},{"cell_type":"code","source":"# Paths to training and test data\ntrain_path =  \"../input/rsna-miccai-brain-tumor-radiogenomic-classification/train\"\ntest_path  = \"../input/rsna-miccai-brain-tumor-radiogenomic-classification/test\"\n\n# Subdirectories inside each directory of dataset\nsubdirs = [\"/FLAIR\", \"/T1w\", \"/T1wCE\", \"/T2w\"]\n\n# Sizes of training and test set\ntrain_size = len(next(os.walk(train_path))[1])\ntest_size  = len(next(os.walk(test_path))[1])\n\n# Size of an image descriptor (e.g. 128 for SIFT, 32 for ORB)\ndescriptor_size = 32\n\n# Feature detector\ndetector = cv.ORB_create(64)\n\n# Size of visual vocabulary\nvocab_size = 2000","metadata":{"execution":{"iopub.status.busy":"2021-09-18T16:43:52.382596Z","iopub.execute_input":"2021-09-18T16:43:52.383361Z","iopub.status.idle":"2021-09-18T16:43:52.446892Z","shell.execute_reply.started":"2021-09-18T16:43:52.383317Z","shell.execute_reply":"2021-09-18T16:43:52.446034Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Creating vocabulary of visual words","metadata":{}},{"cell_type":"code","source":"# Populating array of visual features with the descriptors computed by the defined detector\n\n# Each element of this list is an array of all the descriptor arrays\n# computed by the detector for every image of each sample.\nfeatures_per_sample = []\n\ni = 0\nwhile(len(features_per_sample) < train_size):\n    # Current directory\n    curr_dir = train_path + '/{0:05d}'.format(i)\n    \n    i += 1\n    \n    # If the there is no such directory, continue to the next one\n    if not os.path.exists(curr_dir):\n        continue\n        \n    # Array of descriptor array for each image of current sample\n    curr_features = np.array([]).reshape(0,descriptor_size)\n        \n    # Process the images from each subdirectory in the current dir\n    for subdir in subdirs:\n        curr_subdir = curr_dir+subdir\n        for filename in os.listdir(curr_subdir):\n            dcm  = pydicom.dcmread(curr_subdir+'/'+filename)\n            gray = dcmToGray(dcm)\n            keypoints, descriptors = detector.detectAndCompute(gray,None)\n            if descriptors is not None:\n                curr_features = np.vstack([curr_features, descriptors])\n                \n    features_per_sample.append(curr_features)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T16:43:52.448646Z","iopub.execute_input":"2021-09-18T16:43:52.449071Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Group all features to run clustering in order to get bag of visual words\nall_features = np.array([]).reshape(0,descriptor_size)\nfor sample_features in features_per_sample:\n    all_features = np.vstack([all_features, sample_features])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Clustering all the features obtained with the detector\n# The centroids will be the visual words of the vocabulary\nkmeans = MiniBatchKMeans(n_clusters = vocab_size,\n                         batch_size = vocab_size//10,\n                         verbose    = False, \n                         init       = 'k-means++',\n                         n_init     = 3,\n                         max_iter   = 1)\n\nvocab = kmeans.fit(all_features)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create the visual words histogram for each sample","metadata":{}},{"cell_type":"code","source":"# Training set\nhistograms = []\nfor sample_features in features_per_sample:\n    \n    sample_hist = np.zeros(vocab_size)\n    n_features  = sample_features.shape[0]\n    \n    visual_word_indexes = vocab.predict(sample_features)\n    for index in visual_word_indexes:\n        sample_hist[index] += 1/n_features\n        \n    histograms.append(sample_hist)\n\nX_train = np.array(histograms)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Test set\nhistograms = []\ntest_sample_ids = []\ni = 0\nwhile(len(histograms) < test_size):\n    # Current directory\n    curr_dir = test_path + '/{0:05d}'.format(i)\n    \n    i += 1\n    \n    # If the there is no such directory, continue to the next one\n    if not os.path.exists(curr_dir):\n        continue\n        \n    test_sample_ids.append('{0:05d}'.format(i-1))\n        \n    # Array of descriptor array for each image of current sample\n    curr_features = np.array([]).reshape(0,descriptor_size)\n        \n    # Process the images from each subdirectory in the current dir\n    for subdir in subdirs:\n        curr_subdir = curr_dir+subdir\n        for filename in os.listdir(curr_subdir):\n            dcm  = pydicom.dcmread(curr_subdir+'/'+filename)\n            gray = dcmToGray(dcm)\n            keypoints, descriptors = detector.detectAndCompute(gray,None)\n            if descriptors is not None:\n                curr_features = np.vstack([curr_features, descriptors])\n                \n    sample_hist = np.zeros(vocab_size)\n    n_features  = curr_features.shape[0]\n    \n    visual_word_indexes = vocab.predict(curr_features)\n    for index in visual_word_indexes:\n        sample_hist[index] += 1/n_features\n        \n    histograms.append(sample_hist)\n    \nX_test = np.array(histograms)\ntest_sample_ids = np.array(test_sample_ids)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Classifier","metadata":{}},{"cell_type":"code","source":"# Reading labels\nlabels = pd.read_csv(\"../input/rsna-miccai-brain-tumor-radiogenomic-classification/train_labels.csv\")\nlabels = labels.iloc[:,1].values\n\ntrain_labels = labels[0:int(0.8*train_size)]\nvalid_labels = labels[int(0.8*train_size):train_size]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Reading training, validation and test data\nX_valid = X_train[int(0.8*train_size):train_size,:]\nX_train = X_train[0:int(0.8*train_size),:]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fitting classifier\nsvc = SVC(probability=True)\nsvc.fit(X_train, train_labels)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Validating\nscore = svc.score(X_valid, valid_labels)\nprint(score)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Predictions\npred = svc.predict_proba(X_test)\nprint(pred)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Write submission file\nsubmission = pd.DataFrame({\"BraTS21ID\": test_sample_ids, \"MGMT_value\": pred[:,1]})\nsubmission.to_csv(\"./submission.csv\", index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}