{"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":"%%capture\n# 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\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\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\nimport os\nfor 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":"2021-12-06T09:57:35.097434Z","iopub.execute_input":"2021-12-06T09:57:35.097839Z","iopub.status.idle":"2021-12-06T09:57:38.226745Z","shell.execute_reply.started":"2021-12-06T09:57:35.097759Z","shell.execute_reply":"2021-12-06T09:57:38.225730Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# EDA - Exploratory data analysis\n\nUpvote if you found useful","metadata":{}},{"cell_type":"markdown","source":"<p align = \"center\">\n<img src = \"https://econews.com.au/wp-content/uploads/2016/10/Crown-of-thorns-starfish-attached-healthy-coral-reef-Mackay-.jpg\">\n</p>\n<p align = \"center\">\nCrown-of-thorns starfish (Image from econews.com.au)\n</p>","metadata":{}},{"cell_type":"markdown","source":"## Content\n\n1. **Video frames numbers**\n2. **Train dataframe analysis: video analysis and annotations numbers (per video and sequence)**\n3. **Visualizing some training examples**\n","metadata":{}},{"cell_type":"code","source":"import os\nimport ast\nimport PIL\nimport cv2\nimport pandas as pd\nfrom os import listdir\nfrom os.path import isfile,join\nimport seaborn as sns\nimport plotly.express as px\nimport plotly.graph_objects as go","metadata":{"execution":{"iopub.status.busy":"2021-12-06T09:57:38.228500Z","iopub.execute_input":"2021-12-06T09:57:38.228884Z","iopub.status.idle":"2021-12-06T09:57:39.174612Z","shell.execute_reply.started":"2021-12-06T09:57:38.228841Z","shell.execute_reply":"2021-12-06T09:57:39.173935Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataset overview\n## 1. Video frames stats","metadata":{}},{"cell_type":"code","source":"DATA_PATH = '/kaggle/input/tensorflow-great-barrier-reef'\nimages_path = join(DATA_PATH,'train_images')\ndf_train = pd.read_csv(join(DATA_PATH,'train.csv'))","metadata":{"execution":{"iopub.status.busy":"2021-12-06T09:57:39.175746Z","iopub.execute_input":"2021-12-06T09:57:39.176073Z","iopub.status.idle":"2021-12-06T09:57:39.207286Z","shell.execute_reply.started":"2021-12-06T09:57:39.176043Z","shell.execute_reply":"2021-12-06T09:57:39.206444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = pd.read_csv(join(DATA_PATH,'train.csv'))\ndf_train[\"img_path\"] = os.path.join(DATA_PATH, \"train_images\")+\"/video_\"+df_train.video_id.astype(str)+\"/\"+df_train.video_frame.astype(str)+\".jpg\"","metadata":{"execution":{"iopub.status.busy":"2021-12-06T09:57:39.209218Z","iopub.execute_input":"2021-12-06T09:57:39.209433Z","iopub.status.idle":"2021-12-06T09:57:39.286741Z","shell.execute_reply.started":"2021-12-06T09:57:39.209407Z","shell.execute_reply":"2021-12-06T09:57:39.285911Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from PIL import Image\n\ndef video_stats(path):\n    # Lookfor files within video folder\n    onlyfiles = [f for f in listdir(path) if isfile(join(path, f))]\n    # Filter files by extension\n    onlyfiles = [f for f in onlyfiles if f.endswith(\".jpg\")]\n    im = Image.open(join(path,onlyfiles[0]))\n    width, height = im.size\n    print(f'Number of frames: {len(onlyfiles)}')\n    print(f'Frames with size (w,h): ({width},{height})')","metadata":{"execution":{"iopub.status.busy":"2021-12-06T09:57:39.287835Z","iopub.execute_input":"2021-12-06T09:57:39.288036Z","iopub.status.idle":"2021-12-06T09:57:39.294069Z","shell.execute_reply.started":"2021-12-06T09:57:39.288012Z","shell.execute_reply":"2021-12-06T09:57:39.293248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Video 0\nprint('Video 0 Stats:')\nvideo_stats(join(images_path,'video_0'))\n\n# Video 1\nprint(\"\\n\",'Video 1 Stats:')\nvideo_stats(join(images_path,'video_1'))\n\n# Video 2\nprint(\"\\n\",'Video 2 Stats:')\nvideo_stats(join(images_path,'video_2'))","metadata":{"execution":{"iopub.status.busy":"2021-12-06T09:57:39.295297Z","iopub.execute_input":"2021-12-06T09:57:39.295632Z","iopub.status.idle":"2021-12-06T09:57:40.461433Z","shell.execute_reply.started":"2021-12-06T09:57:39.295596Z","shell.execute_reply":"2021-12-06T09:57:40.459602Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2 Train dataframe analysis","metadata":{}},{"cell_type":"markdown","source":"- `video_id` - ID number of the video the image was part of. The video ids are not meaningfully ordered.\n- `video_frame` - The frame number of the image within the video. Expect to see occasional gaps in the frame number from when the diver surfaced.\n- `sequence` - ID of a gap-free subset of a given video. The sequence ids are not meaningfully ordered.\n- `sequence_frame` - The frame number within a given sequence.\n- `image_id` - ID code for the image, in the format '{video_id}-{video_frame}'\n- `annotations` - The bounding boxes of any starfish detections in a string format that can be evaluated directly with Python. Does not use the same format as the predictions you will submit. Not available in **test.csv.** A bounding box is described by the pixel coordinate (x_min, y_min) of its upper left corner within the image together with its width and height in pixels.","metadata":{}},{"cell_type":"markdown","source":"### 2.1 Video details","metadata":{}},{"cell_type":"markdown","source":"Display the number of frames per video","metadata":{}},{"cell_type":"code","source":"df_train_video_group = df_train.groupby(\"video_id\")[\"video_frame\"].max()\nfig = px.bar(df_train_video_group, \n             color=px.colors.qualitative.Plotly[:3],\n             labels={\"sequence\":\"Video id\", \"value\":\"N° of frames\", \"variable\":\"Original Column Name\"},\n             title=\"Number of frames per video ID\")\n\nfig.update_layout(xaxis=dict(type='category'), showlegend=False)\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-06T09:57:40.462669Z","iopub.execute_input":"2021-12-06T09:57:40.462880Z","iopub.status.idle":"2021-12-06T09:57:40.763790Z","shell.execute_reply.started":"2021-12-06T09:57:40.462854Z","shell.execute_reply":"2021-12-06T09:57:40.762720Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"However, each video has several sequences. Let's see in a more detailed way.","metadata":{}},{"cell_type":"code","source":"df_train_sequence_group = df_train.groupby(\"sequence\")[[\"sequence_frame\", \"video_id\"]].max().sort_values(by=\"video_id\")\ndf_train_sequence_group[\"video_id\"] = df_train_sequence_group[\"video_id\"].astype(str) # For label color mode\n\nfig = px.bar(df_train_sequence_group, \n             color=\"video_id\",\n             labels={\"sequence\":\"Sequence id\", \"value\":\"Number Of Frames\", \"variable\":\"Original Column Name\"},\n             title=\"Number Of Frames In Each Sequence\")\n\nfig.update_layout(xaxis=dict(type='category'), showlegend=True)\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-06T09:57:40.765193Z","iopub.execute_input":"2021-12-06T09:57:40.765420Z","iopub.status.idle":"2021-12-06T09:57:40.842762Z","shell.execute_reply.started":"2021-12-06T09:57:40.765392Z","shell.execute_reply":"2021-12-06T09:57:40.841828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 2.2 Annotation analysis","metadata":{}},{"cell_type":"code","source":"# Train stats\nsamples_without_annotations=len(df_train[df_train['annotations']=='[]'])\n#ax = sns.barplot(x=['Without bbox','With bbox'], y=[samples_without_annotations,(len(df_train) - samples_without_annotations)])\ncolors = ['lightslategray',] * 2 \ncolors[1] = 'crimson'\nlabels = ['Without bbox','With bbox']\n\nfig = go.Figure([go.Bar(x=labels, \n                        y=[samples_without_annotations, len(df_train) - samples_without_annotations],\n                        marker_color=px.colors.qualitative.Plotly[:2])])\nfig.show()\nprint(f'Number of training samples: {len(df_train)}')\nprint(f'Training samples without object labels: {samples_without_annotations}')\nprint(f'Training samples with object labels: {len(df_train) - samples_without_annotations}')","metadata":{"execution":{"iopub.status.busy":"2021-12-06T09:57:40.844050Z","iopub.execute_input":"2021-12-06T09:57:40.844383Z","iopub.status.idle":"2021-12-06T09:57:40.862252Z","shell.execute_reply.started":"2021-12-06T09:57:40.844353Z","shell.execute_reply":"2021-12-06T09:57:40.861628Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train[\"annotations\"] = df_train[\"annotations\"].apply(lambda x: ast.literal_eval(x))\ndf_train[\"num_boxes\"] = df_train[\"annotations\"].apply(len)\ndf_train[\"video_id\"] = df_train[\"video_id\"].astype(str)\ndf_train[\"sequence\"] = df_train[\"sequence\"].astype(str)","metadata":{"execution":{"iopub.status.busy":"2021-12-06T09:57:40.863084Z","iopub.execute_input":"2021-12-06T09:57:40.863335Z","iopub.status.idle":"2021-12-06T09:57:41.332539Z","shell.execute_reply.started":"2021-12-06T09:57:40.863307Z","shell.execute_reply":"2021-12-06T09:57:41.331703Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_annotations_count = df_train.groupby('num_boxes')['annotations'].count()","metadata":{"execution":{"iopub.status.busy":"2021-12-06T09:57:41.333901Z","iopub.execute_input":"2021-12-06T09:57:41.334126Z","iopub.status.idle":"2021-12-06T09:57:41.340742Z","shell.execute_reply.started":"2021-12-06T09:57:41.334096Z","shell.execute_reply":"2021-12-06T09:57:41.339885Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_annotations_count = df_annotations_count.drop([0]);","metadata":{"execution":{"iopub.status.busy":"2021-12-06T09:57:41.342033Z","iopub.execute_input":"2021-12-06T09:57:41.342260Z","iopub.status.idle":"2021-12-06T09:57:41.352909Z","shell.execute_reply.started":"2021-12-06T09:57:41.342225Z","shell.execute_reply":"2021-12-06T09:57:41.352140Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Information about the number of samples with bounding boxes\nfig = px.bar(df_annotations_count)\nfig.update_layout(xaxis=dict(type='category'), showlegend=False)\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-06T09:57:41.355777Z","iopub.execute_input":"2021-12-06T09:57:41.356054Z","iopub.status.idle":"2021-12-06T09:57:41.416854Z","shell.execute_reply.started":"2021-12-06T09:57:41.356011Z","shell.execute_reply":"2021-12-06T09:57:41.415978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# View nunber of bounding boxes per frame in each sequence\nfig = px.histogram(df_train, x=\"sequence\", color=\"num_boxes\",\n             labels={\"sequence\":\"Sequence ID\", \"num_boxes\":\"N° of Boxes per frame\"},\n             title=\"Number of annotations in each sequence\")\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-06T09:57:41.418126Z","iopub.execute_input":"2021-12-06T09:57:41.418463Z","iopub.status.idle":"2021-12-06T09:57:41.672396Z","shell.execute_reply.started":"2021-12-06T09:57:41.418428Z","shell.execute_reply":"2021-12-06T09:57:41.671525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 3 Visualizing some training examples","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nimport matplotlib.pyplot as plt\n\ndef tf_load_img(img_path, reshape_to=None):\n    if reshape_to is None:\n        return tf.image.decode_image(tf.io.read_file(img_path), channels=3)\n    else:\n        return tf.image.resize(tf.image.decode_image(tf.io.read_file(img_path), channels=3), reshape_to)\n    \ndef get_tl_br(bbox):\n    \"\"\" Return the top-left and bottom-right bounding box \"\"\"\n    return (bbox['x'], bbox['y']), (bbox['x']+bbox[\"width\"], bbox['y']+bbox[\"height\"])\n    \ndef plot_image(img_path, annotations=None, **kwargs):\n    \"\"\" Plot an image and bounding boxes \"\"\"\n    img = np.array(tf_load_img(img_path))\n    \n    if annotations:\n        plt.figure(figsize=(20,10))\n        for i, bbox in enumerate(annotations):\n            tl_box, br_box = get_tl_br(bbox)\n            img = cv2.rectangle(img, tl_box, br_box, (255-2*i,14*i,0), 4)\n        plt.imshow(img)\n        plt.axis(False)\n        plt.title(f\"Bounding boxes plotted: ({len(annotations)})\")\n    else:\n        plt.figure(figsize=(20,10))\n        plt.imshow(img)\n        plt.axis(False)\n        plt.title(\"No bounding boxes within the image\")\n    plt.tight_layout()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-12-06T10:06:07.138325Z","iopub.execute_input":"2021-12-06T10:06:07.138646Z","iopub.status.idle":"2021-12-06T10:06:07.149745Z","shell.execute_reply.started":"2021-12-06T10:06:07.138613Z","shell.execute_reply":"2021-12-06T10:06:07.148394Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_bbox_for_visualization = [1,3,7,15]\nfor num_bbox in sorted(num_bbox_for_visualization):\n    ex_row = df_train[df_train.num_boxes==num_bbox].reset_index(drop=True).iloc[0]\n    plot_image(**ex_row)","metadata":{"execution":{"iopub.status.busy":"2021-12-06T10:07:42.841710Z","iopub.execute_input":"2021-12-06T10:07:42.842012Z","iopub.status.idle":"2021-12-06T10:07:46.610496Z","shell.execute_reply.started":"2021-12-06T10:07:42.841983Z","shell.execute_reply":"2021-12-06T10:07:46.609622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}