{"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":"import tensorflow as tf","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-01-03T14:24:53.708437Z","iopub.execute_input":"2022-01-03T14:24:53.709042Z","iopub.status.idle":"2022-01-03T14:24:57.959723Z","shell.execute_reply.started":"2022-01-03T14:24:53.708919Z","shell.execute_reply":"2022-01-03T14:24:57.958855Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Install Object Detection API","metadata":{}},{"cell_type":"code","source":"!git clone https://github.com/tensorflow/models\n    \n# Check out a certain commit to ensure that future changes in the TF ODT API codebase won't affect this notebook.\n!cd models && git checkout ac8d06519","metadata":{"execution":{"iopub.status.busy":"2022-01-03T14:25:02.775450Z","iopub.execute_input":"2022-01-03T14:25:02.776074Z","iopub.status.idle":"2022-01-03T14:25:21.939955Z","shell.execute_reply.started":"2022-01-03T14:25:02.776024Z","shell.execute_reply":"2022-01-03T14:25:21.939113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%bash\ncd models/research\n\n# Compile protos.\nprotoc object_detection/protos/*.proto --python_out=.\n\n# Install TensorFlow Object Detection API.\n# Note: I fixed the version of some dependencies to make it work on Kaggle notebook. In particular:\n# * scipy==1.6.3 to avoid the missing GLIBCXX_3.4.26 error\n# * tensorflow to 2.6.0 to make it compatible with the CUDA version preinstalled on Kaggle.\n# When Kaggle notebook upgrade to TF 2.7, you can use the default setup.py script:\n# cp object_detection/packages/tf2/setup.py .\nwget https://storage.googleapis.com/odml-dataset/others/setup.py\npip install -q --user .\n\n# Test if the Object Dectection API is working correctly\npython object_detection/builders/model_builder_tf2_test.py","metadata":{"execution":{"iopub.status.busy":"2022-01-03T14:25:25.952130Z","iopub.execute_input":"2022-01-03T14:25:25.952397Z","iopub.status.idle":"2022-01-03T14:27:21.537123Z","shell.execute_reply.started":"2022-01-03T14:25:25.952370Z","shell.execute_reply":"2022-01-03T14:27:21.536417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Import Dependencies","metadata":{}},{"cell_type":"code","source":"import contextlib2\nimport io\nimport IPython\nimport json\nimport numpy as np\nimport os\nimport pathlib\nimport pandas as pd\nimport sys\nimport time\nfrom tqdm.notebook import tqdm\ntqdm.pandas()\nfrom sklearn.model_selection import GroupKFold\n\nfrom PIL import Image, ImageDraw\n\n# Import the library that is used to submit the prediction result.\nINPUT_DIR = '/kaggle/input/tensorflow-great-barrier-reef/'\nsys.path.insert(0, INPUT_DIR)\nimport greatbarrierreef","metadata":{"execution":{"iopub.status.busy":"2022-01-03T14:27:51.458356Z","iopub.execute_input":"2022-01-03T14:27:51.459327Z","iopub.status.idle":"2022-01-03T14:27:52.487382Z","shell.execute_reply.started":"2022-01-03T14:27:51.459262Z","shell.execute_reply":"2022-01-03T14:27:52.486604Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prepare Dataset","metadata":{}},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/tensorflow-great-barrier-reef/train.csv\")\ndf.head(500)","metadata":{"execution":{"iopub.status.busy":"2022-01-03T14:28:02.757608Z","iopub.execute_input":"2022-01-03T14:28:02.758349Z","iopub.status.idle":"2022-01-03T14:28:02.849031Z","shell.execute_reply.started":"2022-01-03T14:28:02.758303Z","shell.execute_reply":"2022-01-03T14:28:02.848388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Take only annotated photos(starfish)\nanno_df = df[df.annotations != '[]'].reset_index()\nprint('Number of Starfish images used for training:', len(anno_df))","metadata":{"execution":{"iopub.status.busy":"2022-01-03T14:28:08.699794Z","iopub.execute_input":"2022-01-03T14:28:08.700766Z","iopub.status.idle":"2022-01-03T14:28:08.718376Z","shell.execute_reply.started":"2022-01-03T14:28:08.700717Z","shell.execute_reply":"2022-01-03T14:28:08.717738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"anno_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-01-03T14:28:11.942368Z","iopub.execute_input":"2022-01-03T14:28:11.943034Z","iopub.status.idle":"2022-01-03T14:28:11.955447Z","shell.execute_reply.started":"2022-01-03T14:28:11.942995Z","shell.execute_reply":"2022-01-03T14:28:11.954720Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"kf = GroupKFold(n_splits = 5) \nanno_df= anno_df.reset_index(drop=True)\nanno_df['fold'] = -1\nfor fold, (train_idx, val_idx) in enumerate(kf.split(anno_df, y = anno_df.video_id.tolist(), groups=anno_df.sequence)):\n    anno_df.loc[val_idx, 'fold'] = fold\n\nanno_df.head(500)","metadata":{"execution":{"iopub.status.busy":"2022-01-03T14:28:15.654297Z","iopub.execute_input":"2022-01-03T14:28:15.655105Z","iopub.status.idle":"2022-01-03T14:28:15.676461Z","shell.execute_reply.started":"2022-01-03T14:28:15.655068Z","shell.execute_reply":"2022-01-03T14:28:15.675884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SELECTED_FOLD=4\n#train dataframe\ntrain_df= anno_df[anno_df[\"fold\"]!=SELECTED_FOLD].reset_index()\ntrain_df.head(500)","metadata":{"execution":{"iopub.status.busy":"2022-01-03T14:28:34.134839Z","iopub.execute_input":"2022-01-03T14:28:34.135152Z","iopub.status.idle":"2022-01-03T14:28:34.157283Z","shell.execute_reply.started":"2022-01-03T14:28:34.135119Z","shell.execute_reply":"2022-01-03T14:28:34.156543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#validation dataframe\nval_df= anno_df[anno_df[\"fold\"]==SELECTED_FOLD].reset_index()\nval_df.head(500)","metadata":{"execution":{"iopub.status.busy":"2022-01-03T14:28:38.463713Z","iopub.execute_input":"2022-01-03T14:28:38.463994Z","iopub.status.idle":"2022-01-03T14:28:38.485410Z","shell.execute_reply.started":"2022-01-03T14:28:38.463954Z","shell.execute_reply":"2022-01-03T14:28:38.484575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from object_detection.utils import dataset_util\nfrom object_detection.dataset_tools import tf_record_creation_util\n\n\ndef create_tf_example(video_id, video_frame, data_df, image_path):\n    \"\"\"Create a tf.Example entry for a given training image.\"\"\"\n    full_path = os.path.join(image_path, os.path.join(f'video_{video_id}', f'{video_frame}.jpg'))\n    with tf.io.gfile.GFile(full_path, 'rb') as fid:\n        encoded_jpg = fid.read()\n    encoded_jpg_io = io.BytesIO(encoded_jpg)\n    image = Image.open(encoded_jpg_io)\n    if image.format != 'JPEG':\n        raise ValueError('Image format not JPEG')\n\n    height = image.size[1] # Image height\n    width = image.size[0] # Image width\n    filename = f'{video_id}:{video_frame}'.encode('utf8') # Unique id of the image.\n    encoded_image_data = None # Encoded image bytes\n    image_format = 'jpeg'.encode('utf8') # b'jpeg' or b'png'\n\n    xmins = [] # List of normalized left x coordinates in bounding box (1 per box)\n    xmaxs = [] # List of normalized right x coordinates in bounding box\n             # (1 per box)\n    ymins = [] # List of normalized top y coordinates in bounding box (1 per box)\n    ymaxs = [] # List of normalized bottom y coordinates in bounding box\n             # (1 per box)\n    classes_text = [] # List of string class name of bounding box (1 per box)\n    classes = [] # List of integer class id of bounding box (1 per box)\n\n    rows = data_df[(data_df.video_id == video_id) & (data_df.video_frame == video_frame)]\n    for _, row in rows.iterrows():\n        annotations = json.loads(row.annotations.replace(\"'\", '\"'))\n        for annotation in annotations:\n            xmins.append(annotation['x'] / width) \n            xmaxs.append((annotation['x'] + annotation['width']) / width) \n            ymins.append(annotation['y'] / height) \n            ymaxs.append((annotation['y'] + annotation['height']) / height) \n\n            classes_text.append('COTS'.encode('utf8'))\n            classes.append(1)\n\n    tf_example = tf.train.Example(features=tf.train.Features(feature={\n      'image/height': dataset_util.int64_feature(height),\n      'image/width': dataset_util.int64_feature(width),\n      'image/filename': dataset_util.bytes_feature(filename),\n      'image/source_id': dataset_util.bytes_feature(filename),\n      'image/encoded': dataset_util.bytes_feature(encoded_jpg),\n      'image/format': dataset_util.bytes_feature(image_format),\n      'image/object/bbox/xmin': dataset_util.float_list_feature(xmins),\n      'image/object/bbox/xmax': dataset_util.float_list_feature(xmaxs),\n      'image/object/bbox/ymin': dataset_util.float_list_feature(ymins),\n      'image/object/bbox/ymax': dataset_util.float_list_feature(ymaxs),\n      'image/object/class/text': dataset_util.bytes_list_feature(classes_text),\n      'image/object/class/label': dataset_util.int64_list_feature(classes),\n    }))\n    \n    return tf_example\n\ndef convert_to_tfrecord(data_df, tfrecord_filebase, image_path, num_shards = 10):\n    \"\"\"Convert the object detection dataset to TFRecord as required by the TF ODT API.\"\"\"\n    with contextlib2.ExitStack() as tf_record_close_stack:\n        output_tfrecords = tf_record_creation_util.open_sharded_output_tfrecords(\n            tf_record_close_stack, tfrecord_filebase, num_shards)\n        \n        for index, row in data_df.iterrows():\n            if index % 500 == 0:\n                print('Processed {0} images.'.format(index))\n            tf_example = create_tf_example(row.video_id, row.video_frame, data_df, image_path)\n            output_shard_index = index % num_shards\n            output_tfrecords[output_shard_index].write(tf_example.SerializeToString())\n        \n        print('Completed processing {0} images.'.format(len(data_df)))\n\n!mkdir dataset\nimage_path = os.path.join(INPUT_DIR, 'train_images')\n\n# Convert train images to TFRecord\nprint('Converting TRAIN images...')\nconvert_to_tfrecord(\n  train_df,\n  'dataset/cots_train',\n  image_path,\n  num_shards = 4\n)\n\n# Convert validation images to TFRecord\nprint('Converting VALIDATION images...')\nconvert_to_tfrecord(\n  val_df,\n  'dataset/cots_val',\n  image_path,\n  num_shards = 4\n)","metadata":{"execution":{"iopub.status.busy":"2022-01-03T14:28:46.483551Z","iopub.execute_input":"2022-01-03T14:28:46.483837Z","iopub.status.idle":"2022-01-03T14:29:50.663649Z","shell.execute_reply.started":"2022-01-03T14:28:46.483808Z","shell.execute_reply":"2022-01-03T14:29:50.662550Z"},"trusted":true},"execution_count":null,"outputs":[]}]}