{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":45867,"databundleVersionId":6924515,"sourceType":"competition"},{"sourceId":6774553,"sourceType":"datasetVersion","datasetId":3898019},{"sourceId":6961579,"sourceType":"datasetVersion","datasetId":3948617},{"sourceId":193,"sourceType":"modelInstanceVersion","modelInstanceId":137},{"sourceId":3213,"sourceType":"modelInstanceVersion","modelInstanceId":2390}],"dockerImageVersionId":30558,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!ls /kaggle/input/pyvips-python-and-deb-package-gpu\n# intall the deb packages\n!yes | dpkg -i --force-depends /kaggle/input/pyvips-python-and-deb-package-gpu/linux_packages/archives/*.deb\n# install the python wrapper\n!pip install pyvips -f /kaggle/input/pyvips-python-and-deb-package-gpu/python_packages/ --no-index\n!pip list | grep pyvips","metadata":{"execution":{"iopub.status.busy":"2023-11-14T00:58:38.42144Z","iopub.execute_input":"2023-11-14T00:58:38.421706Z","iopub.status.idle":"2023-11-14T01:00:05.568148Z","shell.execute_reply.started":"2023-11-14T00:58:38.42168Z","shell.execute_reply":"2023-11-14T01:00:05.566969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os, glob\n\nos.environ['VIPS_CONCURRENCY'] = '4'\nos.environ['VIPS_DISC_THRESHOLD'] = '15gb'","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:00:05.570402Z","iopub.execute_input":"2023-11-14T01:00:05.570727Z","iopub.status.idle":"2023-11-14T01:00:05.575942Z","shell.execute_reply.started":"2023-11-14T01:00:05.570699Z","shell.execute_reply":"2023-11-14T01:00:05.574894Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nimport tensorflow_hub as hub\nimport keras\n\nfrom keras.models import Sequential\nfrom keras.metrics import Recall\nfrom keras.layers import Dense, Dropout, BatchNormalization, Activation\nfrom keras.optimizers import Adam\nfrom keras.utils import to_categorical\nfrom keras.applications.resnet_v2 import preprocess_input\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint\n\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array\n\nfrom sklearn.metrics import confusion_matrix, classification_report\n\nimport os\nimport gc\nimport math\nimport seaborn as sns\nimport PIL\nimport cv2 as cv\nimport numpy as np\nimport pandas as pd\nimport pyvips\n\nfrom matplotlib import pyplot as plt\n\nINPUT_PATH = '/kaggle/input/'\nWORKING_PATH = '/kaggle/working/'\nROOT_PATH = '/kaggle/input/UBC-OCEAN/'\nIMAGES_PATH = '/kaggle/input/UBC-OCEAN/train_images/'\nTHUMBNAILS_PATH = '/kaggle/input/UBC-OCEAN/train_thumbnails/'\nTILES_PATH = '/kaggle/input/ubc-ocean-larges-crop/tile_large_images/'\n\nTEST_IMAGES_PATH = '/kaggle/input/UBC-OCEAN/test_images/'\nTEST_THUMBNAILS_PATH = '/kaggle/input/UBC-OCEAN/test_thumbnails/'\n\nMODEL = '/kaggle/input/efficientnet-v2/tensorflow2/imagenet1k-b0-classification/2'\nWEIGHTS = '/kaggle/input/cnn-v3/efficientnet_weights_large.h5'\n\nZOOM = 40\nTHRESHOLD = 2\nSAMPLE = 15\nSCALE = 80\nKILOBYTES = 1024\nSIZE = (224, 224)\nLABELS = ['CC', 'EC', 'HGSC', 'LGSC', 'MC']","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:04:43.73881Z","iopub.execute_input":"2023-11-14T01:04:43.73978Z","iopub.status.idle":"2023-11-14T01:04:43.750634Z","shell.execute_reply.started":"2023-11-14T01:04:43.739745Z","shell.execute_reply":"2023-11-14T01:04:43.749511Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_ = hub.KerasLayer(MODEL, input_shape=(*SIZE, 3))\n\nmodel = Sequential([\n    model_,\n    Dense(5012),\n    BatchNormalization(),\n    Activation('relu'),\n    Dropout(0.25),\n    Dense(1028),\n    BatchNormalization(),\n    Activation('relu'),\n    Dropout(0.25),\n    Dense(5, activation='softmax')\n])\n\nmodel.load_weights(WEIGHTS)","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:00:16.672232Z","iopub.execute_input":"2023-11-14T01:00:16.672732Z","iopub.status.idle":"2023-11-14T01:00:29.351532Z","shell.execute_reply.started":"2023-11-14T01:00:16.672705Z","shell.execute_reply":"2023-11-14T01:00:29.350468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_is_tma(dim, image_path=''):\n    (h, w) = dim\n    area = h * w\n    return area / (KILOBYTES ** 3) < 0.1 and not image_path.__contains__('thumbnail')\n\ndef get_zoom(dim, zoom, image_path=''):\n    (h, w) = dim\n\n    is_tma = get_is_tma(dim, image_path)\n\n    min_side = math.ceil(min(h, w) / (math.ceil(zoom // 20) if is_tma else zoom))\n\n    amount_h = math.ceil(h / min_side)\n    amount_w = math.ceil(w / min_side)\n\n    num_squares = amount_h * amount_w\n\n    return num_squares, min_side, is_tma\n\ndef is_within(coord, size_square, size):\n    (y, x) = coord\n    (h, w) = size\n    (square_h, square_w) = size_square\n    return y >= 0 and x >= 0 and y + square_h <= h and x + square_w <= w\n\ndef get_entropy(img):\n    r = cv.split(img)[0]\n\n    hist = cv.calcHist([r], [0], None, [256], [0, 256])\n    hist /= hist.sum()\n    \n    return -np.sum(hist * np.log2(hist + np.finfo(float).eps))","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:00:29.353145Z","iopub.execute_input":"2023-11-14T01:00:29.353518Z","iopub.status.idle":"2023-11-14T01:00:29.36308Z","shell.execute_reply.started":"2023-11-14T01:00:29.353481Z","shell.execute_reply":"2023-11-14T01:00:29.362144Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def point_adjustment(points, size_square, size):\n    (h, w) = size\n    (square_h, square_w) = size_square\n\n    list_is_within = np.array([is_within(point, size_square, size) for point in points])\n    index_without = np.argwhere(list_is_within == False)\n\n    for [index] in index_without:\n        (y, x) = points[index]\n\n        left_outside = x * -1\n        right_outside = (x + square_w) - w\n        top_outside = y * -1\n        buttom_outside = (y + square_h) - h\n\n        if left_outside > 0:\n            x = 0\n        \n        if right_outside > 0:\n            x -= right_outside\n\n        if top_outside > 0:\n            y = 0\n        \n        if buttom_outside > 0:\n            y -= buttom_outside\n\n        points[index] = (y, x)\n\n    return points","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:00:29.364356Z","iopub.execute_input":"2023-11-14T01:00:29.364656Z","iopub.status.idle":"2023-11-14T01:00:29.374956Z","shell.execute_reply.started":"2023-11-14T01:00:29.364633Z","shell.execute_reply":"2023-11-14T01:00:29.374072Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_hotmap(img, dim, num_tiles):\n    (square_h, square_w) = dim\n    ratio_h, ratio_w = math.ceil(square_h / 2), math.ceil(square_w / 2)\n\n    img_hsv = cv.cvtColor(img, cv.COLOR_RGB2HSV)\n    lower = np.array([110,0,150])\n    upper = np.array([170,250,205])\n    mask = cv.inRange(img_hsv, lower, upper)\n    \n    kernel = np.ones((square_h, square_w), np.float32) / (square_h * square_w)\n    mask = cv.filter2D(mask.astype(np.uint8), -1, kernel, borderType=cv.BORDER_CONSTANT)\n\n    hotmap = []\n\n    for _ in range(num_tiles):\n        coord = np.unravel_index(np.argmax(mask), mask.shape)\n        hotmap.append(list(coord))\n        cv.rectangle(mask, (coord[1] - ratio_h, coord[0] - ratio_w), (coord[1] + ratio_h, coord[0] + ratio_w), 0, -1)\n\n    return hotmap, mask","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:00:29.376157Z","iopub.execute_input":"2023-11-14T01:00:29.376448Z","iopub.status.idle":"2023-11-14T01:00:29.386079Z","shell.execute_reply.started":"2023-11-14T01:00:29.376426Z","shell.execute_reply":"2023-11-14T01:00:29.384993Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_tiles(image_path, size=(300,300), num_tiles=20, zoom=5, threshold=2, is_show=False):\n    image = pyvips.Image.new_from_file(image_path)\n    mul_h, mul_w = math.ceil(image.height / SCALE), math.ceil(image.width / SCALE)\n    img = image.thumbnail_image(mul_w, height=mul_h).numpy()[..., :3]\n\n    h, w = image.height, image.width\n\n    entropies = []\n    image_processed = []\n    coord_ = []\n\n    num_squares, min_side, _ = get_zoom((h, w), zoom, image_path)\n\n    if num_tiles == 0 or num_tiles > num_squares:\n        num_tiles = num_squares\n\n    (square_h, square_w) = (min_side, min_side)\n    ratio_h, ratio_w = square_h // 2, square_w // 2\n\n    segments, _ = get_hotmap(img, (math.ceil(square_h / SCALE), math.ceil(square_w / SCALE)), num_tiles)\n\n    segments = np.array(segments) * SCALE\n    segments[:, 0] -= ratio_h\n    segments[:, 1] -= ratio_w\n    \n    segments = point_adjustment((segments), (square_h, square_w), (h, w))\n\n    for coord in segments:\n        [y, x] = coord\n        y_min, x_min = math.ceil(y / SCALE), math.ceil(x / SCALE)\n        \n        img_tile = cv.resize(image.crop(x, y, square_w, square_h).numpy()[..., :3], size)\n\n        entropy = get_entropy(img_tile)\n\n        if entropy >= threshold:\n            entropies.append(entropy)\n            image_processed.append(img_tile)\n            coord_.append((x, y))\n            \n            if is_show:\n                cv.circle(img, (x_min + square_w // SCALE // 2, y_min + square_h // SCALE // 2), 1, (0, 255, 255), -1)\n                cv.rectangle(img, (x_min, y_min), (x_min + square_w // SCALE, y_min + square_h // SCALE), (255, 0, 0), 1)\n        \n        if len(entropies) >= num_tiles: break\n\n    entropies = np.array(entropies)\n    bests = np.argsort(-entropies)\n    entropies = entropies[bests]\n\n    bests_ = []\n\n    if is_show:\n        _, axis = plt.subplots(1, 5, figsize=(15,15))\n\n    for j, best in enumerate(bests):\n        img_ = image_processed[best]\n        bests_.append(img_)\n        (x, y) = coord_[best]\n\n        if is_show and j < 5:\n            cv.putText(img, f'({x}, {y})', (x // SCALE, y // SCALE), cv.FONT_HERSHEY_COMPLEX_SMALL, 0.5, (0,0,255), 1, cv.LINE_AA)\n            axis[j].imshow(img_)\n\n    if is_show:\n        plt.figure()\n        plt.imshow(img)\n        plt.show()\n\n    return bests_","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:00:29.387471Z","iopub.execute_input":"2023-11-14T01:00:29.387803Z","iopub.status.idle":"2023-11-14T01:00:29.404889Z","shell.execute_reply.started":"2023-11-14T01:00:29.387773Z","shell.execute_reply":"2023-11-14T01:00:29.403932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(f'{ROOT_PATH}test.csv')\ndf['label'] = ['HGSC'] * len(df)","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:00:29.406052Z","iopub.execute_input":"2023-11-14T01:00:29.406923Z","iopub.status.idle":"2023-11-14T01:00:29.434322Z","shell.execute_reply.started":"2023-11-14T01:00:29.406895Z","shell.execute_reply":"2023-11-14T01:00:29.433613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n\ndefault_dir = os.listdir(TEST_IMAGES_PATH)\n\npredict = []\nfor _, row in df.iterrows():\n    row = dict(row)\n    \n    image_name = f'{row[\"image_id\"]}.png'\n    if image_name in default_dir:\n        tiles = get_tiles(f'{TEST_IMAGES_PATH}{image_name}', num_tiles=SAMPLE, zoom=ZOOM, size=SIZE)\n    else:\n        tiles = get_tiles(f'{TEST_THUMBNAILS_PATH}{row[\"image_id\"]}_thumbnail.png', num_tiles=SAMPLE, zoom=ZOOM, size=SIZE)\n    \n    if not len(tiles):\n        predict.append(row)\n        continue\n        \n    X_test_ = [preprocess_input(tile).reshape(1, *SIZE, 3) for tile in tiles]\n    y_pred_i = [model.predict(x) for x in X_test_]\n    predict_prev = np.sum(y_pred_i, axis=0)\n    \n    row['label'] = LABELS[np.argmax(predict_prev)]\n    predict.append(row)\n    \n    del X_test_\n    gc.collect()","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:08:28.673976Z","iopub.execute_input":"2023-11-14T01:08:28.674816Z","iopub.status.idle":"2023-11-14T01:08:44.747834Z","shell.execute_reply.started":"2023-11-14T01:08:28.674781Z","shell.execute_reply":"2023-11-14T01:08:44.746794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_predict = pd.DataFrame(predict)\ndf_predict[['image_id', 'label']].to_csv(f\"{WORKING_PATH}submission.csv\", index=False)\n\n!head submission.csv","metadata":{"execution":{"iopub.status.busy":"2023-11-14T01:08:46.499433Z","iopub.execute_input":"2023-11-14T01:08:46.500193Z","iopub.status.idle":"2023-11-14T01:08:47.585586Z","shell.execute_reply.started":"2023-11-14T01:08:46.500157Z","shell.execute_reply":"2023-11-14T01:08:47.584424Z"},"trusted":true},"execution_count":null,"outputs":[]}]}