{"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":"markdown","source":"### Installation","metadata":{}},{"cell_type":"code","source":"# to setup\n# !pip install yolov5 --quiet \n# !pip install wandb --quiet\n# !pip install enlighten --quiet\n# !add-apt-repository ppa:ubuntu-toolchain-r/test -y\n# !apt-get update\n# !apt-get upgrade libstdc++6 -y\n# !pip install -r /kaggle/input/yolov5-lib-ds/requirements.txt","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2021-12-13T08:34:32.640608Z","iopub.execute_input":"2021-12-13T08:34:32.641071Z","iopub.status.idle":"2021-12-13T08:34:32.665421Z","shell.execute_reply.started":"2021-12-13T08:34:32.640967Z","shell.execute_reply":"2021-12-13T08:34:32.66428Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Imports","metadata":{}},{"cell_type":"code","source":"%load_ext autoreload\n%autoreload 2\nimport cv2\nimport matplotlib.pyplot as plt\nimport matplotlib \n%matplotlib inline\nimport numpy as np\nimport pandas as pd\nfrom PIL import Image\nimport os\nimport copy\nimport os.path as osp\nimport json5\nimport shutil\nimport yaml\nfrom pathlib import Path\nimport ast\nimport sys\n\nsys.path.append('../input/tensorflow-great-barrier-reef')\nsys.path.append('../input/run-1280-yolov5l')\nsys.path.append('../input/yolov5pip/yolov5-pip')\n\nnp.random.seed(0)\n\n# import wandb\n# wandb.login(anonymous='must')","metadata":{"execution":{"iopub.status.busy":"2021-12-15T05:57:19.407264Z","iopub.execute_input":"2021-12-15T05:57:19.407582Z","iopub.status.idle":"2021-12-15T05:57:19.748536Z","shell.execute_reply.started":"2021-12-15T05:57:19.407504Z","shell.execute_reply":"2021-12-15T05:57:19.747692Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from kaggle_secrets import UserSecretsClient\nuser_secrets = UserSecretsClient()\nsecret_value_0 = user_secrets.get_secret(\"wb_api\")\n\nimport wandb\nwandb.login(key=secret_value_0)","metadata":{"execution":{"iopub.status.busy":"2021-12-15T05:57:23.204334Z","iopub.execute_input":"2021-12-15T05:57:23.205036Z","iopub.status.idle":"2021-12-15T05:57:25.938746Z","shell.execute_reply.started":"2021-12-15T05:57:23.204998Z","shell.execute_reply":"2021-12-15T05:57:25.937877Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Creating YOLO config YAML","metadata":{}},{"cell_type":"code","source":"# Read https://docs.ultralytics.com/tutorials/train-custom-datasets/\nimport yaml\n\nclass SingleQuoted(str):\n    pass\n\ndef single_quoted_presenter(dumper, data):\n    return dumper.represent_scalar('tag:yaml.org,2002:str', data, style=\"'\")\n\nyaml.add_representer(SingleQuoted, single_quoted_presenter)\n\nclass createYoloYaml:\n    def __init__(self):\n        print('creating dataset config yaml')\n        data = dict(\n            path = \"dataset\",\n            train = \"images\",\n            val = \"images\",\n            nc = 1,\n            names = [SingleQuoted('starfish')]\n        )\n\n        with open('reef.yaml', 'w') as outfile:\n            yaml.dump(data, outfile, default_flow_style=True, sort_keys=False)\n            \n        hyp_par = dict(\n            lr0= 0.0032,\n            lrf= 0.12,\n            momentum= 0.843,\n            weight_decay= 0.00036,\n            warmup_epochs= 2.0,\n            warmup_momentum= 0.5,\n            warmup_bias_lr= 0.05,\n            box= 0.0296,\n            cls= 0.243,\n            cls_pw= 0.631,\n            obj= 0.301,\n            obj_pw= 0.911,\n            iou_t= 0.2,\n            anchor_t= 2.91,\n            # anchors= 3.63,\n            fl_gamma= 0.0,\n            hsv_h= 0.0138,\n            hsv_s= 0.664,\n            hsv_v= 0.464,\n            degrees= 0.373,\n            translate= 0.245,\n            scale= 0.898,\n            shear= 0.602,\n            perspective= 0.0,\n            flipud= 0.00856,\n            fliplr= 0.5,\n            mosaic= 1.0,\n            mixup= 0.243,\n            copy_paste= 0.0,\n        )\n        \n        with open('reef_hyp_param.yaml', 'w') as outfile:\n            yaml.dump(hyp_par, outfile, default_flow_style=True, sort_keys=False)\n            \n            \ncreateYoloYaml()","metadata":{"execution":{"iopub.status.busy":"2021-12-15T05:57:27.813298Z","iopub.execute_input":"2021-12-15T05:57:27.813866Z","iopub.status.idle":"2021-12-15T05:57:27.864880Z","shell.execute_reply.started":"2021-12-15T05:57:27.813827Z","shell.execute_reply":"2021-12-15T05:57:27.864144Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Data Related Helpers\n#### Convert labels to YOLO format, with one *.txt file per image (if no objects in image, no *.txt file is required). The *.txt file specifications are:\n- One row per object\n- Each row is class x_center y_center width height format.\n- Class numbers are zero-indexed (start from 0).\n- Box coordinates must be in normalized xywh format (from 0 - 1). \n    If your boxes are in pixels, divide x_center and width by image width, and y_center and height by image height.\n    \n    ##### Calculates x_center & y_center because yolo format uses center + normalized values\n    \n    - x_min : x_min of bounding box,\n    - y_min : y_min of bounding box,\n    - bb_w : width of bounding box,\n    - bb_h : height of bounding box,\n    - im_w : width of image,\n    - im_h : height of image,\n    \n    - returns : normalized values of x_center, y_center, bb_w, bb_h","metadata":{}},{"cell_type":"code","source":"# helper to generate yolo label file\ndef generateYoloLabelFile(folder_path, file_name, label_data_list):\n    pth = str(folder_path) + str(file_name) + '.txt'\n    with open(pth, 'w') as f:\n        if label_data_list is None:\n            # create empty txt file\n            pass\n        else:\n            # create data txt file\n            for label in label_data_list:\n                if label:\n                    f.write(label.strip())\n                    f.write(\"\\n\")\n    return pth\n\n# helper to convert bbox value to yolo format\ndef convertToYoloFormat(x_min, y_min, bb_w, bb_h, im_w, im_h):\n    # find x_center\n    x_center = x_min + (bb_w/2.0)\n    # find y_center\n    y_center = y_min + (bb_h/2.0)\n    # normalize values to 0-1\n    n_x_center = x_center / im_w\n    n_y_center = y_center / im_h\n    n_bb_w = bb_w / im_w\n    n_bb_h = bb_h / im_h\n    return f'{round(n_x_center, 4)} {round(n_y_center,4)} {round(n_bb_w, 4)} {round(n_bb_h, 4)}'\n\n# Memory saving function credit to https://www.kaggle.com/gemartin/load-data-reduce-memory-usage\ndef reduce_mem_usage(df):\n    \"\"\" iterate through all the columns of a dataframe and modify the data type to reduce memory usage.        \n    \"\"\"\n    start_mem = df.memory_usage().sum() / 1024**2\n    print('Memory usage of dataframe is {:.2f} MB'.format(start_mem))\n\n    for col in df.columns:\n        col_type = df[col].dtype\n\n        if col_type != object:\n            c_min = df[col].min()\n            c_max = df[col].max()\n            if str(col_type)[:3] == 'int':\n                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:\n                    df[col] = df[col].astype(np.int8)\n                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:\n                    df[col] = df[col].astype(np.int16)\n                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:\n                    df[col] = df[col].astype(np.int32)\n                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:\n                    df[col] = df[col].astype(np.int64)  \n            else:\n                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:\n                    df[col] = df[col].astype(np.float16)\n                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:\n                    df[col] = df[col].astype(np.float32)\n                else:\n                    df[col] = df[col].astype(np.float64)\n\n    end_mem = df.memory_usage().sum() / 1024**2\n    print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))\n    print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))\n\n    return df\n\ndef get_path(row):\n    row['image_path'] = f'/kaggle/input/tensorflow-great-barrier-reef/train_images/video_{row.video_id}/{row.video_frame}.jpg'\n    return row\n\ndef load_labels(only_with_bbox = True):\n    labels = pd.read_csv(\"/kaggle/input/tensorflow-great-barrier-reef/train.csv\", skipinitialspace=True)\n    labels.drop_duplicates(inplace=True)\n    labels.drop(['sequence'], axis = 1, inplace=True)\n    labels.drop(['sequence_frame'], axis = 1, inplace=True)\n    labels = reduce_mem_usage(labels)\n    labels = labels.apply(get_path, axis=1)\n    if only_with_bbox:\n        return labels[labels['annotations'] != '[]']\n    return labels\n\ndef get_sample_imgs(sample_count = 100):\n    labels = load_labels()\n    # 49 is the length of single annotation images\n    # so we want to return only those which have more than 2 annotations\n    labels['has_multiple_annotations'] = labels['annotations'].str.len() > 49\n    labels = labels.apply(get_path, axis=1)\n    return labels[labels['has_multiple_annotations']].sample(sample_count)['image_path']\n\ndef get_datasets():\n    from sklearn.model_selection import train_test_split\n    # split into 60:40\n    train, val = train_test_split(load_labels(), test_size=0.40)\n    print('Length of train, val data : ', len(train),len(val))\n    return train, val","metadata":{"execution":{"iopub.status.busy":"2021-12-15T05:57:33.219591Z","iopub.execute_input":"2021-12-15T05:57:33.220084Z","iopub.status.idle":"2021-12-15T05:57:33.274918Z","shell.execute_reply.started":"2021-12-15T05:57:33.220041Z","shell.execute_reply":"2021-12-15T05:57:33.273843Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Image Enhancement Helpers","metadata":{}},{"cell_type":"code","source":"# further read for good tips/tricks\n# https://www.kaggle.com/soumya9977/learning-to-sea-underwater-img-enhancement-eda#%F0%9F%8E%AF-Main-Working-Code\n\n# CLAHE (Contrast Limited Adaptive Histogram Equalization)\ndef clhae(img):\n    import cv2\n    clahe = cv2.createCLAHE(clipLimit=3., tileGridSize=(8,8))\n    lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)  # convert from BGR to LAB color space\n    l, a, b = cv2.split(lab)  # split on 3 different channels\n    l2 = clahe.apply(l)  # apply CLAHE to the L-channel\n    lab = cv2.merge((l2,a,b))  # merge channels\n    img = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)  # convert from LAB to BGR\n    del lab, l2, l, clahe\n    return img\n\n# auto white balance\n# credit to https://gist.github.com/DavidYKay/9dad6c4ab0d8d7dbf3dc\ndef white_balance(img, percent=1):\n    out_channels = []\n    cumstops = (\n        img.shape[0] * img.shape[1] * percent / 200.0,\n        img.shape[0] * img.shape[1] * (1 - percent / 200.0)\n    )\n    for channel in cv2.split(img):\n        cumhist = np.cumsum(cv2.calcHist([channel], [0], None, [256], (0,256)))\n        low_cut, high_cut = np.searchsorted(cumhist, cumstops)\n        lut = np.concatenate((\n            np.zeros(low_cut),\n            np.around(np.linspace(0, 255, high_cut - low_cut + 1)),\n            255 * np.ones(255 - high_cut)\n        ))\n        out_channels.append(cv2.LUT(channel, lut.astype('uint8')))\n        del cumhist, low_cut, high_cut\n    del cumstops\n    return cv2.merge(out_channels)\n\n# auto gamma correction\n# why 1.2? because, I felt it is better visually\ndef gamma_correction(img, gamma =1.2):\n    igamma = 1.0 / gamma\n    imin, imax = img.min(), img.max()\n    img_c = img.copy()\n    img_c = ((img_c - imin) / (imax - imin)) ** igamma\n    img_c = img_c * (imax - imin) + imin\n    del imin, imax, igamma\n    return img_c.astype(np.uint8)\n\n# combined helper function\n# NOTE : ORDER MATTERS HERE\ndef enhance_image(img):\n    # why in this order? again, visually it gives a lot better results\n    # also, photographer recommend to gamma correct -> white balance -> color correction\n    img = gamma_correction(img)\n    img = white_balance(img)\n    return clhae(img)\n\ndef convert_to_gray(img):\n    return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n\ndef flip_image(img, horizontal=True):\n    return cv2.flip(img, 1 if horizontal else 0)\n\ndef rand_img_transform(img):\n    import random\n    # random chance if flip or grayscale or none\n    # 0= no-op, 1=flip-h, 2=flip-v, 3=convert2gray\n    dec = random.randrange(0, 4)\n    if dec == 1:\n        img = flip_image(img)\n    elif dec == 2:\n        img = flip_image(img, False)\n    elif dec == 3:\n        img = convert_to_gray(img)\n    return img","metadata":{"execution":{"iopub.status.busy":"2021-12-15T05:57:35.958113Z","iopub.execute_input":"2021-12-15T05:57:35.958770Z","iopub.status.idle":"2021-12-15T05:57:36.004622Z","shell.execute_reply.started":"2021-12-15T05:57:35.958725Z","shell.execute_reply":"2021-12-15T05:57:36.003926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Dataset Creation","metadata":{}},{"cell_type":"code","source":"def process_row(val, is_val=False):\n    # input paths\n    video_path_base = \"/kaggle/input/tensorflow-great-barrier-reef/train_images/\"\n    # output paths\n    dataset_root = \"./dataset/\"\n    image_root = f'{dataset_root}images/'\n    label_root = f'{dataset_root}labels/'\n    if is_val:\n        image_root = f'{dataset_root}val_images/'\n    \n    im_w, im_h = 1280, 720\n    video_id = str(val[0])\n    video_frame = str(val[1])\n    image_id = str(val[2])\n    img_path = val[4]\n    if os.path.exists(img_path) and os.path.isfile(img_path):\n        try:\n            # get annotation data\n            ann_data = val[3]\n\n            # only add, if ann data is available\n            if ann_data and ann_data != '[]':\n                ann_splits = json5.loads(ann_data)\n                yolo_labels = []\n\n                # use image_id for filename, it's videoId_imageId.jpg ex: 0_16.jpg\n                # before, we copy image for yolo train\n                # transform images \n                img = cv2.imread(img_path)\n                img = enhance_image(img)\n                img = rand_img_transform(img)\n                img = cv2.resize(img, (im_w, im_h))\n                new_dst = os.path.join(image_root, f'{image_id}.jpg')\n                cv2.imwrite(new_dst, img)\n\n                del img # clear memory\n\n                for ann_split in ann_splits:\n                    # load annotation data as json and get values\n                    a_data = json5.loads(ann_split)\n                    bb_x_min = int(a_data[\"x\"])\n                    bb_y_min = int(a_data[\"y\"])\n                    bb_w = int(a_data[\"width\"])\n                    bb_h = int(a_data[\"height\"])\n                    yolo_format_bb = convertToYoloFormat(bb_x_min, bb_y_min, bb_w, bb_h, im_w, im_h)\n                    yolo_labels.append(f'0 {yolo_format_bb}')\n                    del a_data, bb_x_min, bb_y_min, bb_w, bb_h, yolo_format_bb\n\n                if yolo_labels:\n                    generateYoloLabelFile(label_root, image_id, yolo_labels)\n\n                del ann_data\n                \n        except KeyboardInterrupt:\n            raise\n\n        except:\n            # corrupt file, skip\n            print('corrupt file')\n            raise\n            \ndef createReefDataset(data, is_val=False):\n    from tqdm import tqdm\n    import pandas as pd\n    import numpy as np\n    import gc\n    import os\n    import cv2\n    from joblib import Parallel, delayed  \n    \n    os.chdir('/kaggle/working/')\n    \n    Parallel(n_jobs=2, prefer='processes')(delayed(process_row)(val,is_val) for val in tqdm(data.values))\n\n#     for val in tqdm(data.values):\n        \n    gc.collect()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-14T21:30:57.095145Z","iopub.execute_input":"2021-12-14T21:30:57.095502Z","iopub.status.idle":"2021-12-14T21:30:57.155833Z","shell.execute_reply.started":"2021-12-14T21:30:57.095469Z","shell.execute_reply":"2021-12-14T21:30:57.154784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # clean dataset folder before re-creating data\n!rm -rf dataset\n!mkdir dataset\n!mkdir dataset/images\n# !mkdir dataset/val_images\n!mkdir dataset/labels\n%cd /kaggle/working","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-12-15T05:57:41.863890Z","iopub.execute_input":"2021-12-15T05:57:41.864381Z","iopub.status.idle":"2021-12-15T05:57:44.587705Z","shell.execute_reply.started":"2021-12-15T05:57:41.864343Z","shell.execute_reply":"2021-12-15T05:57:44.586897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Run create dataset","metadata":{}},{"cell_type":"code","source":"# try:\n#     # read labels\n#     train, val = get_datasets()\n\n#     createReefDataset(train)\n#     del train\n    \n#     createReefDataset(val, True)\n#     del val\n# except KeyboardInterrupt:\n#     pass\n\n# print(len(os.listdir('./dataset/images')), len(os.listdir('./dataset/val_images')), len(os.listdir('./dataset/labels')))","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2021-12-14T21:52:04.254651Z","iopub.execute_input":"2021-12-14T21:52:04.255576Z","iopub.status.idle":"2021-12-14T22:06:49.13548Z","shell.execute_reply.started":"2021-12-14T21:52:04.255529Z","shell.execute_reply":"2021-12-14T22:06:49.134293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Model Utils","metadata":{}},{"cell_type":"code","source":"!mkdir -p /root/.config/Ultralytics\n!cp /kaggle/input/yolov5-font/Arial.ttf /root/.config/Ultralytics/","metadata":{"execution":{"iopub.status.busy":"2021-12-15T05:57:48.725631Z","iopub.execute_input":"2021-12-15T05:57:48.726142Z","iopub.status.idle":"2021-12-15T05:57:50.127091Z","shell.execute_reply.started":"2021-12-15T05:57:48.726103Z","shell.execute_reply":"2021-12-15T05:57:50.126108Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!cp /kaggle/input/run-1280-yolov5l/best.pt /kaggle/working/best.pt\n\n!cp -r /kaggle/input/yolov5l-train-output-map-0/dataset/images/. /kaggle/working/dataset/images/\n!cp -r /kaggle/input/yolov5l-train-output-map-0/dataset/labels/. /kaggle/working/dataset/labels/","metadata":{"execution":{"iopub.status.busy":"2021-12-15T05:57:52.867765Z","iopub.execute_input":"2021-12-15T05:57:52.868272Z","iopub.status.idle":"2021-12-15T05:58:38.829365Z","shell.execute_reply.started":"2021-12-15T05:57:52.868233Z","shell.execute_reply":"2021-12-15T05:58:38.828477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(os.listdir('./dataset/images')), len(os.listdir('./dataset/labels')))","metadata":{"execution":{"iopub.status.busy":"2021-12-15T05:58:42.035463Z","iopub.execute_input":"2021-12-15T05:58:42.035914Z","iopub.status.idle":"2021-12-15T05:58:42.082111Z","shell.execute_reply.started":"2021-12-15T05:58:42.035877Z","shell.execute_reply":"2021-12-15T05:58:42.081311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport gc\nimport torch\nfrom yolov5 import train, val, detect, export\n\n# train model\ndef train_model(imgsz=1280, data='/kaggle/working/reef.yaml', weights='/kaggle/working/best.pt', device='cuda:0', \n                epochs=12, batch_size=6, project='reef_train_2', name='impr_1280_train_2', workers=0,\n                hyp='', save_period=4, exist_ok=True, resume=False):\n    # save_period : Save checkpoint every x epochs (disabled if < 1)\n    # run gc first\n    gc.collect()\n    # make sure directory is set\n    os.chdir('/kaggle/working/')\n    # train model\n    train.run(imgsz=imgsz, data=data, device=device, weights=weights, epochs=epochs, batch_size=batch_size, project=project, name=name, workers=workers,\n             hyp=hyp, save_period=save_period, exist_ok=exist_ok, resume=resume, evolve=True)\n    print('training done')\n\n# validate model\ndef validate_model(imgsz=1024, data='/kaggle/working/reef.yaml', weights='/kaggle/input/run-1280-yolov51/best.pt', device='cuda:0', \n                epochs=15, batch_size=12, project='reef_train_2', name='impr_1280_val', workers=0,\n                hyp='', save_period=6):\n    # run gc first\n    gc.collect()\n    # make sure directory is set\n    os.chdir('/kaggle/working/')\n    # validate model\n    val.run(imgsz=imgsz, data=data, device=device, weights=weights, epochs=epochs, batch_size=batch_size, project=project, name=name, workers=workers)\n    print('val done')\n\n# detect\ndef detect_source(img_path, weights, conf=0.50, iou=0.55, imgsz=1280):\n    # run gc first\n    gc.collect()\n    # make sure directory is set\n    os.chdir('/kaggle/working/')\n    # predict\n    detect.run(source=img_path, weights=weights, conf_thres=conf, iou_thres=iou, imgsz=imgsz)\n    \n# load model from yolov5\ndef load_model(model_path = \"/kaggle/input/run-1280-yolov5l/best.pt\", device = \"cuda:0\", conf = 0.40, iou = 0.5):\n    from yolov5 import YOLOv5\n\n    if not torch.cuda.is_available():\n        print('using cpu')\n        device = 'cpu'\n    else:\n        print('using gpu')\n        \n    yolov5 = YOLOv5(model_path, device)\n    yolov5.model.conf = conf\n    yolov5.model.iou = iou\n    yolov5.model.max_det = 500\n    return yolov5\n\ndef load_model_ultralytics():\n    model = torch.hub.load('/kaggle/input/yolov5-lib-ds',\n                           'custom',\n                           path='/kaggle/input/run-1280-yolov5l/best.pt',\n                           source='local',\n                           force_reload=True)  # local repo\n    \n    if torch.cuda.is_available():\n        model.cuda()\n        print('using gpu')\n    else:\n        model.cpu()\n        print('using cpu')\n\n    model.conf = 0.40\n    model.iou = 0.50\n    model.max_det = 500\n    model.classes = None   # (optional list) filter by class, i.e. = [0, 15, 16] for persons, cats and dogs\n    model.multi_label = False  # NMS multiple labels per box\n    return model\n","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2021-12-15T05:59:09.290688Z","iopub.execute_input":"2021-12-15T05:59:09.291264Z","iopub.status.idle":"2021-12-15T05:59:09.367391Z","shell.execute_reply.started":"2021-12-15T05:59:09.291224Z","shell.execute_reply":"2021-12-15T05:59:09.366673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# to train model, uncomment below\ntrain_model()\n\n# to eval model, uncomment below\n# validate_model()\n\n# to detect manual, uncomment below\n# detect_source('dataset/images/0_18.jpg')","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2021-12-15T05:59:14.286735Z","iopub.execute_input":"2021-12-15T05:59:14.287245Z","iopub.status.idle":"2021-12-15T06:02:28.402627Z","shell.execute_reply.started":"2021-12-15T05:59:14.287210Z","shell.execute_reply":"2021-12-15T06:02:28.401533Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Image & Bounding Box Data Utils","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport matplotlib \n%matplotlib inline\nimport cv2\n\ndef predictionsToCVFormat(results, debug_print = False):\n    res = []\n    if results is not None:\n        rp = results.pandas().xyxy\n        if debug_print:\n            print('[debug] result : ', rp)\n\n        if rp is not None:\n            preds = rp[0]\n            if preds is not None:\n                bboxes  = preds[['xmin','ymin','xmax','ymax']].values.astype(int)\n                if bboxes is not None:\n                    scores = preds.confidence.values\n                    classes = preds.name.values\n                    score_sum = np.sum(scores)\n                    total_preds = len(preds.confidence.values)\n                    if total_preds >= 1:\n                        avg_conf = score_sum/total_preds\n                        print(f'Total starfishs : {total_preds}, Average confidence : {avg_conf}')\n                    else:\n                        print(\"No starfish detected\")\n                    for idx, bbox in enumerate(bboxes):\n                        res.append({\n                            \"xmin\": bbox[0],\n                            \"ymin\": bbox[1],\n                            \"xmax\": bbox[2],\n                            \"ymax\": bbox[3],\n                            \"score\": round(scores[idx], 2),\n                            \"label\": classes[idx]\n                        })\n        \n    return res\n\ndef getSubmissionFormatBB(dict_list):    \n    ann = ''\n    if len(dict_list)>0:\n        for data in dict_list:\n            xmin = int(data['xmin'])\n            ymin = int(data['ymin'])\n            xmax = int(data['xmax'])\n            ymax = int(data['ymax'])\n            score = data['score']\n            w = xmax - xmin\n            h = ymax - ymin\n            xmin, ymin, w, h = xmin, ymin, w, h\n            ann += f'{score} {xmin} {ymin} {w} {h}'\n            ann +=' '\n        ann = ann.strip(' ')\n    return ann\n\ndef drawBoundingBoxes(imageData, infer_results):\n    if infer_results:\n        pinkish_red = (227, 27, 90)\n        starfish_count = len(infer_results)\n        for res in infer_results:\n            left = int(res['xmin'])\n            top = int(res['ymin'])\n            right = int(res['xmax'])\n            bottom = int(res['ymax'])\n            score = res['score']\n            label = res['label'] if res['label'] is not None else 'starfish'\n            imgHeight, imgWidth, _ = imageData.shape\n            thick = int((imgHeight + imgWidth) // 750) * 2\n            cv2.rectangle(imageData,(left, top), (right, bottom), pinkish_red, thick)\n\n            tf = max(thick - 1, 1)   # font thickness\n            t_size = cv2.getTextSize(label, 0, fontScale=thick / 3, thickness=int(tf))[0]\n            c2 = left + t_size[0], top - t_size[1] + 2\n            cv2.rectangle(imageData, (left, top ), c2, pinkish_red, -1, cv2.LINE_AA)  # filled\n            cv2.putText(imageData, f'{label} {score}', (left, top - 6), 0, 1e-3 * imgHeight, (255,255,255), int(thick*0.5))\n        \n    return imageData\n\ndef displayImage(path_or_image, infer_results = [], just_return = False):\n    from IPython.display import display\n\n    # if path is given, read image \n    if path_or_image is not None and type(path_or_image) is str:\n        image = cv2.imread(path_or_image)\n    else:\n        image = path_or_image\n        \n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    image = drawBoundingBoxes(image, infer_results)\n    if not just_return:\n        display(Image.fromarray(image))\n    return image","metadata":{"execution":{"iopub.status.busy":"2021-12-15T05:20:42.318874Z","iopub.execute_input":"2021-12-15T05:20:42.320596Z","iopub.status.idle":"2021-12-15T05:20:42.429161Z","shell.execute_reply.started":"2021-12-15T05:20:42.320555Z","shell.execute_reply":"2021-12-15T05:20:42.428142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Load Model","metadata":{}},{"cell_type":"code","source":"# load model \n# model = load_model('../input/yolov5l-train-output-map-0/reef_train_2/impr_1280_train/weights/last.pt') # either load from my script\n# model = load_model_ultralytics() # or load from ultralytics script","metadata":{"execution":{"iopub.status.busy":"2021-12-14T07:57:00.279756Z","iopub.execute_input":"2021-12-14T07:57:00.280104Z","iopub.status.idle":"2021-12-14T07:57:08.247643Z","shell.execute_reply.started":"2021-12-14T07:57:00.280054Z","shell.execute_reply":"2021-12-14T07:57:08.2463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Run inference on Train","metadata":{}},{"cell_type":"code","source":"# import random\n# random.seed(24)\n# def plot_img(img_dir,num_items,func,mode):\n#     import tensorflow as tf\n    \n#     img_list = random.sample(os.listdir(img_dir), num_items)\n#     for i in range(len(img_list)):\n#         splt = img_list[i].split('-')\n#         vf = splt[0]\n#         ff = splt[1]\n#         og_img_path = f'../input/tensorflow-great-barrier-reef/train_images/video_{vf}/{ff}'\n#         full_path = img_dir + '/' + img_list[i]\n#         img_temp1 = plt.imread(full_path)\n#         og_img = plt.imread(og_img_path)\n#         img_temp_cv = cv2.imread(full_path)\n#         plt.figure(figsize=(30,25))\n#         plt.subplot(1,2,1)\n#         plt.imshow(og_img)\n# #         plt.subplot(1,4,2)\n#         if mode == 'plt':\n#             plt.subplot(1,2,2)\n# #             plt.imshow(func(img_temp1))\n#             plt.imshow(img_temp1, cmap = plt.get_cmap(name = 'gray'))\n\n#         elif mode == 'cv2':\n#             plt.imshow(func(img_temp_cv, add_random=True));\n            \n# vid_0_dir = \"../input/tensorflow-great-barrier-reef/train_images/video_0\"\n# ds_dir = \"../input/yolov5l-train-output-map-0/dataset/images\"\n# val_ds_dir = \"./dataset/images\"\n# num_items1 = 5\n# plot_img(ds_dir,num_items1,enhance_image,\"plt\")","metadata":{"execution":{"iopub.status.busy":"2021-12-15T05:09:07.848485Z","iopub.execute_input":"2021-12-15T05:09:07.849268Z","iopub.status.idle":"2021-12-15T05:09:14.187073Z","shell.execute_reply.started":"2021-12-15T05:09:07.849219Z","shell.execute_reply":"2021-12-15T05:09:14.184851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import os\n# import gc\n# import torch\n# import matplotlib.pyplot as plt\n\n# from yolov5 import YOLOv5\n\n# gc.collect()\n\n# os.chdir('/kaggle/working/')\n# model = load_model('../input/yolov5l-train-output-map-0/reef_train_2/impr_1280_train/weights/last.pt')\n# og_model = load_model('../input/run-1280-yolov5l/best.pt')\n\n# image_paths = get_sample_imgs(100)\n# ds_dir = \"../input/yolov5l-train-output-map-0/dataset/images/\"\n# num_items1 = 5\n# image_paths1 = random.sample(os.listdir(ds_dir), num_items1)\n# print(image_paths1)\n# for i in range(len(image_paths1)):\n#     splt = image_paths1[i].split('-')\n#     vf = splt[0]\n#     ff = splt[1]\n#     og_img_path = f'../input/tensorflow-great-barrier-reef/train_images/video_{vf}/{ff}'\n#     path = ds_dir + '/' + image_paths1[i]\n# # for idx, path in enumerate(image_paths):\n#     if os.path.exists(path) and os.path.isfile(path):\n#         image = cv2.imread(path)\n\n#         results = model.predict(path, size=1280, augment=True)\n#         bb_list = predictionsToCVFormat(results)\n#         og_results = og_model.predict(path, size=1280, augment=True)\n#         og_bb_list = predictionsToCVFormat(og_results)\n#         plt.figure(figsize=(30,25))\n#         plt.subplot(1,2,1)\n#         plt.imshow(displayImage(image, og_bb_list, True), cmap = plt.get_cmap(name = 'gray'))\n#         plt.subplot(1,2,2)\n#         plt.imshow(displayImage(image, bb_list, True), cmap = plt.get_cmap(name = 'gray'))\n        \n# #         if idx>1:\n# #             break\n            \n# del image_paths","metadata":{"execution":{"iopub.status.busy":"2021-12-15T05:43:59.571761Z","iopub.execute_input":"2021-12-15T05:43:59.572252Z","iopub.status.idle":"2021-12-15T05:45:18.959632Z","shell.execute_reply.started":"2021-12-15T05:43:59.572215Z","shell.execute_reply":"2021-12-15T05:45:18.958973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Init env","metadata":{}},{"cell_type":"code","source":"# import os\n# import gc\n# import matplotlib.pyplot as plt\n# import greatbarrierreef\n\n# # os.chdir('/kaggle/working/')\n# os.chdir('/kaggle/')\n\n# print('starting infer')\n\n# # init environment\n# env = greatbarrierreef.make_env() # initialize the environment\n# iter_test = env.iter_test()      # an iterator which loops over the test set and sample submission\n\n# for img, pred_df in iter_test:\n# #     results = model.predict(img, size=1280, augment=True)\n#     img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n#     results = model(img, size=1280, augment=True)\n#     bb_list = predictionsToCVFormat(results)\n#     annot = getSubmissionFormatBB(bb_list)\n#     pred_df['annotations'] = annot\n#     env.predict(pred_df)\n# #     displayImage(img, bb_list, img)\n\n# del model","metadata":{"execution":{"iopub.status.busy":"2021-12-13T08:36:59.726146Z","iopub.execute_input":"2021-12-13T08:36:59.726662Z","iopub.status.idle":"2021-12-13T08:37:02.176842Z","shell.execute_reply.started":"2021-12-13T08:36:59.726626Z","shell.execute_reply":"2021-12-13T08:37:02.175863Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# sub_df = pd.read_csv('submission.csv')\n# sub_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-12-13T08:37:24.068703Z","iopub.execute_input":"2021-12-13T08:37:24.06899Z","iopub.status.idle":"2021-12-13T08:37:24.087223Z","shell.execute_reply.started":"2021-12-13T08:37:24.068959Z","shell.execute_reply":"2021-12-13T08:37:24.086133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### References\n- Improvements learned from [Learning to Sea: Underwater img Enhancement](https://www.kaggle.com/soumya9977/learning-to-sea-underwater-img-enhancement-eda#%F0%9F%8E%AF-Main-Working-Code)\n- Improved white balance implementation by [gist](https://gist.github.com/DavidYKay/9dad6c4ab0d8d7dbf3dc#gistcomment-3025656)\n- [Image preprocessing tips](https://machinelearningmastery.com/how-to-configure-image-data-augmentation-when-training-deep-learning-neural-networks/)","metadata":{}}]}