{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":19989,"databundleVersionId":1160143,"sourceType":"competition"},{"sourceId":1154184,"sourceType":"datasetVersion","datasetId":652413},{"sourceId":1164586,"sourceType":"datasetVersion","datasetId":659763},{"sourceId":1164617,"sourceType":"datasetVersion","datasetId":659784},{"sourceId":1219292,"sourceType":"datasetVersion","datasetId":648709},{"sourceId":5730479,"sourceType":"datasetVersion","datasetId":3295862},{"sourceId":5801371,"sourceType":"datasetVersion","datasetId":3331748},{"sourceId":6024453,"sourceType":"datasetVersion","datasetId":648967},{"sourceId":6930197,"sourceType":"datasetVersion","datasetId":3979218},{"sourceId":7073794,"sourceType":"datasetVersion","datasetId":4074101},{"sourceId":7090203,"sourceType":"datasetVersion","datasetId":4085630},{"sourceId":7097340,"sourceType":"datasetVersion","datasetId":4090682},{"sourceId":7131194,"sourceType":"datasetVersion","datasetId":4114369},{"sourceId":7155279,"sourceType":"datasetVersion","datasetId":4132088},{"sourceId":7983332,"sourceType":"datasetVersion","datasetId":4694596},{"sourceId":8017874,"sourceType":"datasetVersion","datasetId":4724154},{"sourceId":8018002,"sourceType":"datasetVersion","datasetId":4724253},{"sourceId":8021428,"sourceType":"datasetVersion","datasetId":4726728},{"sourceId":8027577,"sourceType":"datasetVersion","datasetId":4731194},{"sourceId":8051791,"sourceType":"datasetVersion","datasetId":4748414},{"sourceId":8055438,"sourceType":"datasetVersion","datasetId":4751026},{"sourceId":8059334,"sourceType":"datasetVersion","datasetId":4753766}],"dockerImageVersionId":29928,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Inference EfficientDet\n\nHi everyone!\n\nMy name is Alex Shonenkov, I am DL/NLP/CV/TS research engineer. Especially I am in Love with NLP & DL.\n\nRecently I have created kernel for this competition about Weighted Boxes Fusion:\n- [WBF approach for ensemble](https://www.kaggle.com/shonenkov/wbf-approach-for-ensemble)\n\n\nI hope it is useful for you, my friends! If you didn't read this kernel, don't forget to do it! :)\n\n\nHere I would like to share with you inference part for my training kernel:\n\n- [[Training] EfficientDet](https://www.kaggle.com/shonenkov/training-efficientdet)","metadata":{}},{"cell_type":"markdown","source":"In this kernel used github repos [efficientdet-pytorch](https://github.com/rwightman/efficientdet-pytorch) and [pytorch-image-models](https://github.com/rwightman/pytorch-image-models) by [@rwightman](https://www.kaggle.com/rwightman). Don't forget add stars ;)","metadata":{}},{"cell_type":"code","source":"!pip install --no-deps '../input/timm-package/timm-0.1.26-py3-none-any.whl' > /dev/null\n!pip install --no-deps '../input/pycocotools/pycocotools-2.0-cp37-cp37m-linux_x86_64.whl' > /dev/null","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","execution":{"iopub.status.busy":"2024-04-08T03:50:44.474558Z","iopub.execute_input":"2024-04-08T03:50:44.474937Z","iopub.status.idle":"2024-04-08T03:51:31.280613Z","shell.execute_reply.started":"2024-04-08T03:50:44.474903Z","shell.execute_reply":"2024-04-08T03:51:31.279514Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import sys\n\nsys.path.insert(0, \"../input/timm-efficientdet-pytorch\")\nsys.path.insert(0, \"../input/omegaconf\")\nsys.path.insert(0, \"../input/weightedboxesfusion\")\nsys.path.insert(0, \"../input/my-ablu\")\n# sys.path.insert(0, \"../input/weighted-boxes-fusion-104\")\n\nfrom ensemble_boxes import *\nimport os\nimport torch\nimport random\nimport numpy as np\nimport torch.nn.functional as F\nfrom scipy.ndimage import zoom\nimport pandas as pd\nfrom glob import glob\nfrom torch.utils.data import Dataset,DataLoader\nimport albumentations as A\n# from albumentations import read_rgb_image \nfrom albu import (clipped,\n                            get_opencv_dtype_from_numpy,\n                            is_grayscale_image,\n                            is_multispectral_image,\n                            preserve_shape,)\n#                             read_rgb_image,) \nfrom albumentations.pytorch.transforms import ToTensorV2\nfrom typing import List, Tuple, Union, Callable\nfrom albumentations import to_tuple\nimport cv2\nimport gc\nimport shutil as sh\nfrom matplotlib import pyplot as plt\nfrom effdet import get_efficientdet_config, EfficientDet, DetBenchEval\nfrom effdet.efficientdet import HeadNet\n\n# importing the joblib libraray\nimport joblib","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:51:31.284148Z","iopub.execute_input":"2024-04-08T03:51:31.284541Z","iopub.status.idle":"2024-04-08T03:51:34.618695Z","shell.execute_reply.started":"2024-04-08T03:51:31.284506Z","shell.execute_reply":"2024-04-08T03:51:34.617848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def read_rgb_image(path):\n    image = cv2.imread(path, cv2.IMREAD_COLOR)\n    return cv2.cvtColor(image, cv2.COLOR_BGR2RGB) #.astype(np.float32)","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:51:34.619845Z","iopub.execute_input":"2024-04-08T03:51:34.620151Z","iopub.status.idle":"2024-04-08T03:51:34.624808Z","shell.execute_reply.started":"2024-04-08T03:51:34.620122Z","shell.execute_reply":"2024-04-08T03:51:34.623907Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !unzip /kaggle/input/may-8-effdet/16EJAZRnEgZ0ktG54NTzGHx_1k0PWTPSJ","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:04.759483Z","iopub.execute_input":"2024-04-08T03:53:04.759895Z","iopub.status.idle":"2024-04-08T03:53:04.763590Z","shell.execute_reply.started":"2024-04-08T03:53:04.759860Z","shell.execute_reply":"2024-04-08T03:53:04.762532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv(\"/kaggle/input/global-wheat-detection/train.csv\")\n\ntarget_col = train_df.drop_duplicates(['image_id'])['source'].value_counts().sort_values()[:6].index\ntrain_drop_dup = train_df.drop_duplicates(['image_id'])\n\ntarget_id = []\nfor col in target_col:\n    ids = np.random.choice(train_drop_dup[train_drop_dup['source'] == col]['image_id'], 3)\n    target_id += [f\"/kaggle/input/global-wheat-detection/train/{id}.jpg\" for id in ids]\n    \n# test_file_path = glob('/kaggle/input/global-wheat-detection/test/*')\n# np.random.shuffle(test_file_path)\ntarget_path = target_id\nnp.random.shuffle(target_path)\n\n\nreference_imgs = []\nfor target in target_path:\n    reference_imgs.append(read_rgb_image(target))\n                  \n                  ","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:05.325153Z","iopub.execute_input":"2024-04-08T03:53:05.325516Z","iopub.status.idle":"2024-04-08T03:53:06.239221Z","shell.execute_reply.started":"2024-04-08T03:53:05.325478Z","shell.execute_reply":"2024-04-08T03:53:06.238337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class AdaptiveABGamma(A.ImageOnlyTransform):\n    \"\"\"\n    Args:\n        alpha_limit:\n        beta_limit:\n        patch_size:\n        gamma_limit (float or (float, float)): If gamma_limit is a single float value,\n            the range will be (-gamma_limit, gamma_limit). Default: (80, 120).\n\n    Targets:\n        image\n\n    Image types:\n        uint8, float32\n    \"\"\"\n\n    def __init__(self, patch_size=32, alpha_limit=(1.2, 3.0), beta_limit=(-0.1, 2.0), gamma_limit=(0.8, 3.0), max_value=255.0, num=1, always_apply=False, p=0.5):\n        super(AdaptiveABGamma, self).__init__(always_apply, p)\n        self.alpha_limit = to_tuple(alpha_limit)\n        self.beta_limit = to_tuple(beta_limit)\n        self.gamma_limit = to_tuple(gamma_limit)\n        self.patch_size = patch_size\n        self.max = max_value\n        self.num = num\n\n    def apply(self, image, patch_size=32, alpha=1.2, beta=-0.1, gamma=1, max_value=1, **params):\n        img = image.copy()\n        img = cv2.resize(img, dsize=(image.shape[1]//self.num, image.shape[0]//self.num))\n        src_image_transformed = adaptive_alpha_beta_gamma_correction(image=image, patch_size=patch_size, alpha_range=alpha, beta_range=beta, gamma_range=gamma, max=max_value) \n        # F.gamma_transform(img, gamma=gamma)\n        if type(src_image_transformed) == torch.Tensor:\n            src_image_transformed = src_image_transformed.cpu().numpy()\n        return cv2.resize(src_image_transformed, dsize=(img.shape[1]*self.num, img.shape[0]*self.num))\n\n    def get_params(self):\n        return {\"alpha\": (self.alpha_limit[0], self.alpha_limit[1]),\n                \"beta\": (self.beta_limit[0], self.beta_limit[1]),\n                \"gamma\": (self.gamma_limit[0], self.gamma_limit[1]),\n                \"patch_size\": self.patch_size,\n                \"max_value\" : self.max}\n\n    def get_transform_init_args_names(self):\n        return (\"patch_size\",\"alpha_limit\", \"beta_limit\", \"gamma_limit\", \"max\")","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:06.330460Z","iopub.execute_input":"2024-04-08T03:53:06.330801Z","iopub.status.idle":"2024-04-08T03:53:06.348409Z","shell.execute_reply.started":"2024-04-08T03:53:06.330771Z","shell.execute_reply":"2024-04-08T03:53:06.347536Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ndef adaptive_alpha_beta_gamma_correction(image, patch_size, alpha_range, beta_range, gamma_range, max=255.0):\n    # Convert image to float32 for correction\n    if type(image) == torch.Tensor:\n        image = image.cpu().numpy()\n    image = image.astype(np.float32) / max\n    \n    # Calculate local statistics\n    img_mean = image.mean()\n    img_std = image.std()\n\n    # Split the image into patches\n    height, width = image.shape[:2]\n    num_rows = height // patch_size\n    num_cols = width // patch_size\n\n    for r in range(0, num_rows):\n        for c in range(0, num_cols):\n            # Get the current patch\n            patch = image[r * patch_size:(r + 1) * patch_size,\n                          c * patch_size:(c + 1) * patch_size]\n\n            # Calculate local statistics\n            mean = np.mean(patch)\n            std = np.std(patch)\n            var = np.var(patch)\n\n            # Calculate the alpha, beta, and gamma values based on local statistics\n#             a = mean /std\n            a = (img_std - std)/(img_mean - mean)\n            # a = mean**2 * (((1 - mean) / var) - (1 / mean))\n#             b =  0.5 - std\n            b = (img_std - std)\n            # b = a * ((1 / mean) - 1)\n#             g = mean/std\n            g = (img_std - std)/mean\n            # g = np.log(mean) / np.log(std) #1.0 - np.log(std)\n            alpha = np.clip(a, alpha_range[0], alpha_range[1])\n            beta = np.clip(b, beta_range[0], beta_range[1])\n            gamma = np.clip(g, gamma_range[0], gamma_range[1])\n#             print(alpha, beta, gamma)\n            # alpha = np.clip(mean / 0.5, alpha_range[0], alpha_range[1])\n            # beta = np.clip(0.5 - std / 2.0, beta_range[0], beta_range[1])\n            # gamma = np.clip(mean / 0.5, gamma_range[0], gamma_range[1])\n\n\n            # Apply alpha, beta, and gamma correction to the patch\n            # clipped = np.clip(alpha * patch + beta,0,1)\n            # corrected_patch = np.power(clipped, 1.0 / gamma) #, dtype=complex)\n            # clipped = alpha * patch + beta #np.clip(alpha * patch + beta,0,1)\n            corrected_patch = np.power(alpha * patch + beta, 1.0 / gamma, dtype=complex).real.astype(np.float32)\n            corrected_patch = np.nan_to_num(corrected_patch)\n            \n            # Replace the patch with the corrected patch\n            image[r * patch_size:(r + 1) * patch_size,\n                  c * patch_size:(c + 1) * patch_size] = corrected_patch\n\n    # Convert the image back to uint8\n    # image = (image * max).clip(0, max).astype(np.uint8)\n    image = image.astype(np.float32)\n#     image = torch.as_tensor(image).cuda()\n    return image\n\n\n\nimage = cv2.imread(f'{target_path[7]}', cv2.IMREAD_COLOR)\nimage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) #.astype(np.float32)\n\n\nfig, ax = plt.subplots(1, 2, figsize=(16, 8))\n\nax[0].set_axis_off()\nax[0].imshow(image)\n\naug = A.Compose([\n                AdaptiveABGamma(patch_size=128,\n                                alpha_limit=(0.8, 1.5), beta_limit=(-0.05, 0.25), gamma_limit=(0.8, 1.5),\n                                max_value=255.0,\n                                num=2,\n                                always_apply=True, p=1),\n\n                        ])\nres = aug(image=image)['image']\n# plt.imshow(res)\nax[1].set_axis_off()\nax[1].imshow(res)","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:09.979979Z","iopub.execute_input":"2024-04-08T03:53:09.980330Z","iopub.status.idle":"2024-04-08T03:53:10.918695Z","shell.execute_reply.started":"2024-04-08T03:53:09.980301Z","shell.execute_reply":"2024-04-08T03:53:10.917712Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image.shape","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:10.920519Z","iopub.execute_input":"2024-04-08T03:53:10.920812Z","iopub.status.idle":"2024-04-08T03:53:10.926164Z","shell.execute_reply.started":"2024-04-08T03:53:10.920781Z","shell.execute_reply":"2024-04-08T03:53:10.925441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# def adaptive_alpha_beta_gamma_correction(image, patch_size, alpha_range, beta_range, gamma_range, max=255.0):\n#     # Convert image to float32 for correction\n#     image = image.astype(np.float32) / max\n\n#     # Split the image into patches\n#     height, width = image.shape[:2]\n#     num_rows = height // patch_size\n#     num_cols = width // patch_size\n\n#     for r in range(0, num_rows):\n#         for c in range(0, num_cols):\n#             # Get the current patch\n#             patch = image[r * patch_size:(r + 1) * patch_size,\n#                           c * patch_size:(c + 1) * patch_size]\n\n#             # Calculate local statistics\n#             mean = np.mean(patch)\n#             std = np.std(patch)\n\n#             # Calculate the alpha, beta, and gamma values based on local statistics\n#             alpha = np.clip(mean / 0.5, alpha_range[0], alpha_range[1])\n#             beta = np.clip(0.5 - std / 2.0, beta_range[0], beta_range[1])\n#             gamma = np.clip(mean / 0.5, gamma_range[0], gamma_range[1])\n\n#             # Apply alpha, beta, and gamma correction to the patch\n#             corrected_patch = np.power(alpha * patch + beta, 1.0 / gamma)\n\n#             # Replace the patch with the corrected patch\n#             image[r * patch_size:(r + 1) * patch_size,\n#                   c * patch_size:(c + 1) * patch_size] = corrected_patch\n\n#     # Convert the image back to uint8\n#     # image = (image * max).clip(0, max).astype(np.uint8)\n#     image = image.astype(np.float32)\n\n#     return image\n\n\n\n# image = cv2.imread(f'{target_path[1]}', cv2.IMREAD_COLOR)\n# image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) #.astype(np.float32)\n# aug = A.Compose([\n#                 AdaptiveABGamma(patch_size=16, \n#                                 alpha_limit=(2.1, 2.9), beta_limit=(-0.1, 0.2), gamma_limit=(0.5, 0.8), \n#                                 max_value=255.0,\n#                                 num=2,\n#                                 always_apply=True, p=1),\n             \n#                         ])\n# res = aug(image=image)['image']\n# plt.imshow(res)","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:11.028375Z","iopub.execute_input":"2024-04-08T03:53:11.028748Z","iopub.status.idle":"2024-04-08T03:53:11.034055Z","shell.execute_reply.started":"2024-04-08T03:53:11.028712Z","shell.execute_reply":"2024-04-08T03:53:11.032822Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def box_map(img, r):\n#     h = int(r / 2)\n    \n#     # Check if the input is a batch of images or a single image\n#     if img.ndim == 4:\n#         # Handle batch of images\n#         batch_size, height, width, channels = img.shape\n#         box_mean = np.zeros(img.shape)\n\n#         # Pad each image in the batch\n#         for i in range(batch_size):\n#             img = np.pad(img[i], ((h,), (h,), (0,)), 'reflect')\n#             # Calculate the box mean for each pixel in the batch image\n#             for j in range(height):\n#                 for k in range(width):\n#                     box_mean[i, j, k] = img[j:j + r, k:k + r].mean()\n\n#         return box_mean\n\n#     else:\n#         # Handle single RGB image\n#         height, width, channels = img.shape\n#         box_mean = np.zeros((height, width, channels))\n         \n#         if img.ndim == 2:\n#             img = np.pad(img, ((h,),(h,)), 'reflect')\n#         else:\n#             # Pad the image\n#             img = np.pad(img, ((h,), (h,), (0,)), 'reflect')\n    \n#         # Calculate the box mean for each pixel in the image\n#         for i in range(height):\n#             for j in range(width):\n#                 box_mean[i, j] = img[i:i + r, j:j + r].mean()\n\n#         return box_mean","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:11.292182Z","iopub.execute_input":"2024-04-08T03:53:11.292591Z","iopub.status.idle":"2024-04-08T03:53:11.297025Z","shell.execute_reply.started":"2024-04-08T03:53:11.292559Z","shell.execute_reply":"2024-04-08T03:53:11.296107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # def box_map(img, r):\n# #     h = int(r / 2)\n# #      # 2 D　image\n# #     box_mean = np.zeros(img.shape)\n# #     print(box_mean.shape)\n# #     if img.ndim == 2:\n# #         img = np.pad(img, ((h,),(h,)), 'reflect')\n# #     else:\n# #         img = np.pad(img, ((h,),(h,),(0,)), 'reflect')\n# #     for i in range(box_mean.shape[0]):\n# #         for j in range(box_mean.shape[1]):\n# #             box_mean[i, j] = img[i:i+r, j:j+r].mean()\n# #     return box_mean\n\n# def guided_filter(p, I, r, eps):\n#     # (x, y)\n\n#     I_mean = box_map(I, r)\n#     p_mean = box_map(p, r)\n\n#     corr_I = box_map(np.square(I), r)\n#     corr_Ip = box_map(I * p, r)\n\n#     var_I = corr_I - I_mean**2\n#     cov_Ip = corr_Ip - I_mean * p_mean\n\n#     a = cov_Ip / (var_I + eps)\n#     b = p_mean - a * I_mean\n\n#     a_mean = box_map(a, r)\n#     b_mean = box_map(b, r)\n\n#     for x in range(p.shape[0]):\n#         for y in range(p.shape[1]):\n#             a_mean[x, y] = a_mean[x:x+r, y:y+r].mean()\n#             b_mean[x, y] = b_mean[x:x+r, y:y+r].mean()\n\n#     q = a_mean * I + b_mean\n    \n#     return q, (a_mean, b_mean)\n\n# def Fast_guided_filter(p, I, r, s, eps, mode='linear'):\n#     # sample a dot from images every  **s** dots\n# #     print(I.shape)\n#     I_s = None\n#     p_s = None\n    \n#     if len(p.shape)>3:\n#         scale = np.array([p.shape[0],s, s, 1]).astype('float')\n#     else:\n#         scale = np.array([s, s, 1]).astype('float')\n#     # downsample\n#     p_s = zoom(p, 1 / scale)\n#     I_s = zoom(I, 1 / scale)\n\n#     r_s = int(r / s)\n\n\n#     _, ab_mean = guided_filter(p_s, I_s, r_s, eps)\n\n\n#     a_mean_s = ab_mean[0]\n#     b_mean_s = ab_mean[1]\n        \n#     #  upsample\n#     a_mean = zoom(a_mean_s, scale)\n#     b_mean = zoom(b_mean_s, scale)\n\n# #     print(a_mean.shape)\n# #     print(b_mean.shape)\n#     q = a_mean * I + b_mean\n\n#     return q","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:11.622341Z","iopub.execute_input":"2024-04-08T03:53:11.622712Z","iopub.status.idle":"2024-04-08T03:53:11.628183Z","shell.execute_reply.started":"2024-04-08T03:53:11.622678Z","shell.execute_reply":"2024-04-08T03:53:11.627057Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def box_map(img, r):\n#     h = int(r / 2)\n#     if img.dim() == 4:\n#         # Handle batch of images\n#         batch_size, height, width, channels = img.shape\n#         box_mean = torch.zeros(img.shape)\n\n#         # Pad each image in the batch\n#         for i in range(batch_size):\n#             padded_img = F.pad(img[i], (h, h, 0, 0), mode='reflect')\n#             # Calculate the box mean for each pixel in the batch image\n#             for j in range(height):\n#                 for k in range(width):\n#                     box_mean[i, j, k] = torch.mean(padded_img[j:j + r, k:k + r])\n\n#         return box_mean\n\n#     else:\n#         # Handle single RGB image\n#         height, width, channels = img.shape\n#         box_mean = torch.zeros((height, width, channels))\n\n#         if img.dim() == 2:\n#             padded_img = F.pad(img, (h, h), mode='reflect')\n#         else:\n#             # Pad the image\n#             padded_img = F.pad(img, (h, h, 0, 0), mode='reflect')\n\n#         # Calculate the box mean for each pixel in the image\n#         for i in range(height):\n#             for j in range(width):\n#                 box_mean[i, j] = torch.mean(padded_img[i:i + r, j:j + r])\n#         return box_mean\n","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:11.900354Z","iopub.execute_input":"2024-04-08T03:53:11.900721Z","iopub.status.idle":"2024-04-08T03:53:11.905237Z","shell.execute_reply.started":"2024-04-08T03:53:11.900691Z","shell.execute_reply":"2024-04-08T03:53:11.904216Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def guided_filter(p, I, r, eps=1e-8):\n#     # (x, y)\n\n#     I_mean = box_mean(I, r)\n#     p_mean = box_mean(p, r)\n\n#     corr_I = box_mean(torch.pow(I, 2), r)\n#     corr_Ip = box_mean(I * p, r)\n\n#     var_I = corr_I - torch.pow(I_mean, 2)\n#     cov_Ip = corr_Ip - I_mean * p_mean\n\n#     a = cov_Ip / (var_I + eps)\n#     b = p_mean - a * I_mean\n\n#     a_mean = box_mean(a, r)\n#     b_mean = box_mean(b, r)\n\n#     # Calculate the mean of 'a' and 'b' across the local window for each pixel\n#     if p.dim() == 4:\n#         # Handle batch of images\n#         batch_size, height, width, channels = p.shape\n#     # Pad each image in the batch\n#         for i in range(batch_size):\n#             for j in range(height):\n#                 for k in range(width):\n#                     a_mean[i, j, k] = a_mean[i:i + r, j:j + r].mean()\n#                     b_mean[i, j, k] = b_mean[i:i + r, j:j + r].mean()\n#     else:\n#         for i in range(p.shape[0]):\n#             for j in range(p.shape[1]):\n#                 a_mean[i, j] = a_mean[i:i + r, j:j + r].mean()\n#                 b_mean[i, j] = b_mean[i:i + r, j:j + r].mean()\n\n#     q = a_mean * I + b_mean\n\n#     return q, (a_mean, b_mean)\n\n\n# def Fast_guided_filter(p, I, r, s, eps, mode='linear'):\n#     # Sample a dot from images every **s** dots\n#     I_s = None\n#     p_s = None\n\n#     if len(p.shape) > 3:\n#         scale = torch.tensor([p.shape[0], s, s, 1], dtype=torch.float)\n#     else:\n#         scale = torch.tensor([s, s, 1], dtype=torch.float)\n# #     scale = 4\n#     # Downsample\n#     p_s = F.interpolate(p, scale_factor=1 / scale, mode=mode)\n#     I_s = F.interpolate(I, scale_factor=1 / scale, mode=mode)\n\n#     r_s = int(r / s)\n\n#     _, ab_mean = guided_filter(p_s, I_s, r_s, eps)\n\n#     a_mean_s = ab_mean[0]\n#     b_mean_s = ab_mean[1]\n\n#     # Upsample\n#     a_mean = F.interpolate(a_mean_s, scale_factor=scale, mode=mode)\n#     b_mean = F.interpolate(b_mean_s, scale_factor=scale, mode=mode)\n\n#     q = a_mean * I + b_mean\n\n#     return q","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:12.208620Z","iopub.execute_input":"2024-04-08T03:53:12.208989Z","iopub.status.idle":"2024-04-08T03:53:12.215352Z","shell.execute_reply.started":"2024-04-08T03:53:12.208956Z","shell.execute_reply":"2024-04-08T03:53:12.214181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Simplified for 3 channel [c,h,w] input. Check my other code for utility script\n# def guided_filter(p, I, r, e, return_intermediates=False):\n#     kernel = torch.ones(p.shape[0],1,r,r) / (r**2)\n#     print(kernel.shape)\n#     pad = r // 2\n\n#     mean_p = F.conv2d(p, kernel, padding=pad, groups=3)\n#     mean_I = F.conv2d(I, kernel, padding=pad, groups=3)\n#     corr_I = F.conv2d(I*I, kernel, padding=pad, groups=3)\n#     corr_Ip = F.conv2d(I*p, kernel, padding=pad, groups=3)\n\n#     var_I = corr_I - mean_I*mean_I\n#     cov_Ip = corr_Ip - mean_I*mean_p\n\n#     a = cov_Ip / (var_I + e)\n#     b = mean_p - a * mean_I\n#     mean_a = F.conv2d(a, kernel, padding=pad, groups=3)\n#     mean_b = F.conv2d(b, kernel, padding=pad, groups=3)\n#     q = mean_a*I + mean_b\n#     # if return_intermediates:\n#     #     return mean_p, mean_I, corr_I, corr_Ip, \\\n#     #         var_I, cov_Ip, a, b, mean_a, mean_b, q\n#     if return_intermediates:\n#         return mean_p, mean_I, a, b, mean_a*I, I+mean_b, q\n#     else:\n#         return q","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:12.521318Z","iopub.execute_input":"2024-04-08T03:53:12.521681Z","iopub.status.idle":"2024-04-08T03:53:12.526056Z","shell.execute_reply.started":"2024-04-08T03:53:12.521639Z","shell.execute_reply":"2024-04-08T03:53:12.525028Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# p = cv2.imread(f'{target_path[7]}', cv2.IMREAD_COLOR)\n# p = cv2.cvtColor(p, cv2.COLOR_BGR2RGB).astype(np.float32)\n# p = cv2.resize(p, dsize=(512,512))\n# print(p.shape)\n# p = torch.as_tensor(p).permute(2,0,1)\n# print(p.shape)\n# # p = cv2.imread('wheat.jpg', cv2.IMREAD_COLOR)\n# # p = cv2.cvtColor(p, cv2.COLOR_BGR2RGB)\n\n\n\n# I = p\n# r = 7\n# eps = 0.01\n\n# s = 4\n\n# guided_filter(p, I, r, eps, return_intermediates=False)\n# # Fast_guided_filter(p, I, r, s, eps, mode='linear')\n# # out_1 = Fast_guided_filter(p, I, r, s, eps)","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:12.791628Z","iopub.execute_input":"2024-04-08T03:53:12.791997Z","iopub.status.idle":"2024-04-08T03:53:12.796134Z","shell.execute_reply.started":"2024-04-08T03:53:12.791962Z","shell.execute_reply":"2024-04-08T03:53:12.795107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# class AdaptiveABGamma_gf(A.ImageOnlyTransform):\n#     \"\"\"\n#     Args:\n#         alpha_limit:\n#         beta_limit:\n#         patch_size:\n#         gamma_limit (float or (float, float)): If gamma_limit is a single float value,\n#             the range will be (-gamma_limit, gamma_limit). Default: (80, 120).\n\n#     Targets:\n#         image\n\n#     Image types:\n#         uint8, float32\n#     \"\"\"\n\n#     def __init__(self, r=7, e=0.01, s=4, gamma_limit=(0.8, 3.0), max_value=255.0, always_apply=False, p=0.5):\n#         super(AdaptiveABGamma_gf, self).__init__(always_apply, p)\n#         self.gamma_limit = to_tuple(gamma_limit)\n#         self.r = r # kernel size\n#         self.e = e # regularization\n#         self.s = s # scale\n#         self.max = max_value\n\n#     def apply(self, image, r=7, e=0.01, s=4, gamma=1, max_value=1, **params):\n#         # img = image.copy()\n#         # img = cv2.resize(img, dsize=(image.shape[1]//self.num, image.shape[0]//self.num))\n#         src_image_transformed = adaptive_guided_filter(image=image, r=r, e=e, s=s, gamma_range=gamma, max=max_value)\n#         if type(src_image_transformed) == torch.Tensor:\n#             src_image_transformed = src_image_transformed.cpu().numpy()\n#         return src_image_transformed\n\n#     def get_params(self):\n#         return {\"gamma\": (self.gamma_limit[0], self.gamma_limit[1]),\n#                 \"r\": self.r,\n#                 \"e\": self.e,\n#                 \"s\": self.s,\n#                 \"max_value\" : self.max}\n\n#     def get_transform_init_args_names(self):\n#         return (\"r\", \"e\", \"s\", \"gamma_limit\", \"max\")","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:13.064193Z","iopub.execute_input":"2024-04-08T03:53:13.064568Z","iopub.status.idle":"2024-04-08T03:53:13.069298Z","shell.execute_reply.started":"2024-04-08T03:53:13.064538Z","shell.execute_reply":"2024-04-08T03:53:13.068259Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# def adaptive_guided_filter(image, r, e, s, gamma_range, max=255.0):\n#     if type(image) == torch.Tensor:\n# #         if len(image.ndim) > 3:\n# #             image = image.permute(0,2, 3, 1).cpu().numpy()\n# #         else:\n#         image = image.cpu().numpy()\n#     # Convert image to float32 for correction\n#     image = image.astype(np.float32) / max\n\n#     # image statistics\n#     # mean = 0.28577543694475377\n#     # std = 0.08460948859737534\n#     img_mean = image.mean()\n#     img_std = image.std()\n    \n#     p = image\n# #     p = cv2.resize(p, dsize=(512,512))\n#     I = p     # guide image (self-guided here)\n#     # r = 3    # kernel size\n#     # e = 0.05 # regularization\n# #     filter_images = guided_filter(p, I, r, e, return_intermediates=True)\n#     filter_images = Fast_guided_filter(p, I, r, s, e, mode='linear')\n# #     idx = np.random.choice(range(len(filter_images)), 1)[0]\n#     # print(idx)\n#     clipped = filter_images #[idx]\n#     # print(clipped.shape)\n# #     clipped = clipped.permute(1,2,0).numpy()\n#     # clipped = clipped.numpy()\n#     g = img_std / img_mean\n#     # g = abs((img_mean - mean)/(img_std - std))\n\n#     gamma = np.clip(g, gamma_range[0], gamma_range[1])\n#     # print(g, gamma, 1.0/gamma)\n#     corrected_patch = np.power(clipped, 1.0/gamma, dtype=complex).real.astype(np.float32)\n#     # print(clipped.shape)\n\n#     image = corrected_patch.astype(np.float32)\n#     image = torch.as_tensor(image).cuda()\n#     # print(image.shape)\n#     return image\n\n# id = 'a8f992d8d'\n# # image = cv2.imread(f'{target_path[1]}', cv2.IMREAD_COLOR)\n# image = cv2.imread(f\"/kaggle/input/global-wheat-detection/train/{id}.jpg\", cv2.IMREAD_COLOR)\n# image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) #.astype(np.float32)\n\n\n# fig, ax = plt.subplots(1, 2, figsize=(10, 5))\n\n# ax[0].set_axis_off()\n# ax[0].imshow(image)\n\n# aug = A.Compose([\n#                 AdaptiveABGamma_gf(\n#                                    r=5,\n#                                    e=0.02,\n#                                    s=4,\n#                                 gamma_limit=(0.7, 1.5),\n#                                 max_value=255.0, p=1),\n\n#                         ])\n# res = aug(image=image)['image'] #.transpose((1,2,0))\n# # plt.imshow(res)\n# ax[1].set_axis_off()\n# ax[1].imshow(res)\n","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:13.335197Z","iopub.execute_input":"2024-04-08T03:53:13.335593Z","iopub.status.idle":"2024-04-08T03:53:13.341296Z","shell.execute_reply.started":"2024-04-08T03:53:13.335559Z","shell.execute_reply":"2024-04-08T03:53:13.340305Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# bi = np.expand_dims(image, axis=0)","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:13.608478Z","iopub.execute_input":"2024-04-08T03:53:13.608876Z","iopub.status.idle":"2024-04-08T03:53:13.613105Z","shell.execute_reply.started":"2024-04-08T03:53:13.608844Z","shell.execute_reply":"2024-04-08T03:53:13.612111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# r=8\n# s =4\n# e=0.01\n# gamma_range = (0.5, 1.5)\n# adaptive_guided_filter(bi, r, e, s, gamma_range, max=255.0)","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:14.225464Z","iopub.execute_input":"2024-04-08T03:53:14.225918Z","iopub.status.idle":"2024-04-08T03:53:14.230021Z","shell.execute_reply.started":"2024-04-08T03:53:14.225869Z","shell.execute_reply":"2024-04-08T03:53:14.229034Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preprocess = A.Compose([\n                        AdaptiveABGamma(patch_size=32, \n                        alpha_limit=(1.0, 1.8), beta_limit=(-0.1, 0.2), gamma_limit=(0.5, 0.8), \n                        max_value=1.0, num=1, p=0.5),\n                    ])","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:14.689083Z","iopub.execute_input":"2024-04-08T03:53:14.689494Z","iopub.status.idle":"2024-04-08T03:53:14.696588Z","shell.execute_reply.started":"2024-04-08T03:53:14.689453Z","shell.execute_reply":"2024-04-08T03:53:14.695519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_valid_transforms():\n    return A.Compose([\n            A.Resize(height=512, width=512, p=1.0),\n#             AdaptiveABGamma(patch_size=64, \n#                         alpha_limit=(0.5, 1.5), beta_limit=(-0.1, 0.3), gamma_limit=(0.5, 1.5), \n#                         max_value=1.0, num=2, p=1.0),\n            ToTensorV2(p=1.0),\n        ], p=1.0)","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:15.429335Z","iopub.execute_input":"2024-04-08T03:53:15.429803Z","iopub.status.idle":"2024-04-08T03:53:15.435226Z","shell.execute_reply.started":"2024-04-08T03:53:15.429767Z","shell.execute_reply":"2024-04-08T03:53:15.434126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DATA_ROOT_PATH = '../input/global-wheat-detection/test'\n\nclass DatasetRetriever(Dataset):\n\n    def __init__(self, image_ids, preprocess=None, transforms=None):\n        super().__init__()\n        self.image_ids = image_ids\n        self.transforms = transforms\n        self.preprocess = preprocess\n        \n    def __getitem__(self, index: int):\n        image_id = self.image_ids[index]\n        image = cv2.imread(f'{DATA_ROOT_PATH}/{image_id}.jpg', cv2.IMREAD_COLOR)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) #.astype(np.float32)''\n        image = (image / 255.0).astype(np.float32)\n        \n        if self.preprocess:\n            image = self.preprocess(image=image)['image']\n#         image = (image / 255.0) #.astype(np.float32)\n        if self.transforms:\n            sample = {'image': image}\n            sample = self.transforms(**sample)\n            image = sample['image']\n        return image, image_id\n\n    def __len__(self) -> int:\n        return self.image_ids.shape[0]","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:15.926633Z","iopub.execute_input":"2024-04-08T03:53:15.926969Z","iopub.status.idle":"2024-04-08T03:53:15.938419Z","shell.execute_reply.started":"2024-04-08T03:53:15.926940Z","shell.execute_reply":"2024-04-08T03:53:15.937433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset = DatasetRetriever(\n    image_ids=np.array([path.split('/')[-1][:-4] for path in glob(f'{DATA_ROOT_PATH}/*.jpg')]),\n    preprocess=None,\n    transforms=get_valid_transforms()\n)\n\ndef collate_fn(batch):\n    return tuple(zip(*batch))\n\ndata_loader = DataLoader(\n    dataset,\n    batch_size=8,\n    shuffle=False,\n    num_workers=4,\n    drop_last=False,\n    collate_fn=collate_fn\n)","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:16.670856Z","iopub.execute_input":"2024-04-08T03:53:16.671198Z","iopub.status.idle":"2024-04-08T03:53:16.686288Z","shell.execute_reply.started":"2024-04-08T03:53:16.671168Z","shell.execute_reply":"2024-04-08T03:53:16.685584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sys.path.insert(0, \"../input/attention-module\")","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:17.537100Z","iopub.execute_input":"2024-04-08T03:53:17.537493Z","iopub.status.idle":"2024-04-08T03:53:17.541749Z","shell.execute_reply.started":"2024-04-08T03:53:17.537455Z","shell.execute_reply":"2024-04-08T03:53:17.540754Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport math\n\nclass se_block(nn.Module):\n    def __init__(self, channel, ratio=16):\n        super(se_block, self).__init__()\n        self.avg_pool = nn.AdaptiveAvgPool2d(1)\n        self.fc = nn.Sequential(\n                nn.Linear(channel, channel // ratio, bias=False),\n                nn.ReLU(inplace=True),\n                nn.Linear(channel // ratio, channel, bias=False),\n                nn.Sigmoid()\n        )\n\n    def forward(self, x):\n        b, c, _, _ = x.size()\n        y = self.avg_pool(x).view(b, c)\n        y = self.fc(y).view(b, c, 1, 1)\n        return x * y\n\nclass ChannelAttention(nn.Module):\n    def __init__(self, in_planes, ratio=8):\n        super(ChannelAttention, self).__init__()\n        self.avg_pool = nn.AdaptiveAvgPool2d(1)\n        self.max_pool = nn.AdaptiveMaxPool2d(1)\n\n        self.fc1   = nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False)\n        self.relu1 = nn.ReLU()\n        self.fc2   = nn.Conv2d(in_planes // ratio, in_planes, 1, bias=False)\n\n        self.sigmoid = nn.Sigmoid()\n\n    def forward(self, x):\n        avg_out = self.fc2(self.relu1(self.fc1(self.avg_pool(x))))\n        max_out = self.fc2(self.relu1(self.fc1(self.max_pool(x))))\n        out = avg_out + max_out\n        return self.sigmoid(out)\n\nclass SpatialAttention(nn.Module):\n    def __init__(self, kernel_size=7):\n        super(SpatialAttention, self).__init__()\n\n        assert kernel_size in (3, 7), 'kernel size must be 3 or 7'\n        padding = 3 if kernel_size == 7 else 1\n        self.conv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)\n        self.sigmoid = nn.Sigmoid()\n\n    def forward(self, x):\n        avg_out = torch.mean(x, dim=1, keepdim=True)\n        max_out, _ = torch.max(x, dim=1, keepdim=True)\n        x = torch.cat([avg_out, max_out], dim=1)\n        x = self.conv1(x)\n        return self.sigmoid(x)\n\nclass cbam_block(nn.Module):\n    def __init__(self, channel, ratio=8, kernel_size=7):\n        super(cbam_block, self).__init__()\n        self.channelattention = ChannelAttention(channel, ratio=ratio)\n        self.spatialattention = SpatialAttention(kernel_size=kernel_size)\n\n    def forward(self, x):\n        x = x*self.channelattention(x)\n        x = x*self.spatialattention(x)\n        return x\n\nclass eca_block(nn.Module):\n    def __init__(self, channel, b=1, gamma=2):\n        super(eca_block, self).__init__()\n        kernel_size = int(abs((math.log(channel, 2) + b) / gamma))\n        kernel_size = kernel_size if kernel_size % 2 else kernel_size + 1\n        \n        self.avg_pool = nn.AdaptiveAvgPool2d(1)\n        self.conv = nn.Conv1d(1, 1, kernel_size=kernel_size, padding=(kernel_size - 1) // 2, bias=False) \n        self.sigmoid = nn.Sigmoid()\n\n    def forward(self, x):\n        y = self.avg_pool(x)\n        y = self.conv(y.squeeze(-1).transpose(-1, -2)).transpose(-1, -2).unsqueeze(-1)\n        y = self.sigmoid(y)\n        return x * y.expand_as(x)","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:19.362684Z","iopub.execute_input":"2024-04-08T03:53:19.363014Z","iopub.status.idle":"2024-04-08T03:53:19.395728Z","shell.execute_reply.started":"2024-04-08T03:53:19.362987Z","shell.execute_reply":"2024-04-08T03:53:19.394786Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from Attention_modules.CBAM import CBAM, SpatialAttention","metadata":{"execution":{"iopub.status.busy":"2024-04-08T03:53:29.953296Z","iopub.execute_input":"2024-04-08T03:53:29.953687Z","iopub.status.idle":"2024-04-08T03:53:29.957861Z","shell.execute_reply.started":"2024-04-08T03:53:29.953651Z","shell.execute_reply":"2024-04-08T03:53:29.956979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_net(checkpoint_path):\n    config = get_efficientdet_config('tf_efficientdet_d5')\n    net = EfficientDet(config, pretrained_backbone=False)\n\n    config.num_classes = 1\n    config.image_size=512\n    net.class_net = HeadNet(config, num_outputs=config.num_classes, norm_kwargs=dict(eps=.001, momentum=.01))   \n    \n    for i in range(len(net.backbone.blocks)):\n        for j in range(len(net.backbone.blocks[i])):\n            in_channels = net.backbone.blocks[i][j].se.conv_reduce.in_channels\n#             print(in_channels)\n            net.backbone.blocks[i][j].se.add_module('sa',SpatialAttention())\n    net.backbone.add_module(\"CBAM\", nn.Sequential(CBAM(channel = 512)\n                                        ))\n    \n#     net.backbone.add_module(\"Attention\", nn.Sequential(CBAM(channel = 512),\n#                                         ))\n    \n    checkpoint = torch.load(checkpoint_path)\n    net.load_state_dict(checkpoint['model_state_dict'])\n\n    del checkpoint\n    gc.collect()\n\n    net = DetBenchEval(net, config)\n    net.eval();\n    return net.cuda()\n\n# net = load_net('/kaggle/input/effdet-29-ckpt/best-checkpoint-035epoch.bin')\n# net = load_net('/kaggle/input/may-15-ckpt/best-checkpoint-031epoch.bin')\n# net = load_net('/kaggle/input/efficientdet-gwhd-nov-09-v2/best-checkpoint-033epoch.bin')\nnet = load_net('/kaggle/input/efficientdet-sagf-cbam-gwhd-slug-1712547824/last-checkpoint.bin')","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:30:35.998036Z","iopub.execute_input":"2024-04-08T04:30:35.998385Z","iopub.status.idle":"2024-04-08T04:30:43.095830Z","shell.execute_reply.started":"2024-04-08T04:30:35.998354Z","shell.execute_reply":"2024-04-08T04:30:43.094983Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Custom TTA API\nIdea is simple:\n\n- augment make tta for one image\n- batch_augment make tta for batch of images\n- deaugment_boxes return tta predicted boxes in back to original state of image\n\nAlso we are interested in Compose with combinations of tta :)","metadata":{}},{"cell_type":"code","source":"class BaseWheatTTA:\n    \"\"\" author: @shonenkov \"\"\"\n    image_size = 512\n\n    def augment(self, image):\n        raise NotImplementedError\n    \n    def batch_augment(self, images):\n        raise NotImplementedError\n    \n    def deaugment_boxes(self, boxes):\n        raise NotImplementedError\n\nclass TTAHorizontalFlip(BaseWheatTTA):\n    \"\"\" author: @shonenkov \"\"\"\n\n    def augment(self, image):\n        return image.flip(1)\n    \n    def batch_augment(self, images):\n        return images.flip(2)\n    \n    def deaugment_boxes(self, boxes):\n        boxes[:, [1,3]] = self.image_size - boxes[:, [3,1]]\n        return boxes\n\nclass TTAVerticalFlip(BaseWheatTTA):\n    \"\"\" author: @shonenkov \"\"\"\n    \n    def augment(self, image):\n        return image.flip(2)\n    \n    def batch_augment(self, images):\n        return images.flip(3)\n    \n    def deaugment_boxes(self, boxes):\n        boxes[:, [0,2]] = self.image_size - boxes[:, [2,0]]\n        return boxes\n    \nclass TTARotate90(BaseWheatTTA):\n    \"\"\" author: @shonenkov \"\"\"\n    \n    def augment(self, image):\n        return torch.rot90(image, 1, (1, 2))\n\n    def batch_augment(self, images):\n        return torch.rot90(images, 1, (2, 3))\n    \n    def deaugment_boxes(self, boxes):\n        res_boxes = boxes.copy()\n        res_boxes[:, [0,2]] = self.image_size - boxes[:, [1,3]]\n        res_boxes[:, [1,3]] = boxes[:, [2,0]]\n        return res_boxes\n\nclass TTAABG(BaseWheatTTA):\n    \"\"\" author: @ffares \"\"\"\n    \n    def augment(self, image):\n#         adaptive_alpha_beta_gamma_correction(image, patch_size, alpha_range, beta_range, gamma_range, max=255.0)\n        return adaptive_alpha_beta_gamma_correction(image,patch_size=512, \n                        alpha_range=(0.7, 1.5), beta_range=(-0.05, 0.25), gamma_range=(0.7, 1.5), \n                        max=1.0)\n\n    def batch_augment(self, images):\n        return adaptive_alpha_beta_gamma_correction(images, patch_size=512, \n                        alpha_range=(0.7, 1.5), beta_range=(-0.05, 0.25), gamma_range=(0.7, 1.5), \n                        max=1.0)\n    \n    def deaugment_boxes(self, boxes):\n        return boxes\n \n# class TTAABGF(BaseWheatTTA):\n#     \"\"\" author: @ffares \"\"\"\n    \n#     def augment(self, image):\n#         image = image.permute(1,2,0)\n# #        adaptive_guided_filter(image, r, e, s, gamma_range, max=255.0)\n#         return adaptive_guided_filter(image, r=8, e=0.02,s=4,gamma_range=(0.7, 1.5),max=1.0).permute(2,0,1)\n\n#     def batch_augment(self, images):\n#         images = images.permute(0,2,3,1)\n#         return adaptive_guided_filter(images, r=8, e=0.02, s=4,gamma_range=(0.7, 1.5),max=1.0).permute(0,3,1,2)\n    \n#     def deaugment_boxes(self, boxes):\n#         return boxes\n    \nclass TTACompose(BaseWheatTTA):\n    \"\"\" author: @shonenkov \"\"\"\n    def __init__(self, transforms):\n        self.transforms = transforms\n        \n    def augment(self, image):\n        for transform in self.transforms:\n            image = transform.augment(image)\n        return image\n    \n    def batch_augment(self, images):\n        for transform in self.transforms:\n            images = transform.batch_augment(images)\n        return images\n    \n    def prepare_boxes(self, boxes):\n        result_boxes = boxes.copy()\n        result_boxes[:,0] = np.min(boxes[:, [0,2]], axis=1)\n        result_boxes[:,2] = np.max(boxes[:, [0,2]], axis=1)\n        result_boxes[:,1] = np.min(boxes[:, [1,3]], axis=1)\n        result_boxes[:,3] = np.max(boxes[:, [1,3]], axis=1)\n        return result_boxes\n    \n    def deaugment_boxes(self, boxes):\n        for transform in self.transforms[::-1]:\n            boxes = transform.deaugment_boxes(boxes)\n        return self.prepare_boxes(boxes)","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:30:43.098607Z","iopub.execute_input":"2024-04-08T04:30:43.099018Z","iopub.status.idle":"2024-04-08T04:30:43.132570Z","shell.execute_reply.started":"2024-04-08T04:30:43.098975Z","shell.execute_reply":"2024-04-08T04:30:43.131513Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def process_det(index, det, score_threshold=0.25):\n    boxes = det[index].detach().cpu().numpy()[:,:4]    \n    scores = det[index].detach().cpu().numpy()[:,4]\n    boxes[:, 2] = boxes[:, 2] + boxes[:, 0]\n    boxes[:, 3] = boxes[:, 3] + boxes[:, 1]\n    boxes = (boxes).clip(min=0, max=511).astype(int)\n    indexes = np.where(scores>score_threshold)\n    boxes = boxes[indexes]\n    scores = scores[indexes]\n    return boxes, scores","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:30:43.134314Z","iopub.execute_input":"2024-04-08T04:30:43.134754Z","iopub.status.idle":"2024-04-08T04:30:43.147590Z","shell.execute_reply.started":"2024-04-08T04:30:43.134711Z","shell.execute_reply":"2024-04-08T04:30:43.146760Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# you can try own combinations:\ntransform = TTACompose([\n    TTARotate90(),\n    TTAVerticalFlip(),\n#     TTAABGF(),\n])\n\nfig, ax = plt.subplots(1, 3, figsize=(16, 6))\n\nimage, image_id = dataset[5]\n# print(image.shape)\nnumpy_image = image.permute(1,2,0).cpu().numpy().copy()\n\nax[0].imshow(numpy_image);\nax[0].set_title('original')\n\ntta_image = transform.augment(image)\n# print(tta_image)\ntta_image_numpy = tta_image.permute(1,2,0).cpu().numpy().copy()\n\ndet = net(tta_image.unsqueeze(0).float().cuda(), torch.tensor([1]).float().cuda())\nboxes, scores = process_det(0, det)\n\nfor box in boxes:\n    cv2.rectangle(tta_image_numpy, (box[0], box[1]), (box[2],  box[3]), (0, 1, 0), 2)\n\nax[1].imshow(tta_image_numpy);\nax[1].set_title('tta')\n    \nboxes = transform.deaugment_boxes(boxes)\n\nfor box in boxes:\n    cv2.rectangle(numpy_image, (box[0], box[1]), (box[2],  box[3]), (0, 1, 0), 2)\n    \nax[2].imshow(numpy_image);\nax[2].set_title('deaugment predictions');","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:30:43.149191Z","iopub.execute_input":"2024-04-08T04:30:43.149585Z","iopub.status.idle":"2024-04-08T04:30:43.937714Z","shell.execute_reply.started":"2024-04-08T04:30:43.149547Z","shell.execute_reply":"2024-04-08T04:30:43.936665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Combinations of TTA","metadata":{}},{"cell_type":"code","source":"from itertools import product\n\ntta_transforms = []\nfor tta_combination in product(\n                               [TTAHorizontalFlip(), None], \n                               [TTAVerticalFlip(), None],\n#                                [TTAABGF(), None],\n                               [TTARotate90(), None]\n                              ):\n    tta_transforms.append(TTACompose([tta_transform for tta_transform in tta_combination if tta_transform]))","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:30:43.940522Z","iopub.execute_input":"2024-04-08T04:30:43.940875Z","iopub.status.idle":"2024-04-08T04:30:43.947731Z","shell.execute_reply.started":"2024-04-08T04:30:43.940839Z","shell.execute_reply":"2024-04-08T04:30:43.947031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### WBF over TTA","metadata":{}},{"cell_type":"code","source":"def make_tta_predictions(images, score_threshold=0.1):\n    with torch.no_grad():\n        images = torch.stack(images).float().cuda()\n        predictions = []\n        for tta_transform in tta_transforms:\n            result = []\n            det = net(tta_transform.batch_augment(images.clone()), torch.tensor([1]*images.shape[0]).float().cuda())\n\n            for i in range(images.shape[0]):\n                boxes = det[i].detach().cpu().numpy()[:,:4]    \n                scores = det[i].detach().cpu().numpy()[:,4]\n                indexes = np.where(scores > score_threshold)[0]\n                boxes = boxes[indexes]\n                boxes[:, 2] = boxes[:, 2] + boxes[:, 0]\n                boxes[:, 3] = boxes[:, 3] + boxes[:, 1]\n                boxes = tta_transform.deaugment_boxes(boxes.copy())\n                result.append({\n                    'boxes': boxes,\n                    'scores': scores[indexes],\n                })\n            predictions.append(result)\n    return predictions\n\ndef run_wbf(predictions, image_index, image_size=512, iou_thr=0.44, skip_box_thr=0.43, weights=None):\n    boxes = [(prediction[image_index]['boxes']/(image_size-1)).tolist() for prediction in predictions]\n    scores = [prediction[image_index]['scores'].tolist() for prediction in predictions]\n    labels = [np.ones(prediction[image_index]['scores'].shape[0]).astype(int).tolist() for prediction in predictions]\n    boxes, scores, labels = ensemble_boxes_wbf.weighted_boxes_fusion(boxes, scores, labels, weights=None, iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n    boxes = boxes*(image_size-1)\n    return boxes, scores, labels","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:30:43.949094Z","iopub.execute_input":"2024-04-08T04:30:43.949439Z","iopub.status.idle":"2024-04-08T04:30:43.967664Z","shell.execute_reply.started":"2024-04-08T04:30:43.949384Z","shell.execute_reply":"2024-04-08T04:30:43.966883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_predictions(images, score_threshold=0.2):\n    images = torch.stack(images).cuda().float()\n    predictions = []\n    with torch.no_grad():\n        det = net(images, torch.tensor([1]*images.shape[0]).float().cuda())\n        for i in range(images.shape[0]):\n            boxes = det[i].detach().cpu().numpy()[:,:4]    \n            scores = det[i].detach().cpu().numpy()[:,4]\n            indexes = np.where(scores > score_threshold)[0]\n            boxes = boxes[indexes]\n            boxes[:, 2] = boxes[:, 2] + boxes[:, 0]\n            boxes[:, 3] = boxes[:, 3] + boxes[:, 1]\n            predictions.append({\n                'boxes': boxes[indexes],\n                'scores': scores[indexes],\n            })\n    return [predictions]\n\n# def run_wbf(predictions, image_index, image_size=512, iou_thr=0.44, skip_box_thr=0.41, weights=None):\n#     boxes = [(prediction[image_index]['boxes']/(image_size-1)).tolist()  for prediction in predictions]\n#     scores = [prediction[image_index]['scores'].tolist()  for prediction in predictions]\n#     labels = [np.ones(prediction[image_index]['scores'].shape[0]).tolist() for prediction in predictions]\n#     boxes, scores, labels = weighted_boxes_fusion(boxes, scores, labels, weights=None, iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n#     boxes = boxes*(image_size-1)\n#     return boxes, scores, labels","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:30:43.969187Z","iopub.execute_input":"2024-04-08T04:30:43.969788Z","iopub.status.idle":"2024-04-08T04:30:43.982210Z","shell.execute_reply.started":"2024-04-08T04:30:43.969744Z","shell.execute_reply":"2024-04-08T04:30:43.981168Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torchvision\n\niou_thr = 0.44\nskip_box_thr = 0.41\nsigma = 0.5\nweights = None # np.array([1,])\ncuda = 1 if torch.cuda.is_available() else 0\n\ndef run_nms(predictions, image_index, image_size=512, iou_thr=0.41, weights=weights):\n    boxes = [prediction[image_index]['boxes']/(image_size-1)  for prediction in predictions]\n    scores = [prediction[image_index]['scores']  for prediction in predictions]\n    labels = [np.ones(prediction[image_index]['scores'].shape[0]) for prediction in predictions]\n    boxes, scores, labels = ensemble_boxes_nms.nms(boxes, scores, labels, weights=weights, iou_thr=iou_thr)\n    boxes = boxes*(image_size-1)\n    return boxes, scores, labels\n\ndef run_nmw(predictions, image_index, image_size=512, iou_thr=0.41, skip_box_thr=skip_box_thr, weights=weights):\n    boxes = [(prediction[image_index]['boxes']/(image_size-1)).tolist()  for prediction in predictions]\n    scores = [prediction[image_index]['scores'].tolist() for prediction in predictions]\n    labels = [np.ones(prediction[image_index]['scores'].shape[0]).tolist() for prediction in predictions]\n    boxes, scores, labels = ensemble_boxes_nmw.non_maximum_weighted(boxes, scores, labels, weights=weights, iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n    boxes = boxes*(image_size-1)\n    return boxes, scores, labels\n\n\ndef run_soft_nms(predictions, image_index, image_size=512, iou_thr=0.41, skip_box_thr=skip_box_thr, sigma=sigma, weights=weights):\n    boxes = [prediction[image_index]['boxes']/(image_size-1)  for prediction in predictions]\n    scores = [prediction[image_index]['scores'] for prediction in predictions]\n    labels = [np.ones(prediction[image_index]['scores'].shape[0]) for prediction in predictions]\n    try:\n        boxes, scores, labels = ensemble_boxes_nms.soft_nms(boxes, scores, labels, weights=weights, iou_thr=iou_thr, sigma=sigma, thresh=skip_box_thr)\n    except:\n        return [], [], []\n    boxes = boxes*(image_size-1)\n    return boxes, scores, labels","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:30:43.983672Z","iopub.execute_input":"2024-04-08T04:30:43.984053Z","iopub.status.idle":"2024-04-08T04:30:44.005466Z","shell.execute_reply.started":"2024-04-08T04:30:43.984013Z","shell.execute_reply":"2024-04-08T04:30:44.004576Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Method = \"WBF\"\n\nif Method ==\"NMS\":\n    run = run_nms\nelif Method ==\"Soft-NMS\":\n    run = run_soft_nms\nelif Method ==\"NMW\":\n    run = run_nmw\nelif Method ==\"WBF\":\n    run = run_wbf","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:30:45.839670Z","iopub.execute_input":"2024-04-08T04:30:45.840047Z","iopub.status.idle":"2024-04-08T04:30:45.845461Z","shell.execute_reply.started":"2024-04-08T04:30:45.840008Z","shell.execute_reply":"2024-04-08T04:30:45.844699Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:30:48.095588Z","iopub.execute_input":"2024-04-08T04:30:48.095957Z","iopub.status.idle":"2024-04-08T04:30:48.228656Z","shell.execute_reply.started":"2024-04-08T04:30:48.095922Z","shell.execute_reply":"2024-04-08T04:30:48.227682Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nfor j, (images, image_ids) in enumerate(data_loader):\n    break\n\npredictions = make_tta_predictions(images)\n\ni = 0\nsample = images[i].permute(1,2,0).cpu().numpy()\n\nboxes, scores, labels = run(predictions, image_index=i)\nboxes = boxes.round().astype(np.int32).clip(min=0, max=1023)\n\nfig, ax = plt.subplots(1, 1, figsize=(16, 8))\n\nfor box in boxes:\n    cv2.rectangle(sample, (box[0], box[1]), (box[2], box[3]), (1, 0, 0), 1)\n    \nax.set_axis_off()\nax.imshow(sample);","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:30:51.547289Z","iopub.execute_input":"2024-04-08T04:30:51.547659Z","iopub.status.idle":"2024-04-08T04:30:54.453106Z","shell.execute_reply.started":"2024-04-08T04:30:51.547623Z","shell.execute_reply":"2024-04-08T04:30:54.452265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Inference","metadata":{}},{"cell_type":"code","source":"def format_prediction_string(boxes, scores):\n    pred_strings = []\n    for j in zip(scores, boxes):\n        pred_strings.append(\"{0:.4f} {1} {2} {3} {4}\".format(j[0], j[1][0], j[1][1], j[1][2], j[1][3]))\n    return \" \".join(pred_strings)","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:30:55.601855Z","iopub.execute_input":"2024-04-08T04:30:55.602212Z","iopub.status.idle":"2024-04-08T04:30:55.609351Z","shell.execute_reply.started":"2024-04-08T04:30:55.602180Z","shell.execute_reply":"2024-04-08T04:30:55.608194Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results = []\n\nfor images, image_ids in data_loader:\n    predictions = make_tta_predictions(images)\n    for i, image in enumerate(images):\n        boxes, scores, labels = run(predictions, image_index=i)\n        boxes = (boxes*2).astype(np.int32).clip(min=0, max=1023)\n        image_id = image_ids[i]\n        \n        boxes[:, 2] = boxes[:, 2] - boxes[:, 0]\n        boxes[:, 3] = boxes[:, 3] - boxes[:, 1]\n\n        result = {\n            'image_id': image_id,\n            'PredictionString': format_prediction_string(boxes, scores)\n        }\n        results.append(result)","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:30:56.294549Z","iopub.execute_input":"2024-04-08T04:30:56.294903Z","iopub.status.idle":"2024-04-08T04:31:00.304440Z","shell.execute_reply.started":"2024-04-08T04:30:56.294874Z","shell.execute_reply":"2024-04-08T04:31:00.303119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df = pd.DataFrame(results, columns=['image_id', 'PredictionString'])\ntest_df.to_csv('submission.csv', index=False)\ntest_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-04-08T04:31:00.306662Z","iopub.execute_input":"2024-04-08T04:31:00.306967Z","iopub.status.idle":"2024-04-08T04:31:00.321915Z","shell.execute_reply.started":"2024-04-08T04:31:00.306934Z","shell.execute_reply":"2024-04-08T04:31:00.320800Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Thank you for reading my kernel!\n\nIf you didn't read training and WBF kernels:\n\n- [[Training] EfficientDet](https://www.kaggle.com/shonenkov/training-efficientdet)\n- [WBF approach for ensemble](https://www.kaggle.com/shonenkov/wbf-approach-for-ensemble)\n\n\nJust recently I have started publishing my works, if you like this format of notebooks I would like continue to make kernels.","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}