{"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 os\nimport re\nimport time\nimport numpy as np\nimport tensorflow as tf\nfrom kaggle_datasets import KaggleDatasets\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2022-08-05T14:40:49.911503Z","iopub.execute_input":"2022-08-05T14:40:49.911842Z","iopub.status.idle":"2022-08-05T14:40:49.917034Z","shell.execute_reply.started":"2022-08-05T14:40:49.911812Z","shell.execute_reply":"2022-08-05T14:40:49.916168Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's use 224x224 by default\nimage_size = (224, 224)\n\n# Data dirs\ndata_gcs = KaggleDatasets().get_gcs_path('tpu-getting-started')\next_gcs = KaggleDatasets().get_gcs_path('tf-flower-photo-tfrec')\n\n# Subdirs by image size\ndata_dir_by_size = {\n    (512, 512): '/tfrecords-jpeg-512x512',\n    (331, 331): '/tfrecords-jpeg-331x331',\n    (224, 224): '/tfrecords-jpeg-224x224',\n    (192, 192): '/tfrecords-jpeg-192x192'\n}\nsubdir = data_dir_by_size[image_size]\n\n# Paths to data files\ntrain_file_names = tf.io.gfile.glob(data_gcs + subdir + '/train' + '/*.tfrec')\nval_file_names = tf.io.gfile.glob(data_gcs + subdir + '/val' + '/*.tfrec')\ntest_file_names = tf.io.gfile.glob(data_gcs + subdir + '/test' + '/*.tfrec')\n\n# Extending the dataset with additional data\nimagenet_files = tf.io.gfile.glob(ext_gcs + '/imagenet' + subdir + '/*.tfrec')\ninaturelist_files = tf.io.gfile.glob(ext_gcs + '/inaturalist' + subdir + '/*.tfrec')\nopenimage_files = tf.io.gfile.glob(ext_gcs + '/openimage' + subdir + '/*.tfrec')\noxford_files = tf.io.gfile.glob(ext_gcs + '/oxford_102' + subdir + '/*.tfrec')\ntensorflow_files = tf.io.gfile.glob(ext_gcs + '/tf_flowers' + subdir + '/*.tfrec')\n\ntrain_file_names = train_file_names + imagenet_files + inaturelist_files + \\\n    openimage_files + oxford_files + tensorflow_files","metadata":{"execution":{"iopub.status.busy":"2022-08-05T14:40:00.102858Z","iopub.execute_input":"2022-08-05T14:40:00.103183Z","iopub.status.idle":"2022-08-05T14:40:01.636144Z","shell.execute_reply.started":"2022-08-05T14:40:00.103156Z","shell.execute_reply":"2022-08-05T14:40:01.635347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Classification Categories in our Dataset\nflower_categories = [\n    'pink primrose',     'hard-leaved pocket orchid', 'canterbury bells',\n    'sweet pea',         'wild geranium',             'tiger lily',\n    'moon orchid',       'bird of paradise',          'monkshood',\n    'globe thistle',     'snapdragon',                'colt\\'s foot',\n    'king protea',       'spear thistle',             'yellow iris',\n    'globe-flower',      'purple coneflower',         'peruvian lily',\n    'balloon flower',    'giant white arum lily',     'fire lily',\n    'pincushion flower', 'fritillary',                'red ginger',\n    'grape hyacinth',    'corn poppy',                'prince of wales feathers',\n    'stemless gentian',  'artichoke',                 'sweet william',\n    'carnation',         'garden phlox',              'love in the mist',\n    'cosmos',            'alpine sea holly',          'ruby-lipped cattleya',\n    'cape flower',       'great masterwort',          'siam tulip',\n    'lenten rose',       'barberton daisy',           'daffodil',\n    'sword lily',        'poinsettia',                'bolero deep blue',\n    'wallflower',        'marigold',                  'buttercup',\n    'daisy',             'common dandelion',          'petunia',\n    'wild pansy',        'primula',                   'sunflower',\n    'lilac hibiscus',    'bishop of llandaff',        'gaura',\n    'geranium',          'orange dahlia',             'pink-yellow dahlia',\n    'cautleya spicata',  'japanese anemone',          'black-eyed susan',\n    'silverbush',        'californian poppy',         'osteospermum',\n    'spring crocus',     'iris',                      'windflower',\n    'tree poppy',        'gazania',                   'azalea',\n    'water lily',        'rose',                      'thorn apple',\n    'morning glory',     'passion flower',            'lotus',\n    'toad lily',         'anthurium',                 'frangipani',\n    'clematis',          'hibiscus',                  'columbine',\n    'desert-rose',       'tree mallow',               'magnolia',\n    'cyclamen ',         'watercress',                'canna lily',\n    'hippeastrum ',      'bee balm',                  'pink quill',\n    'foxglove',          'bougainvillea',             'camellia',\n    'mallow',            'mexican petunia',           'bromelia',\n    'blanket flower',    'trumpet creeper',           'blackberry lily',\n    'common tulip',      'wild rose'\n]\n\nprint('Number of flower categories:', len(flower_categories))","metadata":{"execution":{"iopub.status.busy":"2022-08-05T14:40:01.637737Z","iopub.execute_input":"2022-08-05T14:40:01.638018Z","iopub.status.idle":"2022-08-05T14:40:01.648398Z","shell.execute_reply.started":"2022-08-05T14:40:01.637991Z","shell.execute_reply":"2022-08-05T14:40:01.647652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def decode_image(image_data):\n    \"\"\"Decodes JPEG data and return a normalized image.\n    \n    WARNING: you may need a different normalization if you\n    use VGG-like networks.\n    \"\"\"\n    image = tf.image.decode_jpeg(image_data, channels=3)\n    # image = tf.cast(image, tf.float32) / 255.0\n    image = tf.reshape(image, [*image_size, 3])\n    return image\n\n\ndef read_labeled_tfrecord(example):\n    \"\"\"\n    Converts a single record in labeled dataset (i.e. train and validation\n    sets) to the more convenient format (image, label)\n    \"\"\"\n    example = tf.io.parse_single_example(\n        serialized=example,\n        features={\n            'image': tf.io.FixedLenFeature([], tf.string),\n            'class': tf.io.FixedLenFeature([], tf.int64),\n        }\n    )\n    \n    image = decode_image(example['image'])\n    label = tf.cast(example['class'], tf.int32)\n    return image, label\n\n\ndef read_unlabeled_tfrecord(example):\n    \"\"\"\n    Converts a single record in labeled dataset (i.e. test\n    set) to the more convenient format (image, id)\n    \"\"\"\n    example = tf.io.parse_single_example(\n        serialized=example,\n        features={\n            'image': tf.io.FixedLenFeature([], tf.string),\n            'id': tf.io.FixedLenFeature([], tf.string),\n        }\n    )\n    \n    image = decode_image(example['image'])\n    idnum = example['id']\n    return image, idnum\n\n\ndef load_dataset(filenames, labeled=True, ordered=False):\n    \"\"\"\n    Given a list of `*.tfrec` file names, converts them into a `tf.data.Dataset`\n    object that yields elements of format (image, label) or (image, id)\n    \n    # Arguments\n        filenames: list of paths to `*.tfrec` files\n        labeled: if True, the resulting dataset will yield data in format\n            (image, label). Otherwise it will yield in format (image, id)\n        ordered: whether to shuffle the dataset (not desirable for test/val)\n        \n    # Returns\n        a `tf.data.Dataset` object that holds memory map to `*.tfrec` files\n    \"\"\"\n    ignore_order = tf.data.Options()\n    ignore_order.experimental_deterministic = ordered\n    \n    dataset = tf.data.TFRecordDataset(\n        filenames, num_parallel_reads=tf.data.experimental.AUTOTUNE)\n    dataset = dataset.with_options(ignore_order)\n    dataset = dataset.map(\n        read_labeled_tfrecord if labeled else read_unlabeled_tfrecord,\n        num_parallel_calls=tf.data.experimental.AUTOTUNE)\n    return dataset\n\n\ndef count_data_items(filenames):\n    \"\"\"\n    There's no way to obtain explicitly the number of elements in each dataset\n    (see: https://stackoverflow.com/questions/40472139/), but we can infer that\n    from file names, i.e. flowers00-230.tfrec = 230 data items\n    \"\"\"\n    return np.sum([\n        int(re.compile(r\"-([0-9]*)\\.\").search(filename).group(1))\n        for filename in filenames])\n\n\n# Import Datasets\ntrain_dataset = load_dataset(train_file_names, labeled=True, ordered=True)\nval_dataset = load_dataset(val_file_names, labeled=True, ordered=True)\ntest_dataset = load_dataset(test_file_names, labeled=False, ordered=True)\n\n# Calculate number of items\nnum_training_samples = count_data_items(train_file_names)\nnum_validation_samples = count_data_items(val_file_names)\nnum_testing_samples = count_data_items(test_file_names)\n\nprint('Num train:', num_training_samples)\nprint('Num val:', num_validation_samples)\nprint('Num test:', num_testing_samples)","metadata":{"execution":{"iopub.status.busy":"2022-08-05T14:51:28.416963Z","iopub.execute_input":"2022-08-05T14:51:28.417384Z","iopub.status.idle":"2022-08-05T14:51:28.560673Z","shell.execute_reply.started":"2022-08-05T14:51:28.417350Z","shell.execute_reply":"2022-08-05T14:51:28.559822Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nfrom PIL import Image\nfrom uuid import uuid4\nfrom tqdm import tqdm\n\n# Create dirs\nos.makedirs('flower_dataset/train', exist_ok=True)\nos.makedirs('flower_dataset/val', exist_ok=True)\nos.makedirs('flower_dataset/test', exist_ok=True)\nfor flower_cat in flower_categories:\n    os.makedirs(f'flower_dataset/train/{flower_cat}', exist_ok=True)\n    os.makedirs(f'flower_dataset/val/{flower_cat}', exist_ok=True)\n\n# export train\nfor i, (image_tensor, label_tensor) in enumerate(train_dataset):\n    image = Image.fromarray(image_tensor.numpy())\n    label = flower_categories[label_tensor.numpy()]\n    unique_name = f'{uuid4().hex}.jpg'\n    image.save(os.path.join('flower_dataset/train', label, unique_name), quality=90)\n    if (i + 1) % 500 == 0:\n        print('Processed', i, 'images')\nprint('Finished processing, total', i, 'images')\n    \n# export val\nfor i, (image_tensor, label_tensor) in enumerate(val_dataset):\n    image = Image.fromarray(image_tensor.numpy())\n    label = flower_categories[label_tensor.numpy()]\n    unique_name = f'{uuid4().hex}.jpg'\n    image.save(os.path.join('flower_dataset/val', label, unique_name), quality=90)\n    if (i + 1) % 500 == 0:\n        print('Processed', i, 'images')\nprint('Finished processing, total', i, 'images')\n    \n# export test\nfor i, (image_tensor, label_tensor) in enumerate(test_dataset):\n    image = Image.fromarray(image_tensor.numpy())\n    image_id = label_tensor.numpy().decode()\n    image.save(os.path.join('flower_dataset/test', f'{image_id}.jpg'), quality=90)\n    if (i + 1) % 500 == 0:\n        print('Processed', i, 'images')\nprint('Finished processing, total', i, 'images')","metadata":{"execution":{"iopub.status.busy":"2022-08-05T15:00:17.071390Z","iopub.execute_input":"2022-08-05T15:00:17.071743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!zip -r extended_flower_dataset.zip flower_dataset\n!rm -rf flower_dataset/","metadata":{},"execution_count":null,"outputs":[]}]}