{"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":"## Underwater stuff ","metadata":{}},{"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 # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport copy \nimport cv2\n\nfrom tqdm import tqdm\nfrom pathlib import Path, PosixPath\nfrom PIL import Image, ImageDraw\nfrom pydantic import BaseModel\nfrom typing import Optional \n\n\nimport matplotlib.pyplot as plt\nplt.style.use(\"bmh\")\n%matplotlib inline\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# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\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":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-01-17T13:50:19.981044Z","iopub.execute_input":"2022-01-17T13:50:19.981551Z","iopub.status.idle":"2022-01-17T13:50:20.404575Z","shell.execute_reply.started":"2022-01-17T13:50:19.981421Z","shell.execute_reply":"2022-01-17T13:50:20.403230Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This tutorial is used to understand the data. \n## List of topics. \n- [x] visualize the images.  \n- [x] visualize the image with annot boxes.  \n- [x] understand video_id and create a video and visualize them.  \n- [x] video's with bboxes (vis and data)  \n- [ ] bbox stats  ","metadata":{}},{"cell_type":"code","source":"root = Path(\"/kaggle/input/tensorflow-great-barrier-reef/\")\nroot","metadata":{"execution":{"iopub.status.busy":"2022-01-17T13:50:20.406329Z","iopub.execute_input":"2022-01-17T13:50:20.406674Z","iopub.status.idle":"2022-01-17T13:50:20.416851Z","shell.execute_reply.started":"2022-01-17T13:50:20.406622Z","shell.execute_reply":"2022-01-17T13:50:20.415031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"list(root.iterdir())","metadata":{"execution":{"iopub.status.busy":"2022-01-17T13:50:20.418466Z","iopub.execute_input":"2022-01-17T13:50:20.419114Z","iopub.status.idle":"2022-01-17T13:50:20.429375Z","shell.execute_reply.started":"2022-01-17T13:50:20.419028Z","shell.execute_reply":"2022-01-17T13:50:20.428081Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(root/\"train.csv\")\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2022-01-17T13:50:20.430865Z","iopub.execute_input":"2022-01-17T13:50:20.431128Z","iopub.status.idle":"2022-01-17T13:50:20.638291Z","shell.execute_reply.started":"2022-01-17T13:50:20.431097Z","shell.execute_reply":"2022-01-17T13:50:20.636884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"total_images = {i.name:len(list(i.glob(\"*.jpg\"))) for i in list((root / \"train_images\").glob(\"*\"))}\nprint(total_images)\ndf[\"video_id\"].value_counts()","metadata":{"execution":{"iopub.status.busy":"2022-01-17T13:50:20.641039Z","iopub.execute_input":"2022-01-17T13:50:20.641426Z","iopub.status.idle":"2022-01-17T13:50:21.256705Z","shell.execute_reply.started":"2022-01-17T13:50:20.641383Z","shell.execute_reply":"2022-01-17T13:50:21.255493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Annot(BaseModel):\n    bbox: np.ndarray\n    dtype: str\n    \n    class Config:\n        arbitrary_types_allowed = True        \n        \n\nclass ImageStore(BaseModel):\n    img_loc: PosixPath\n    video_id: str\n    frame_id: str \n    annot: Annot\n    img: np.ndarray\n    vis_img: Optional[np.ndarray]\n    \n    class Config:\n        arbitrary_types_allowed = True","metadata":{"execution":{"iopub.status.busy":"2022-01-17T13:50:21.258518Z","iopub.execute_input":"2022-01-17T13:50:21.259229Z","iopub.status.idle":"2022-01-17T13:50:21.269634Z","shell.execute_reply.started":"2022-01-17T13:50:21.259182Z","shell.execute_reply":"2022-01-17T13:50:21.268850Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class GBR:\n    def __init__(self, root, df_loc, only_annots=True):\n        self.df = pd.read_csv(df_loc) if isinstance(df_loc, (str, PosixPath)) else df_loc\n        self.root = root \n        self.df = self.df[self.df[\"annotations\"] != \"[]\"].reset_index(drop=True) if only_annots else self.df \n    \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        meta = self.df.iloc[idx]\n        video_id = f\"video_{meta['video_id']}\"\n        loc = self.root / \"train_images\" / video_id / (str(meta[\"video_frame\"])+\".jpg\")\n        if loc.exists():\n            img = np.asarray(Image.open(loc))\n            annot = Annot(bbox=np.asarray([[i[\"x\"], i[\"y\"], i[\"width\"], i[\"height\"]] for i in eval(meta[\"annotations\"]) if i != \"[]\"]), dtype=\"xywh\")\n            data = ImageStore(img= img, annot=annot, img_loc=loc, video_id=loc.parent.name, frame_id=loc.name)\n            return data\n        else:\n            print(\"Image not present\")\n    \n    @staticmethod\n    def draw_bboxes(img, bboxes, line_width=5, color=(255, 0, 0)):\n        img = Image.fromarray(copy.deepcopy(img))\n        draw = ImageDraw.Draw(img)\n        lw = line_width or max(round(sum(img.shape) / 2 * 0.003), 2)\n        for annot in bboxes:\n            x, y, w, h = annot\n            draw.rectangle([x, y, x+w, y+h], width=lw, outline=\"red\")\n        return img\n    \n    def vis_random(self):\n        idx = np.random.randint(len(self))\n        data = self[idx]\n        if data is not None:\n            vis_img = self.draw_bboxes(data.img, data.annot.bbox) if len(data.annot.bbox) > 0 else data.img \n            print(f\"visualizing: video_id: {data.video_id}, frame: {data.frame_id}\")\n            fig, ax = plt.subplots(figsize=(12, 7.5), nrows=1, ncols=1)\n            ax.imshow(vis_img)\n            ax.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2022-01-17T13:50:21.271008Z","iopub.execute_input":"2022-01-17T13:50:21.271317Z","iopub.status.idle":"2022-01-17T13:50:21.289772Z","shell.execute_reply.started":"2022-01-17T13:50:21.271251Z","shell.execute_reply":"2022-01-17T13:50:21.288844Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gbr = GBR(root, df, only_annots=True)","metadata":{"execution":{"iopub.status.busy":"2022-01-17T13:50:21.291004Z","iopub.execute_input":"2022-01-17T13:50:21.291373Z","iopub.status.idle":"2022-01-17T13:50:21.318107Z","shell.execute_reply.started":"2022-01-17T13:50:21.291343Z","shell.execute_reply":"2022-01-17T13:50:21.316772Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## visualizing a random frame. Can u recognize a object (starfish) just looking at the frame. \ngbr.vis_random()","metadata":{"execution":{"iopub.status.busy":"2022-01-17T13:50:21.319589Z","iopub.execute_input":"2022-01-17T13:50:21.320001Z","iopub.status.idle":"2022-01-17T13:50:21.949888Z","shell.execute_reply.started":"2022-01-17T13:50:21.319967Z","shell.execute_reply":"2022-01-17T13:50:21.948742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## How many videos are present in the dataset ?\n- `sequence` column gives individual video snippets unique_ids. \n- `sequence_frame` gives the frame number within the video. \n- The below plot also tells where star fishes are located within the video along with their count. ","metadata":{"execution":{"iopub.status.busy":"2022-01-14T07:31:19.595475Z","iopub.execute_input":"2022-01-14T07:31:19.596144Z","iopub.status.idle":"2022-01-14T07:31:19.661969Z","shell.execute_reply.started":"2022-01-14T07:31:19.596091Z","shell.execute_reply":"2022-01-14T07:31:19.660965Z"}}},{"cell_type":"code","source":"df[\"contains_star_fish\"] = df[\"annotations\"].apply(lambda x: len(eval(x)))\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2022-01-17T13:50:21.951083Z","iopub.execute_input":"2022-01-17T13:50:21.951486Z","iopub.status.idle":"2022-01-17T13:50:22.229068Z","shell.execute_reply.started":"2022-01-17T13:50:21.951448Z","shell.execute_reply":"2022-01-17T13:50:22.228328Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fps = 30\ntime_per_sequence = (df.groupby([\"video_id\", \"sequence\"])[\"video_frame\"].count()/fps).reset_index()\ntime_per_sequence.columns = [\"video_id\", \"sequence\", \"time (sec)\"]\ntime_per_sequence.head()","metadata":{"execution":{"iopub.status.busy":"2022-01-17T13:52:55.900123Z","iopub.execute_input":"2022-01-17T13:52:55.900931Z","iopub.status.idle":"2022-01-17T13:52:55.917682Z","shell.execute_reply.started":"2022-01-17T13:52:55.900888Z","shell.execute_reply":"2022-01-17T13:52:55.916993Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"time_per_sequence[\"time (sec)\"].hist(figsize=(8, 3.5), bins=20)\nplt.title(\"time (sec)\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-17T13:55:20.195607Z","iopub.execute_input":"2022-01-17T13:55:20.195931Z","iopub.status.idle":"2022-01-17T13:55:20.452189Z","shell.execute_reply.started":"2022-01-17T13:55:20.195899Z","shell.execute_reply":"2022-01-17T13:55:20.451218Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- Visualizing the appearance of star fish within a video_sequence. \n- Colors represent the count of star fish within the video. On x-axis we have where the star fish is see within the `sequence`.\n- y_axis we have the video_frame number. From this we can make that a single video is stripped into several small video chunks. ","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(figsize=(8*3, 3.5), nrows=1, ncols=3)\nfor i in range(df[\"video_id\"].unique().shape[0]):\n    df_ = df[df[\"video_id\"] == i]\n    ax.flat[i].grid(False)\n    pcm = ax.flat[i].scatter(df_[\"sequence_frame\"].values, df_[\"video_frame\"].values, c=df_[\"contains_star_fish\"].values, cmap='RdBu_r')\n    ax.flat[i].set_title(f\"video_id: {i}\")\n    #ax.flat[i].legend(loc=\"upper right\")\nfig.colorbar(pcm, shrink=1)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-01-17T12:48:32.539081Z","iopub.execute_input":"2022-01-17T12:48:32.53939Z","iopub.status.idle":"2022-01-17T12:48:33.479659Z","shell.execute_reply.started":"2022-01-17T12:48:32.539356Z","shell.execute_reply":"2022-01-17T12:48:33.47878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Convert frame to videos ","metadata":{}},{"cell_type":"code","source":"def frames2video_gbr(df, save_folder, vis_bbox=False, fps:int=30):\n    ## convert a sequence to video using video_id and sequence as folder name. \n    video_id = df[\"video_id\"].unique()[0]\n    out = None \n    d_ = GBR(root, df_, only_annots=False)\n    for i in tqdm(range(len(d_))):\n        data = d_[i]\n        if data is None:\n            continue\n        height, width, layers = data.img.shape\n        size = (width, height)\n        if out is None:\n            out = cv2.VideoWriter((save_folder/f\"video_{video_id}-{sequence}.mp4\").as_posix(), cv2.VideoWriter_fourcc(*'MP4V'), fps, size)\n        \n        if vis_bbox:\n            img = GBR.draw_bboxes(data.img, data.annot.bbox) if len(data.annot.bbox) > 0 else data.img \n            img = img if isinstance(img, np.ndarray) else np.asarray(img)\n        else:\n            img = data.img\n        \n        out.write(img[:, :, ::-1])\n    out.release()","metadata":{"execution":{"iopub.status.busy":"2022-01-17T07:43:56.655273Z","iopub.execute_input":"2022-01-17T07:43:56.656447Z","iopub.status.idle":"2022-01-17T07:43:56.667783Z","shell.execute_reply.started":"2022-01-17T07:43:56.656376Z","shell.execute_reply":"2022-01-17T07:43:56.666226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Save a video\n- one raw video \n- same video with bboxes on the image.","metadata":{}},{"cell_type":"code","source":"save_path=Path(\"/kaggle/working/\") / \"raw\"\nsave_path_bbox=Path(\"/kaggle/working/\") / \"bbox\"\nsave_path.mkdir(exist_ok=True)\nsave_path_bbox.mkdir(exist_ok=True)\nfps = 24\n## select a video \nsequence = df[\"sequence\"].unique()[3]\ndf_ = df[df[\"sequence\"] == sequence].reset_index(drop=True)\nprint(df_.shape)\nframes2video_gbr(df_, save_path, vis_bbox=False, fps=fps)\nframes2video_gbr(df_, save_path_bbox, vis_bbox=True, fps=fps)","metadata":{"execution":{"iopub.status.busy":"2022-01-17T07:37:55.189541Z","iopub.execute_input":"2022-01-17T07:37:55.190527Z","iopub.status.idle":"2022-01-17T07:38:14.992019Z","shell.execute_reply.started":"2022-01-17T07:37:55.190482Z","shell.execute_reply":"2022-01-17T07:38:14.991147Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from IPython.display import Video\n# Video(list(Path(\"/kaggle/working/raw\").glob(\"*\"))[0].as_posix())","metadata":{"execution":{"iopub.status.busy":"2022-01-17T07:38:57.911853Z","iopub.execute_input":"2022-01-17T07:38:57.912461Z","iopub.status.idle":"2022-01-17T07:38:57.91989Z","shell.execute_reply.started":"2022-01-17T07:38:57.91241Z","shell.execute_reply":"2022-01-17T07:38:57.919064Z"},"trusted":true},"execution_count":null,"outputs":[]}]}