{"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":"# help protect the Great Barrier Reef","metadata":{}},{"cell_type":"markdown","source":"## Install Libraries","metadata":{}},{"cell_type":"code","source":"!pip install -q imagesize\n!pip install -qU wandb\n!add-apt-repository ppa:ubuntu-toolchain-r/test -y\n!apt-get update\n!apt-get upgrade libstdc++6 -y","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:36:29.12308Z","iopub.execute_input":"2021-12-02T11:36:29.124074Z","iopub.status.idle":"2021-12-02T11:41:29.964297Z","shell.execute_reply.started":"2021-12-02T11:36:29.123952Z","shell.execute_reply":"2021-12-02T11:41:29.962897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Import Libraries","metadata":{}},{"cell_type":"code","source":"from itertools import groupby\nimport numpy as np\nfrom tqdm.notebook import tqdm\ntqdm.pandas()\nimport pandas as pd\nimport os\nimport pickle\nimport cv2\nfrom multiprocessing import Pool\nimport matplotlib.pyplot as plt\n# import cupy as cp\nimport ast\nimport glob","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:41:29.967289Z","iopub.execute_input":"2021-12-02T11:41:29.968039Z","iopub.status.idle":"2021-12-02T11:41:30.272693Z","shell.execute_reply.started":"2021-12-02T11:41:29.967975Z","shell.execute_reply":"2021-12-02T11:41:30.2717Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil\nimport sys\nsys.path.append('../input/tensorflow-great-barrier-reef')\n\nfrom joblib import Parallel, delayed\nimport imagesize","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:41:30.274691Z","iopub.execute_input":"2021-12-02T11:41:30.274999Z","iopub.status.idle":"2021-12-02T11:41:30.350469Z","shell.execute_reply.started":"2021-12-02T11:41:30.274955Z","shell.execute_reply":"2021-12-02T11:41:30.349382Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Meta Data","metadata":{}},{"cell_type":"code","source":"FOLD      = 6 # which fold to train\nREMOVE_NOBBOX = True # 删除没有 bbox 的图像\nROOT_DIR  = '/kaggle/input/tensorflow-great-barrier-reef/'\nIMAGE_DIR = '/kaggle/images' # 保存图片的目录\nLABEL_DIR = '/kaggle/labels' # 保存标签的目录","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:41:30.353299Z","iopub.execute_input":"2021-12-02T11:41:30.353673Z","iopub.status.idle":"2021-12-02T11:41:30.361771Z","shell.execute_reply.started":"2021-12-02T11:41:30.353627Z","shell.execute_reply":"2021-12-02T11:41:30.36066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 1.创建目录","metadata":{}},{"cell_type":"code","source":"!mkdir -p {IMAGE_DIR}\n!mkdir -p {LABEL_DIR}","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:41:30.364723Z","iopub.execute_input":"2021-12-02T11:41:30.365367Z","iopub.status.idle":"2021-12-02T11:41:31.887066Z","shell.execute_reply.started":"2021-12-02T11:41:30.365262Z","shell.execute_reply":"2021-12-02T11:41:31.885838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 2.Get Paths","metadata":{}},{"cell_type":"code","source":"def get_path(row):\n    row['old_image_path'] = f'{ROOT_DIR}/train_images/video_{row.video_id}/{row.video_frame}.jpg'\n    row['image_path'] = f'{IMAGE_DIR}/video_{row.video_id}_{row.video_frame}.jpg'\n    row['label_path'] = f'{LABEL_DIR}/video_{row.video_id}_{row.video_frame}.txt'\n    return row","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:41:31.889768Z","iopub.execute_input":"2021-12-02T11:41:31.890396Z","iopub.status.idle":"2021-12-02T11:41:31.899488Z","shell.execute_reply.started":"2021-12-02T11:41:31.890317Z","shell.execute_reply":"2021-12-02T11:41:31.89825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train Data\ndf = pd.read_csv(f'{ROOT_DIR}/train.csv')\ndf = df.progress_apply(get_path, axis=1)\ndf['annotations'] = df['annotations'].progress_apply(lambda x: ast.literal_eval(x))\ndisplay(df.head(2))","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:41:31.901141Z","iopub.execute_input":"2021-12-02T11:41:31.901766Z","iopub.status.idle":"2021-12-02T11:42:30.595657Z","shell.execute_reply.started":"2021-12-02T11:41:31.901717Z","shell.execute_reply":"2021-12-02T11:42:30.594389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 3.求BBox 数量","metadata":{}},{"cell_type":"code","source":"df['num_bbox'] = df['annotations'].progress_apply(lambda x: len(x))\ndata = (df.num_bbox>0).value_counts(normalize=True)*100\nprint(f\"No BBox: {data[0]:0.2f}% | With BBox: {data[1]:0.2f}%\")","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:42:30.597436Z","iopub.execute_input":"2021-12-02T11:42:30.597882Z","iopub.status.idle":"2021-12-02T11:42:30.723019Z","shell.execute_reply.started":"2021-12-02T11:42:30.597827Z","shell.execute_reply":"2021-12-02T11:42:30.722043Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* 近80%的图片没有BBox","metadata":{}},{"cell_type":"markdown","source":"## 数据清理","metadata":{}},{"cell_type":"code","source":"if REMOVE_NOBBOX:\n    df = df.query(\"num_bbox>0\")","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:42:30.724643Z","iopub.execute_input":"2021-12-02T11:42:30.725169Z","iopub.status.idle":"2021-12-02T11:42:30.755041Z","shell.execute_reply.started":"2021-12-02T11:42:30.725126Z","shell.execute_reply":"2021-12-02T11:42:30.754171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 将图像复制到当前目录","metadata":{}},{"cell_type":"code","source":"def make_copy(path):\n    data = path.split('/')\n    filename = data[-1]\n    video_id = data[-2]\n    new_path = os.path.join(IMAGE_DIR,f'{video_id}_{filename}')\n    shutil.copy(path, new_path)\n    return","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:42:30.758933Z","iopub.execute_input":"2021-12-02T11:42:30.75917Z","iopub.status.idle":"2021-12-02T11:42:30.765016Z","shell.execute_reply.started":"2021-12-02T11:42:30.759143Z","shell.execute_reply":"2021-12-02T11:42:30.763746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_paths = df.old_image_path.tolist()\n_ = Parallel(n_jobs=-1, backend='threading')(delayed(make_copy)(path) for path in tqdm(image_paths))","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:42:30.767556Z","iopub.execute_input":"2021-12-02T11:42:30.767978Z","iopub.status.idle":"2021-12-02T11:43:10.170297Z","shell.execute_reply.started":"2021-12-02T11:42:30.767921Z","shell.execute_reply":"2021-12-02T11:43:10.169262Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def voc2yolo(image_height, image_width, bboxes):\n    \"\"\"\n    voc  => [x1, y1, x2, y1]\n    yolo => [xmid, ymid, w, h] (normalized)\n    \"\"\"\n    \n    bboxes = bboxes.copy().astype(float) # otherwise all value will be 0 as voc_pascal dtype is np.int\n    \n    bboxes[..., [0, 2]] = bboxes[..., [0, 2]]/ image_width\n    bboxes[..., [1, 3]] = bboxes[..., [1, 3]]/ image_height\n    \n    w = bboxes[..., 2] - bboxes[..., 0]\n    h = bboxes[..., 3] - bboxes[..., 1]\n    \n    bboxes[..., 0] = bboxes[..., 0] + w/2\n    bboxes[..., 1] = bboxes[..., 1] + h/2\n    bboxes[..., 2] = w\n    bboxes[..., 3] = h\n    \n    return bboxes\n\ndef yolo2voc(image_height, image_width, bboxes):\n    \"\"\"\n    yolo => [xmid, ymid, w, h] (normalized)\n    voc  => [x1, y1, x2, y1]\n    \n    \"\"\" \n    bboxes = bboxes.copy().astype(float) # otherwise all value will be 0 as voc_pascal dtype is np.int\n    \n    bboxes[..., [0, 2]] = bboxes[..., [0, 2]]* image_width\n    bboxes[..., [1, 3]] = bboxes[..., [1, 3]]* image_height\n    \n    bboxes[..., [0, 1]] = bboxes[..., [0, 1]] - bboxes[..., [2, 3]]/2\n    bboxes[..., [2, 3]] = bboxes[..., [0, 1]] + bboxes[..., [2, 3]]\n    \n    return bboxes\n\ndef coco2yolo(image_height, image_width, bboxes):\n    \"\"\"\n    coco => [xmin, ymin, w, h]\n    yolo => [xmid, ymid, w, h] (normalized)\n    \"\"\"\n    \n    bboxes = bboxes.copy().astype(float) # otherwise all value will be 0 as voc_pascal dtype is np.int\n    \n    # normolizinig\n    bboxes[..., [0, 2]]= bboxes[..., [0, 2]]/ image_width\n    bboxes[..., [1, 3]]= bboxes[..., [1, 3]]/ image_height\n    \n    # converstion (xmin, ymin) => (xmid, ymid)\n    bboxes[..., [0, 1]] = bboxes[..., [0, 1]] + bboxes[..., [2, 3]]/2\n    \n    return bboxes\n\ndef yolo2coco(image_height, image_width, bboxes):\n    \"\"\"\n    yolo => [xmid, ymid, w, h] (normalized)\n    coco => [xmin, ymin, w, h]\n    \n    \"\"\" \n    bboxes = bboxes.copy().astype(float) # otherwise all value will be 0 as voc_pascal dtype is np.int\n    \n    # denormalizing\n    bboxes[..., [0, 2]]= bboxes[..., [0, 2]]* image_width\n    bboxes[..., [1, 3]]= bboxes[..., [1, 3]]* image_height\n    \n    # converstion (xmid, ymid) => (xmin, ymin) \n    bboxes[..., [0, 1]] = bboxes[..., [0, 1]] - bboxes[..., [2, 3]]/2\n    \n    return bboxes\n\n\ndef load_image(image_path):\n    return cv2.cvtColor(cv2.imread(image_path), cv2.COLOR_BGR2RGB)\n\n\ndef plot_one_box(x, img, color=None, label=None, line_thickness=None):\n    # Plots one bounding box on image img\n    tl = line_thickness or round(0.002 * (img.shape[0] + img.shape[1]) / 2) + 1  # line/font thickness\n    color = color or [random.randint(0, 255) for _ in range(3)]\n    c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))\n    cv2.rectangle(img, c1, c2, color, thickness=tl, lineType=cv2.LINE_AA)\n    if label:\n        tf = max(tl - 1, 1)  # font thickness\n        t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]\n        c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3\n        cv2.rectangle(img, c1, c2, color, -1, cv2.LINE_AA)  # filled\n        cv2.putText(img, label, (c1[0], c1[1] - 2), 0, tl / 3, [225, 255, 255], thickness=tf, lineType=cv2.LINE_AA)\n\ndef draw_bboxes(img, bboxes, classes, class_ids, colors = None, show_classes = None, bbox_format = 'yolo', class_name = False, line_thickness = 2):  \n     \n    image = img.copy()\n    show_classes = classes if show_classes is None else show_classes\n    colors = (0, 255 ,0) if colors is None else colors\n    \n    if bbox_format == 'yolo':\n        \n        for idx in range(len(bboxes)):  \n            \n            bbox  = bboxes[idx]\n            cls   = classes[idx]\n            cls_id = class_ids[idx]\n            color = colors[cls_id] if type(colors) is list else colors\n            \n            if cls in show_classes:\n            \n                x1 = round(float(bbox[0])*image.shape[1])\n                y1 = round(float(bbox[1])*image.shape[0])\n                w  = round(float(bbox[2])*image.shape[1]/2) #w/2 \n                h  = round(float(bbox[3])*image.shape[0]/2)\n\n                voc_bbox = (x1-w, y1-h, x1+w, y1+h)\n                plot_one_box(voc_bbox, \n                             image,\n                             color = color,\n                             label = cls if class_name else str(get_label(cls)),\n                             line_thickness = line_thickness)\n            \n    elif bbox_format == 'coco':\n        \n        for idx in range(len(bboxes)):  \n            \n            bbox  = bboxes[idx]\n            cls   = classes[idx]\n            cls_id = class_ids[idx]\n            color = colors[cls_id] if type(colors) is list else colors\n            \n            if cls in show_classes:            \n                x1 = int(round(bbox[0]))\n                y1 = int(round(bbox[1]))\n                w  = int(round(bbox[2]))\n                h  = int(round(bbox[3]))\n\n                voc_bbox = (x1, y1, x1+w, y1+h)\n                plot_one_box(voc_bbox, \n                             image,\n                             color = color,\n                             label = cls if class_name else str(cls_id),\n                             line_thickness = line_thickness)\n\n    elif bbox_format == 'voc_pascal':\n        \n        for idx in range(len(bboxes)):  \n            \n            bbox  = bboxes[idx]\n            cls   = classes[idx]\n            cls_id = class_ids[idx]\n            color = colors[cls_id] if type(colors) is list else colors\n            \n            if cls in show_classes: \n                x1 = int(round(bbox[0]))\n                y1 = int(round(bbox[1]))\n                x2 = int(round(bbox[2]))\n                y2 = int(round(bbox[3]))\n                voc_bbox = (x1, y1, x2, y2)\n                plot_one_box(voc_bbox, \n                             image,\n                             color = color,\n                             label = cls if class_name else str(cls_id),\n                             line_thickness = line_thickness)\n    else:\n        raise ValueError('wrong bbox format')\n\n    return image\n\ndef get_bbox(annots):\n    bboxes = [list(annot.values()) for annot in annots]\n    return bboxes\n\ndef get_imgsize(row):\n    row['width'], row['height'] = imagesize.get(row['image_path'])\n    return row\n\nnp.random.seed(32)\ncolors = [(np.random.randint(255), np.random.randint(255), np.random.randint(255))\\\n          for idx in range(1)]","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:10.174207Z","iopub.execute_input":"2021-12-02T11:43:10.174547Z","iopub.status.idle":"2021-12-02T11:43:10.300293Z","shell.execute_reply.started":"2021-12-02T11:43:10.174512Z","shell.execute_reply":"2021-12-02T11:43:10.299416Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 创建 BBox","metadata":{}},{"cell_type":"code","source":"df['bboxes'] = df.annotations.progress_apply(get_bbox)\ndf.head(2)","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:10.303635Z","iopub.execute_input":"2021-12-02T11:43:10.304098Z","iopub.status.idle":"2021-12-02T11:43:10.795723Z","shell.execute_reply.started":"2021-12-02T11:43:10.304051Z","shell.execute_reply":"2021-12-02T11:43:10.794713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 获取图像大小","metadata":{}},{"cell_type":"code","source":"df = df.progress_apply(get_imgsize,axis=1)\ndisplay(df.width.unique(), df.height.unique())\ndisplay(df.head(2))","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:10.797478Z","iopub.execute_input":"2021-12-02T11:43:10.798003Z","iopub.status.idle":"2021-12-02T11:43:20.079642Z","shell.execute_reply.started":"2021-12-02T11:43:10.797942Z","shell.execute_reply":"2021-12-02T11:43:20.078475Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* 所有图像具有相同的尺寸，[Width，Height] = [1280, 720]","metadata":{}},{"cell_type":"markdown","source":"## 创建标签","metadata":{}},{"cell_type":"markdown","source":"* 需要将标签导出为YOLO格式，每个图像有一个 *.txt 文件（如果图像中没有对象，则不需要 *.txt 文件）。*.txt 文件规范是：\n1. 每个对象一行\n2. 每行都是类 [x_center, y_center, width, height] 格式。\n3. 方框坐标必须是标准化的xywh格式（从0-1）。如果你的方框是像素，那么x_center和宽度要除以图像宽度，y_center和高度要除以图像高度。\n4. 类号是零索引的（从 0 开始）。\n5. 类号是零索引的（从 0 开始）。","metadata":{}},{"cell_type":"markdown","source":"* 比赛 bbox 格式是 COCO 因此 [x_min, y_min, width, height]。所以，我们需要将 COCO 格式转换为 YOLO 格式。","metadata":{}},{"cell_type":"code","source":"cnt = 0\nall_bboxes = []\nfor row_idx in tqdm(range(df.shape[0])):\n    row = df.iloc[row_idx]\n    image_height = row.height\n    image_width  = row.width\n    bboxes_coco  = np.array(row.bboxes).astype(np.float32).copy()\n    num_bbox     = len(bboxes_coco)\n    names        = ['cots']*num_bbox\n    labels       = [0]*num_bbox\n    ## Create Annotation(YOLO)\n    with open(row.label_path, 'w') as f:\n        if num_bbox<1:\n            annot = ''\n            f.write(annot)\n            cnt+=1\n            continue\n        bboxes_yolo  = coco2yolo(image_height, image_width, bboxes_coco)\n        bboxes_yolo  = np.clip(bboxes_yolo, 0, 1)\n        all_bboxes.extend(bboxes_yolo)\n        for bbox_idx in range(len(bboxes_yolo)):\n            annot = [str(labels[bbox_idx])]+ list(bboxes_yolo[bbox_idx].astype(str))+(['\\n'] if num_bbox!=(bbox_idx+1) else [''])\n            annot = ' '.join(annot)\n            annot = annot.strip(' ')\n            f.write(annot)\nprint('Missing:',cnt)","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:20.081404Z","iopub.execute_input":"2021-12-02T11:43:20.081887Z","iopub.status.idle":"2021-12-02T11:43:23.862047Z","shell.execute_reply.started":"2021-12-02T11:43:20.081841Z","shell.execute_reply":"2021-12-02T11:43:23.860888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"##  BBox Distribution","metadata":{}},{"cell_type":"code","source":"#x_center Vs y_center\nfrom scipy.stats import gaussian_kde\n\nall_bboxes = np.array(all_bboxes)\n\nx_val = all_bboxes[...,0]\ny_val = all_bboxes[...,1]\n\n# Calculate the point density\nxy = np.vstack([x_val,y_val])\nz = gaussian_kde(xy)(xy)\n\nfig, ax = plt.subplots(figsize = (10, 10))\nax.axis('off')\nax.scatter(x_val, y_val, c=z, s=100, cmap='viridis')\n# ax.set_xlabel('x_mid')\n# ax.set_ylabel('y_mid')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:23.864102Z","iopub.execute_input":"2021-12-02T11:43:23.864468Z","iopub.status.idle":"2021-12-02T11:43:28.409564Z","shell.execute_reply.started":"2021-12-02T11:43:23.864421Z","shell.execute_reply":"2021-12-02T11:43:28.408713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#width Vs height\nx_val = all_bboxes[...,2]\ny_val = all_bboxes[...,3]\n\n# 计算点密度\nxy = np.vstack([x_val,y_val])\nz = gaussian_kde(xy)(xy)\n\nfig, ax = plt.subplots(figsize = (10, 10))\nax.axis('off')\nax.scatter(x_val, y_val, c=z, s=100, cmap='viridis')\n# ax.set_xlabel('bbox_width')\n# ax.set_ylabel('bbox_height')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:28.410846Z","iopub.execute_input":"2021-12-02T11:43:28.411766Z","iopub.status.idle":"2021-12-02T11:43:32.371187Z","shell.execute_reply.started":"2021-12-02T11:43:28.411714Z","shell.execute_reply":"2021-12-02T11:43:32.370218Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Area\nimport seaborn as sns\nsns.set(style='white')\nareas = all_bboxes[...,2]*all_bboxes[...,3]*720*1280\nplt.figure(figsize=(12,8))\nsns.kdeplot(areas,shade=True,palette='viridis')\nplt.axis('OFF')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:32.373049Z","iopub.execute_input":"2021-12-02T11:43:32.373681Z","iopub.status.idle":"2021-12-02T11:43:32.782213Z","shell.execute_reply.started":"2021-12-02T11:43:32.373632Z","shell.execute_reply":"2021-12-02T11:43:32.781236Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 可视化","metadata":{}},{"cell_type":"code","source":"df2 = df[(df.num_bbox>0)].sample(100) # takes samples with bbox\nfor idx in range(10):\n    row = df2.iloc[idx]\n    img           = load_image(row.image_path)\n    image_height  = row.height\n    image_width   = row.width\n    bboxes_coco   = np.array(row.bboxes)\n    bboxes_yolo   = coco2yolo(image_height, image_width, bboxes_coco)\n    names         = ['cots']*len(bboxes_coco)\n    labels        = [0]*len(bboxes_coco)\n\n    plt.figure(figsize = (12, 8))\n    plt.imshow(draw_bboxes(img = img,\n                           bboxes = bboxes_yolo, \n                           classes = names,\n                           class_ids = labels,\n                           class_name = True, \n                           colors = colors, \n                           bbox_format = 'yolo',\n                           line_thickness = 2))\n    plt.axis('OFF')\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:32.783929Z","iopub.execute_input":"2021-12-02T11:43:32.784466Z","iopub.status.idle":"2021-12-02T11:43:37.659787Z","shell.execute_reply.started":"2021-12-02T11:43:32.784421Z","shell.execute_reply":"2021-12-02T11:43:37.658986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create Folds","metadata":{}},{"cell_type":"markdown","source":"如果每个折叠中的样本数量不一样，会在交叉验证中会产生很大的差异。","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import GroupKFold\nkf = GroupKFold(n_splits = 10) # num_folds=3 as there are total 3 videos\ndf = df.reset_index(drop=True)\ndf['fold'] = -1\nfor fold, (train_idx, val_idx) in enumerate(kf.split(df, y = df.video_id.tolist(), groups=df.sequence)):\n    df.loc[val_idx, 'fold'] = fold\ndisplay(df.fold.value_counts())","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:37.661463Z","iopub.execute_input":"2021-12-02T11:43:37.66194Z","iopub.status.idle":"2021-12-02T11:43:37.787555Z","shell.execute_reply.started":"2021-12-02T11:43:37.661899Z","shell.execute_reply":"2021-12-02T11:43:37.786369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_files = []\nval_files   = []\ntrain_df = df.query(\"fold!=@FOLD\")\nvalid_df = df.query(\"fold==@FOLD\")\ntrain_files += list(train_df.image_path.unique())\nval_files += list(valid_df.image_path.unique())\nlen(train_files), len(val_files)","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:37.788998Z","iopub.execute_input":"2021-12-02T11:43:37.790751Z","iopub.status.idle":"2021-12-02T11:43:37.814087Z","shell.execute_reply.started":"2021-12-02T11:43:37.790671Z","shell.execute_reply":"2021-12-02T11:43:37.813024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 创建目录","metadata":{}},{"cell_type":"code","source":"import yaml\n\ncwd = '/kaggle/working/'\n\nwith open(os.path.join( cwd , 'train.txt'), 'w') as f:\n    for path in train_df.image_path.tolist():\n        f.write(path+'\\n')\n            \nwith open(os.path.join(cwd , 'val.txt'), 'w') as f:\n    for path in valid_df.image_path.tolist():\n        f.write(path+'\\n')\n\ndata = dict(\n    path  = '/kaggle/working',\n    train =  os.path.join( cwd , 'train.txt') ,\n    val   =  os.path.join( cwd , 'val.txt' ),\n    nc    = 1,\n    names = ['cots'],\n    )\n\nwith open(os.path.join( cwd , 'tgbr.yaml'), 'w') as outfile:\n    yaml.dump(data, outfile, default_flow_style=False)\n\nf = open(os.path.join( cwd , 'tgbr.yaml'), 'r')\nprint('\\nyaml:')\nprint(f.read())","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:37.815368Z","iopub.execute_input":"2021-12-02T11:43:37.816315Z","iopub.status.idle":"2021-12-02T11:43:37.866598Z","shell.execute_reply.started":"2021-12-02T11:43:37.81627Z","shell.execute_reply":"2021-12-02T11:43:37.865458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"##  YOLOv5","metadata":{}},{"cell_type":"code","source":"%cd /kaggle/working\n!rm -r /kaggle/working/yolov5\n\n!cp -r /kaggle/input/yolov5-lib-ds /kaggle/working/yolov5\n%cd yolov5\n!pip install -qr requirements.txt  # install\n","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:37.868205Z","iopub.execute_input":"2021-12-02T11:43:37.86863Z","iopub.status.idle":"2021-12-02T11:43:50.207607Z","shell.execute_reply.started":"2021-12-02T11:43:37.868573Z","shell.execute_reply":"2021-12-02T11:43:50.206389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from yolov5 import utils\ndisplay = utils.notebook_init()  # checks\n\n# Weights & Biases  (optional)\nimport wandb\nwandb.login(anonymous='must')","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:50.21207Z","iopub.execute_input":"2021-12-02T11:43:50.212393Z","iopub.status.idle":"2021-12-02T11:43:54.554535Z","shell.execute_reply.started":"2021-12-02T11:43:50.212357Z","shell.execute_reply":"2021-12-02T11:43:54.55333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 在 COCO128 上训练 YOLOv5s 3 个时期","metadata":{}},{"cell_type":"code","source":"!python train.py --img 1280\\\n--batch 16\\\n--epochs 30\\\n--data /kaggle/working/tgbr.yaml\\\n--weights yolov5s.pt","metadata":{"execution":{"iopub.status.busy":"2021-12-02T11:43:54.565893Z","iopub.execute_input":"2021-12-02T11:43:54.569987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **输出文件**","metadata":{}},{"cell_type":"code","source":"!ls runs/train/exp","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **Class Distribution**","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize = (10,10))\nplt.axis('off')\nplt.imshow(plt.imread('runs/train/exp/labels_correlogram.jpg'));","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize = (10,10))\nplt.axis('off')\nplt.imshow(plt.imread('runs/train/exp/labels.jpg'));","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **批量处理图片**","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nplt.figure(figsize = (10, 10))\nplt.imshow(plt.imread('runs/train/exp/train_batch0.jpg'))\n\nplt.figure(figsize = (10, 10))\nplt.imshow(plt.imread('runs/train/exp/train_batch1.jpg'))\n\nplt.figure(figsize = (10, 10))\nplt.imshow(plt.imread('runs/train/exp/train_batch2.jpg'))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### GT Vs Pred","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(3, 2, figsize = (2*9,3*5), constrained_layout = True)\nfor row in range(3):\n    ax[row][0].imshow(plt.imread(f'runs/train/exp/val_batch{row}_labels.jpg'))\n    ax[row][0].set_xticks([])\n    ax[row][0].set_yticks([])\n    ax[row][0].set_title(f'runs/train/exp/val_batch{row}_labels.jpg', fontsize = 12)\n    \n    ax[row][1].imshow(plt.imread(f'runs/train/exp/val_batch{row}_pred.jpg'))\n    ax[row][1].set_xticks([])\n    ax[row][1].set_yticks([])\n    ax[row][1].set_title(f'runs/train/exp/val_batch{row}_pred.jpg', fontsize = 12)\nplt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **Result**","metadata":{}},{"cell_type":"markdown","source":"### Score Vs Epoch","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(30,15))\nplt.axis('off')\nplt.imshow(plt.imread('runs/train/exp/results.png'));","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Confusion Matrix","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(12,10))\nplt.axis('off')\nplt.imshow(plt.imread('runs/train/exp/confusion_matrix.png'));","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Metrics","metadata":{}},{"cell_type":"code","source":"for metric in ['F1', 'PR', 'P', 'R']:\n    print(f'Metric: {metric}')\n    plt.figure(figsize=(12,10))\n    plt.axis('off')\n    plt.imshow(plt.imread(f'runs/train/exp/{metric}_curve.png'));\n    plt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}