{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np\nimport pandas as pd\nimport cv2\nfrom pathlib import Path\nfrom colorama import Fore, Back, Style\nimport matplotlib.pyplot as plt\nimport ipywidgets as widgets\nfrom IPython.display import display, Image\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n\nROOT_DIR = Path(\"/kaggle/input/tensorflow-great-barrier-reef\")\n\nTRAIN_CSV = ROOT_DIR / \"train.csv\"\nTRAIN_DF = pd.read_csv(TRAIN_CSV)\n\nTEST_CSV = ROOT_DIR / \"test.csv\"\nTEST_DF = pd.read_csv(TEST_CSV)\n\nlist(ROOT_DIR.iterdir())\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"execution":{"iopub.status.busy":"2021-12-01T13:04:22.806434Z","iopub.execute_input":"2021-12-01T13:04:22.806724Z","iopub.status.idle":"2021-12-01T13:04:23.191908Z","shell.execute_reply.started":"2021-12-01T13:04:22.806692Z","shell.execute_reply":"2021-12-01T13:04:23.191048Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 添加常用包","metadata":{}},{"cell_type":"code","source":"import json\n\n\n# Count detections\nif \"detection_count\" not in TRAIN_DF.columns:\n    det_counts = TRAIN_DF.apply(lambda row: len(eval(row.annotations)), axis=1)\n    TRAIN_DF[\"detection_count\"] = det_counts","metadata":{"execution":{"iopub.status.busy":"2021-12-01T13:04:35.792082Z","iopub.execute_input":"2021-12-01T13:04:35.792370Z","iopub.status.idle":"2021-12-01T13:04:35.798285Z","shell.execute_reply.started":"2021-12-01T13:04:35.792337Z","shell.execute_reply":"2021-12-01T13:04:35.797353Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 查看特征属性","metadata":{}},{"cell_type":"code","source":"print(TRAIN_DF.info())\nprint()","metadata":{"execution":{"iopub.status.busy":"2021-12-01T13:04:43.927072Z","iopub.execute_input":"2021-12-01T13:04:43.927526Z","iopub.status.idle":"2021-12-01T13:04:43.953237Z","shell.execute_reply.started":"2021-12-01T13:04:43.927487Z","shell.execute_reply":"2021-12-01T13:04:43.952388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"eq_frames = TRAIN_DF[TRAIN_DF[\"video_frame\"] == TRAIN_DF[\"sequence_frame\"]]\nuneq_frames = TRAIN_DF[TRAIN_DF[\"video_frame\"] != TRAIN_DF[\"sequence_frame\"]]\nprint(\"eq frames, uneq frames:\", eq_frames.size, uneq_frames.size)\nprint()\n# 编号序列从0开始，他们可能切断了没有海星的视频\n\n# 因此，将视频切成序列，每个序列从帧0到n","metadata":{"execution":{"iopub.status.busy":"2021-12-01T13:05:02.432579Z","iopub.execute_input":"2021-12-01T13:05:02.432983Z","iopub.status.idle":"2021-12-01T13:05:02.442077Z","shell.execute_reply.started":"2021-12-01T13:05:02.432923Z","shell.execute_reply":"2021-12-01T13:05:02.441512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Sequence frames sequential and start from 0?\")\nfor seq_name in TRAIN_DF[\"sequence\"].unique():\n    sequential = True\n    numbers = TRAIN_DF[TRAIN_DF[\"sequence\"] == seq_name][\"sequence_frame\"].values\n    numbers.sort()\n    \n    i = 0\n    for num in numbers:\n        while i < num:\n            print(f\"Seq {seq_name}: {Fore.RED}Missing {i}{Fore.RESET}\")\n            i += 1\n        i += 1\n\n    if sequential:\n        print(f\"Seq {seq_name}: {Fore.GREEN}Yes{Fore.RESET}\")\nprint()\n  ","metadata":{"execution":{"iopub.status.busy":"2021-12-01T13:05:06.232249Z","iopub.execute_input":"2021-12-01T13:05:06.232831Z","iopub.status.idle":"2021-12-01T13:05:06.277338Z","shell.execute_reply.started":"2021-12-01T13:05:06.232789Z","shell.execute_reply":"2021-12-01T13:05:06.276470Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Video frames sequential?\")\nfor seq_name in TRAIN_DF[\"sequence\"].unique():\n    sequential = True\n    numbers = TRAIN_DF[TRAIN_DF[\"sequence\"] == seq_name][\"video_frame\"].values\n    numbers.sort()\n    \n    i = numbers[0]\n    for num in numbers:\n        while i < num:\n            print(f\"Seq {seq_name}: {Fore.RED}Missing {i}{Fore.RESET}\")\n            i += 1\n        i += 1\n\n    if sequential:\n        print(f\"Seq {seq_name}: {Fore.GREEN}Yes{Fore.RESET}\")\nprint()\n# image id是否只连接frame id和video id \nnew_vid_ids = TRAIN_DF[\"video_id\"].astype(str) + \"-\" + TRAIN_DF[\"video_frame\"].astype(str)\nprint(\"How many images have strange image_ids:\", (TRAIN_DF[\"image_id\"] != new_vid_ids).sum())\n","metadata":{"execution":{"iopub.status.busy":"2021-12-01T13:05:11.758177Z","iopub.execute_input":"2021-12-01T13:05:11.758452Z","iopub.status.idle":"2021-12-01T13:05:11.886846Z","shell.execute_reply.started":"2021-12-01T13:05:11.758423Z","shell.execute_reply":"2021-12-01T13:05:11.886052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vid_seq_pairs = TRAIN_DF[[\"video_id\", \"sequence\"]].drop_duplicates()\nrepeated_sequence_count = (vid_seq_pairs[\"sequence\"].value_counts() != 1).sum()\nprint(\"How many repeated sequences:\", repeated_sequence_count)\n# 序列是唯一的","metadata":{"execution":{"iopub.status.busy":"2021-12-01T13:05:17.412521Z","iopub.execute_input":"2021-12-01T13:05:17.414554Z","iopub.status.idle":"2021-12-01T13:05:17.427663Z","shell.execute_reply.started":"2021-12-01T13:05:17.414497Z","shell.execute_reply":"2021-12-01T13:05:17.426561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Starfish per image:\", TRAIN_DF[\"detection_count\"].value_counts())\n\nbin_count = len(TRAIN_DF[\"detection_count\"].unique())\nplot = TRAIN_DF.hist(column=\"detection_count\", figsize=(16,6), bins=bin_count)\nax = plot[0][0]\nax.set_title(\"Starfish count, per image\")\n\nTRAIN_DF_WITH_STARFISH = TRAIN_DF[TRAIN_DF[\"detection_count\"] > 0]\nbin_count = len(TRAIN_DF_WITH_STARFISH[\"detection_count\"].unique())\nplot = TRAIN_DF_WITH_STARFISH.hist(column=\"detection_count\", figsize=(16,4), bins=bin_count)\nax = plot[0][0]\nax.set_title(\"Starfish count, per image (with 0 detections removed)\");","metadata":{"execution":{"iopub.status.busy":"2021-12-01T13:05:22.042336Z","iopub.execute_input":"2021-12-01T13:05:22.043159Z","iopub.status.idle":"2021-12-01T13:05:22.654147Z","shell.execute_reply.started":"2021-12-01T13:05:22.043097Z","shell.execute_reply":"2021-12-01T13:05:22.653378Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import math \n\n\nSEQUENCE_COUNT = len(TRAIN_DF[\"sequence\"].drop_duplicates())\nFIG_COLS = 3\nFIG_ROWS = math.ceil(SEQUENCE_COUNT / FIG_COLS)\nfig = plt.figure(figsize=(30, 30), constrained_layout=True)\n# fig.tight_layout(pad=10.0)\n# fig.tight_layout()\n\n\ndet_data = TRAIN_DF[[\"sequence\", \"video_id\", \"sequence_frame\", \"detection_count\"]].drop_duplicates()\nfor i, seq_num in enumerate(det_data[\"sequence\"].unique()):  # we know seq numbers are unique in train data\n    # Get data\n    seq_data = det_data[det_data[\"sequence\"] == seq_num].sort_values(by=\"sequence_frame\")\n    seq_data = seq_data.set_index(seq_data[\"sequence_frame\"]).drop(columns=\"sequence_frame\")\n    video_id = seq_data[\"video_id\"].iloc[0]\n    \n    # Select figure position\n    col = (i % FIG_COLS) + 1\n    row = (i // FIG_COLS) + 1\n     \n    # Plot\n    ax = plt.subplot(FIG_ROWS, FIG_COLS, i+1)\n    ax = seq_data[\"detection_count\"].plot.line(ax=ax)\n    ax.set_title(f\"Video {video_id}, Sequence {seq_num}\", fontsize=22)\n    ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True))\n    ax.set_xlabel('Detections', fontsize=16)\n    ax.set_ylabel('Sequence Frame', fontsize=16)\n    ","metadata":{"execution":{"iopub.status.busy":"2021-12-01T13:05:27.442150Z","iopub.execute_input":"2021-12-01T13:05:27.442414Z","iopub.status.idle":"2021-12-01T13:05:32.736776Z","shell.execute_reply.started":"2021-12-01T13:05:27.442387Z","shell.execute_reply":"2021-12-01T13:05:32.735372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#  Cache / Selected values\nvideo_ids = TRAIN_DF[\"video_id\"].unique()\nsel_video_id = 0\nsel_video_df = TRAIN_DF[TRAIN_DF[\"video_id\"] == sel_video_id]\n\nsequences = sel_video_df[\"sequence\"].unique()\nsel_sequence = sequences[0]\nsel_sequence_df = sel_video_df[sel_video_df[\"sequence\"] == sel_sequence]\n\nlast_frame = sel_sequence_df[\"sequence_frame\"].max()\nsel_sequence_frame = 0\nsel_sequence_frames = sel_sequence_df[sel_sequence_df[\"sequence_frame\"] == sel_sequence_frame]\nassert len(sel_sequence_frames) == 1\nsel_video_frame = sel_sequence_frames[\"video_frame\"].values[0]\nsel_annotation = eval(sel_sequence_frames[\"annotations\"].values[0])\n  # UI elements\ndd_video_id = widgets.Dropdown(options=video_ids, description='Video ID:')\ndd_sequence = widgets.Dropdown(options=sequences, description='Sequence:')\nbtn_first = widgets.Button(description=\"⏮️\")\nbtn_back_50 = widgets.Button(description=\"⏪\")\nbtn_back = widgets.Button(description=\"◀️\")\nbtn_forward = widgets.Button(description=\"▶️\")\nbtn_forward_50 = widgets.Button(description=\"⏩\")\nbtn_last = widgets.Button(description=\"⏯\")\n\nout = widgets.Output()\n\ndd_row = widgets.HBox([dd_video_id, dd_sequence])\nbtn_row = widgets.HBox([btn_first, btn_back_50, btn_back, btn_forward, btn_forward_50, btn_last])\nall_widgets = widgets.VBox([dd_row, btn_row, out])\n\n# Selection helpers (only change the data)\ndef set_frame(new_number):\n    global sel_sequence_frame\n    global sel_sequence_frames\n    global sel_video_frame\n    global sel_annotation\n    \n    sel_sequence_frame = max(0, min(new_number, last_frame))\n    sel_sequence_frames = sel_sequence_df[sel_sequence_df[\"sequence_frame\"] == sel_sequence_frame]\n    assert len(sel_sequence_frames) == 1\n    sel_video_frame = sel_sequence_frames[\"video_frame\"].values[0]\n    \n    sel_annotation = eval(sel_sequence_frames[\"annotations\"].values[0])\n\ndef set_sequence(new_number):\n    global sel_sequence\n    global sel_sequence_df\n    global last_frame\n\n    sel_sequence = new_number\n    sel_sequence_df = sel_video_df[sel_video_df[\"sequence\"] == sel_sequence]\n    last_frame = sel_sequence_df[\"sequence_frame\"].max()\n\n    set_frame(0)\n    \ndef set_video_id(new_id):\n    global sel_video_id\n    global sel_video_df\n    global sequences\n    \n    sel_video_id = new_id\n    sel_video_df = TRAIN_DF[TRAIN_DF[\"video_id\"] == sel_video_id]\n\n    sequences = sel_video_df[\"sequence\"].unique()\n    set_sequence(sequences[0])\n    \n# UI helpers (handle UI events + call selection helpers)\ndef clear_output():\n    out.clear_output()\n    \ndef draw_image():\n    img_path = ROOT_DIR / \"train_images\" / f\"video_{sel_video_id}\" / f\"{sel_video_frame}.jpg\"\n    assert img_path.is_file(), f\"Cannot find image {img_path}\"\n    cv_img = cv2.imread(str(img_path))\n    cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)\n    \n    draw_bboxes(cv_img, sel_annotation)\n\n    with out:\n        print(\"Image\", img_path)\n        \n         # TODO: possible speedup - find a way to update images without clearing output\n        img_fig = plt.figure(figsize=(20,16), facecolor=\"#123456ff\", frameon=False)\n        img_ax = img_fig.add_subplot(1, 1, 1)\n        img_ax.get_xaxis().set_visible(False)\n        img_ax.get_yaxis().set_visible(False)\n        img_ax.use_sticky_edges = False\n        # img_ax.margins(x=0)  # doesn't work. make img_fig.facecolor transparent instead as a hack.\n\n        img_ax.imshow(cv_img)\n        plt.show()\n        \ndef draw_bboxes(cv_img, annotations):\n    BBOX_COLOR_RGB = (255,126,0)\n    for ann in annotations:\n        cv2.rectangle(\n            cv_img,\n            (ann[\"x\"] ,ann[\"y\"]),\n            (ann[\"x\"] + ann[\"width\"], ann[\"y\"] + ann[\"height\"]),\n            color=BBOX_COLOR_RGB,\n            thickness=3\n        )\n        \ndef on_click_forward(b):\n    with out:\n        set_frame(sel_sequence_frame + 1)\n        clear_output()\n        draw_image()\nbtn_forward.on_click(on_click_forward)\ndef on_click_back(b):\n    with out:\n        set_frame(sel_sequence_frame - 1)\n        clear_output()\n        draw_image()\nbtn_back.on_click(on_click_back)\ndef on_click_forward_50(b):\n    with out:\n        set_frame(sel_sequence_frame + 50)\n        clear_output()\n        draw_image()\nbtn_forward_50.on_click(on_click_forward_50)\n\ndef on_click_back_50(b):\n    with out:\n        set_frame(sel_sequence_frame - 50)\n        clear_output()\n        draw_image()\nbtn_back_50.on_click(on_click_back_50)\ndef on_click_first(b):\n    with out:\n        set_frame(0)\n        clear_output()\n        draw_image()\nbtn_first.on_click(on_click_first)\ndef on_click_last(b):\n    with out:\n        set_frame(last_frame)\n        clear_output()\n        draw_image()\nbtn_last.on_click(on_click_last)\n\ndef on_sequence_change(change):\n    with out:\n        if change[\"old\"] == change[\"new\"]:\n            return\n        set_sequence(change[\"new\"])\n\n        clear_output()\n        draw_image()\ndd_sequence.observe(on_sequence_change, names=\"value\")\n\ndef on_video_id_change(change):\n    with out:\n        if change[\"old\"] == change[\"new\"]:\n            return\n        set_video_id(change[\"new\"])\n        dd_sequence.options = sequences\n        \n        clear_output()\n        draw_image()\ndd_video_id.observe(on_video_id_change, names=\"value\")\n\n\ndisplay(all_widgets)\ndraw_image()","metadata":{"execution":{"iopub.status.busy":"2021-12-01T13:05:34.093811Z","iopub.execute_input":"2021-12-01T13:05:34.094105Z","iopub.status.idle":"2021-12-01T13:05:34.975985Z","shell.execute_reply.started":"2021-12-01T13:05:34.094071Z","shell.execute_reply":"2021-12-01T13:05:34.975374Z"},"trusted":true},"execution_count":null,"outputs":[]}]}