{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "name": "DeepLab_demo.ipynb", "version": "0.3.2", "views": {}, "default_view": {}, "provenance": [], "collapsed_sections": [] }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "accelerator": "GPU" }, "cells": [ { "metadata": { "id": "kAbdmRmvq0Je", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 } }, "cellView": "code" }, "cell_type": "code", "source": [ "import os\n", "from io import BytesIO\n", "import tarfile\n", "import tempfile\n", "from six.moves import urllib\n", "\n", "from matplotlib import gridspec\n", "from matplotlib import pyplot as plt\n", "import numpy as np\n", "from PIL import Image\n", "\n", "import tensorflow as tf" ], "execution_count": 0, "outputs": [] }, { "metadata": { "id": "vN0kU6NJ1Ye5", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 } }, "cellView": "code" }, "cell_type": "code", "source": [ "#@title Helper methods\n", "\n", "\n", "class DeepLabModel(object):\n", "\n", " INPUT_TENSOR_NAME = 'ImageTensor:0'\n", " OUTPUT_TENSOR_NAME = 'SemanticPredictions:0'\n", " INPUT_SIZE = 513\n", " FROZEN_GRAPH_NAME = 'frozen_inference_graph'\n", "\n", " def __init__(self, tarball_path):\n", " \"\"\"Creates and loads pretrained deeplab model.\"\"\"\n", " self.graph = tf.Graph()\n", "\n", " graph_def = None\n", " # Extract frozen graph from tar archive.\n", " tar_file = tarfile.open(tarball_path)\n", " for tar_info in tar_file.getmembers():\n", " if self.FROZEN_GRAPH_NAME in os.path.basename(tar_info.name):\n", " file_handle = tar_file.extractfile(tar_info)\n", " graph_def = tf.GraphDef.FromString(file_handle.read())\n", " break\n", "\n", " tar_file.close()\n", "\n", " if graph_def is None:\n", " raise RuntimeError('Cannot find inference graph in tar archive.')\n", "\n", " with self.graph.as_default():\n", " tf.import_graph_def(graph_def, name='')\n", "\n", " self.sess = tf.Session(graph=self.graph)\n", "\n", " def run(self, image):\n", " \"\"\"Runs inference on a single image.\n", "\n", " Args:\n", " image: A PIL.Image object, raw input image.\n", "\n", " Returns:\n", " resized_image: RGB image resized from original input image.\n", " seg_map: Segmentation map of `resized_image`.\n", " \"\"\"\n", " width, height = image.size\n", " resize_ratio = 1.0 * self.INPUT_SIZE / max(width, height)\n", " target_size = (int(resize_ratio * width), int(resize_ratio * height))\n", " resized_image = image.convert('RGB').resize(target_size, Image.ANTIALIAS)\n", " batch_seg_map = self.sess.run(\n", " self.OUTPUT_TENSOR_NAME,\n", " feed_dict={self.INPUT_TENSOR_NAME: [np.asarray(resized_image)]})\n", " seg_map = batch_seg_map[0]\n", " return resized_image, seg_map\n", "\n", "\n", "def create_pascal_label_colormap():\n", " \"\"\"Creates a label colormap used in PASCAL VOC segmentation benchmark.\n", "\n", " Returns:\n", " A Colormap for visualizing segmentation results.\n", " \"\"\"\n", " colormap = np.zeros((256, 3), dtype=int)\n", " ind = np.arange(256, dtype=int)\n", "\n", " for shift in reversed(range(8)):\n", " for channel in range(3):\n", " colormap[:, channel] |= ((ind >> channel) & 1) << shift\n", " ind >>= 3\n", "\n", " return colormap\n", "\n", "\n", "def label_to_color_image(label):\n", " \"\"\"Adds color defined by the dataset colormap to the label.\n", "\n", " Args:\n", " label: A 2D array with integer type, storing the segmentation label.\n", "\n", " Returns:\n", " result: A 2D array with floating type. The element of the array\n", " is the color indexed by the corresponding element in the input label\n", " to the PASCAL color map.\n", "\n", " Raises:\n", " ValueError: If label is not of rank 2 or its value is larger than color\n", " map maximum entry.\n", " \"\"\"\n", " if label.ndim != 2:\n", " raise ValueError('Expect 2-D input label')\n", "\n", " colormap = create_pascal_label_colormap()\n", "\n", " if np.max(label) >= len(colormap):\n", " raise ValueError('label value too large.')\n", "\n", " return colormap[label]\n", "\n", "\n", "def vis_segmentation(image, seg_map):\n", " \"\"\"Visualizes input image, segmentation map and overlay view.\"\"\"\n", " plt.figure(figsize=(15, 5))\n", " grid_spec = gridspec.GridSpec(1, 4, width_ratios=[6, 6, 6, 1])\n", "\n", " plt.subplot(grid_spec[1])\n", " seg_image = label_to_color_image(seg_map).astype(np.uint8)\n", " plt.imshow(seg_image)\n", " plt.axis('off')\n", " plt.title('segmentation')\n", "\n", " unique_labels = np.unique(seg_map)\n", " ax = plt.subplot(grid_spec[3])\n", " plt.imshow(\n", " FULL_COLOR_MAP[unique_labels].astype(np.uint8), interpolation='nearest')\n", " ax.yaxis.tick_right()\n", " plt.yticks(range(len(unique_labels)), LABEL_NAMES[unique_labels])\n", " plt.xticks([], [])\n", " ax.tick_params(width=0.0)\n", " plt.grid('off')\n", " plt.show()\n", "\n", "\n", "LABEL_NAMES = np.asarray([\n", " 'background', 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus',\n", " 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike',\n", " 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tv'\n", "])\n", "\n", "FULL_LABEL_MAP = np.arange(len(LABEL_NAMES)).reshape(len(LABEL_NAMES), 1)\n", "FULL_COLOR_MAP = label_to_color_image(FULL_LABEL_MAP)" ], "execution_count": 0, "outputs": [] }, { "metadata": { "id": "c4oXKmnjw6i_", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 }, "base_uri": "https://localhost:8080/", "height": 68 }, "outputId": "3cf4b8a5-3234-48f6-e3a5-17b5fb49183b", "executionInfo": { "status": "ok", "timestamp": 1528487685396, "user_tz": -330, "elapsed": 2194, "user": { "displayName": "Vinayak Pahalwan", "photoUrl": "//lh4.googleusercontent.com/-Qm4RaRviICA/AAAAAAAAAAI/AAAAAAAAAak/S4ifjavm1_E/s50-c-k-no/photo.jpg", "userId": "112108877758942257242" } } }, "cell_type": "code", "source": [ "#@title Select and download models { display-mode: \"code\" }\n", "\n", "MODEL_NAME = 'mobilenetv2_coco_voctrainaug' # @param ['mobilenetv2_coco_voctrainaug', 'mobilenetv2_coco_voctrainval', 'xception_coco_voctrainaug', 'xception_coco_voctrainval']\n", "\n", "_DOWNLOAD_URL_PREFIX = 'http://download.tensorflow.org/models/'\n", "_MODEL_URLS = {\n", " 'mobilenetv2_coco_voctrainaug':\n", " 'deeplabv3_mnv2_pascal_train_aug_2018_01_29.tar.gz'\n", " #,\n", " #'mobilenetv2_coco_voctrainval':\n", " # 'deeplabv3_mnv2_pascal_trainval_2018_01_29.tar.gz',\n", " #'xception_coco_voctrainaug':\n", " # 'deeplabv3_pascal_train_aug_2018_01_04.tar.gz'\n", " #'xception_coco_voctrainval':\n", " # 'deeplabv3_pascal_trainval_2018_01_04.tar.gz',\n", "}\n", "_TARBALL_NAME = 'deeplab_model.tar.gz'\n", "\n", "model_dir = tempfile.mkdtemp()\n", "tf.gfile.MakeDirs(model_dir)\n", "\n", "download_path = os.path.join(model_dir, _TARBALL_NAME)\n", "print('downloading model')\n", "urllib.request.urlretrieve(_DOWNLOAD_URL_PREFIX + _MODEL_URLS[MODEL_NAME],\n", " download_path)\n", "print('download completed!')\n", "\n", "MODEL = DeepLabModel(download_path)\n", "print('model loaded successfully!')" ], "execution_count": 38, "outputs": [ { "output_type": "stream", "text": [ "downloading model\n", "download completed!\n", "model loaded successfully!\n" ], "name": "stdout" } ] }, { "metadata": { "id": "edGukUHXyymr", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 }, "base_uri": "https://localhost:8080/", "height": 352 }, "outputId": "07c3cb41-103d-4e74-c107-4209c4c8d5c9", "executionInfo": { "status": "ok", "timestamp": 1528487688463, "user_tz": -330, "elapsed": 1362, "user": { "displayName": "Vinayak Pahalwan", "photoUrl": "//lh4.googleusercontent.com/-Qm4RaRviICA/AAAAAAAAAAI/AAAAAAAAAak/S4ifjavm1_E/s50-c-k-no/photo.jpg", "userId": "112108877758942257242" } } }, "cell_type": "code", "source": [ "#@title Run on sample images {display-mode: \"form\"}\n", "\n", "SAMPLE_IMAGE = '' \n", "IMAGE_URL = 'https://i.imgur.com/vBBIQ4J.jpg' \n", "\n", "\n", "def run_visualization(url):\n", " \"\"\"Inferences DeepLab model and visualizes result.\"\"\"\n", " try:\n", " f = urllib.request.urlopen(url)\n", " jpeg_str = f.read()\n", " orignal_im = Image.open(BytesIO(jpeg_str))\n", " except IOError:\n", " print('Cannot retrieve image. Please check url: ' + url)\n", " return\n", "\n", " print('running deeplab on image %s...' % url)\n", " resized_im, seg_map = MODEL.run(orignal_im)\n", "\n", " vis_segmentation(resized_im, seg_map)\n", "\n", "\n", "image_url = IMAGE_URL or _SAMPLE_URL % SAMPLE_IMAGE\n", "run_visualization(image_url)" ], "execution_count": 39, "outputs": [ { "output_type": "stream", "text": [ "running deeplab on image https://i.imgur.com/vBBIQ4J.jpg...\n" ], "name": "stdout" }, { "output_type": "display_data", "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAApYAAAE+CAYAAAA3VVAUAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAAHDpJREFUeJzt3XuQlfV9x/HPLrcWMJoVgYzx2npp\nUUzV6MQWpNIQTOxoINVqMNZM2ik4QUdbsV7KBhNqGC/VJNqM14hpHFOBNEbQICGkiWCtZFIxbUEt\nCtGo4A43rQu7/cOy5bLA7vLsub5eM86wu4fz/J7n7HrefJ/nnG1ob29vDwAA7KfGci8AAIDaICwB\nACiEsAQAoBDCEgCAQghLAAAKISwBACiEsKRTb731Vp566ql93u69997LvHnzkiS//vWvc8455/T2\n0gCACiUs6dSyZcuyaNGifd7uhRde6AjLYcOG5bHHHuvtpQEAFarBG6SXztatWzN9+vQ8++yzaWtr\ny3HHHZebbropgwcPzsKFC3P77bdny5YtOeKII3LzzTenqakpLS0tmTp1al555ZWMHDkyBxxwQIYP\nH54vfvGLOeuss3LppZdmzpw5+fWvf53m5uY8/fTT+clPfpKmpqbcfffdOfDAA7Nq1ao0NzfnzTff\nTP/+/TNz5syceOKJWbZsWW699dacdtppWbhwYf7nf/4nN910UwYNGpTPf/7z2bZtW0aNGpXbbrst\n3/3ud3Pfffdl27ZtOeSQQzJr1qwMGDAg5513XjZt2pTf/d3fzaxZszJu3Li88MILaWtry+23354n\nnngiSfKRj3wkf/u3f5uBAwfm4osvzllnnZUnn3wya9asyUc/+tHccsstaWho2Ol4XXPNNRk2bFie\ne+65rFy5Mueff34OO+ywPPjgg9m8eXP+/u//PiNHjsxbb72VadOmZe3atXnvvfdy8cUX59JLL02S\nHHfccbnuuuvy6KOP5o033sjUqVNz4YUXlvyxB4B6YGJZQv/yL/+SNWvWZMGCBXnyySfz27/921m+\nfHleffXVXH311bnlllvy1FNP5fTTT09zc3OS5Jvf/GaampqyePHi/MVf/EV+8IMf7HSfK1euzNy5\nczNlypRcffXVGT9+fH74wx+mra0tTz75ZNra2nLZZZfl3HPPzRNPPJHm5uZMmTIlW7duTfL+xPGk\nk07K/Pnzc9FFF+Wuu+7KiBEjMmnSpHziE5/IbbfdlnXr1mXGjBm5//778+STT+bwww/PnXfemSFD\nhuTKK6/MRz7ykfzjP/7jTuuaP39+lixZkjlz5uQHP/hBNmzYkAceeKDj64sWLcr999+fJ554IkuX\nLs1zzz3X6TFbsmRJvvnNb+bBBx/MPffck/Xr1+f73/9+PvGJT2T27NlJkrvuuisf/vCHs2DBgnzr\nW9/KLbfcktdee63jPlavXp3vfe97+fa3v52ZM2fm7bff3t+HEgDohLAsoaamprz44ov54Q9/mHfe\neSdXXHFFRo0alSVLluS0007LsccemyT50z/90yxatCjbtm3Ls88+23Hd4gknnJCRI0fudJ9jx45N\nkhx77LEZMGBATj/99DQ0NOSYY47JG2+8kZdeeinr1q3LZz7zmSTJKaeckqampixfvjxJMmjQoPzR\nH/1RkmTEiBH51a9+tdu6Dz744Pzbv/1bhg8fniQ59dRT8+qrr+51XxcvXpzzzjsvAwcOTJ8+fTJh\nwoT89Kc/7fj6+PHj8xu/8RsZOHBgjjzyyJ1CcEdnnHFGBg4cmGOOOSZtbW35wz/8w479feONN5Ik\n119/fW644YYkyWGHHZZDDjkka9as6biPiRMnJkmOPvroHHXUUfnFL36x17UDAD3Tt9wLqCcjR47M\n9ddfn9mzZ2fatGk566yzMn369GzcuDHPPvtsxo8f33HbwYMHp6WlJRs2bMiBBx7Y8flhw4btdJ+D\nBg1KkjQ2Nnb8efvHbW1t2bBhQ959992cffbZHV/btGlTWlpa8oEPfCAHHHDAbn9nV9u2bcsdd9zR\nEbubN2/OUUcdtdd9Xb9+/U7rPvDAA7Nu3bqd9m+7Pn36ZNu2bZ3ez/Z9amhoSGNjYwYOHLjbWv/9\n3/+9Y0rZ2NiYN998c6f92HUdGzZs2OvaAYCeEZYlNn78+IwfPz4tLS259tprc++99+aII47IGWec\nkTvuuGO32w8aNChbtmzp+PjNN9/M4Ycf3uXtDR06NIMGDcqCBQt2+9qyZcu6dB+PP/54Fi1alIce\neihNTU155JFH8v3vf3+vf2fIkCFpaWnp+LilpSVDhgzp8rq746//+q9zySWX5MILL0xDQ0NGjRq1\n09fffvvtHHrooR3r2DE0AYDiOBVeQo8++mi+8Y1vJEkOOuigHH300UmSP/iDP8izzz7bcXr5F7/4\nRb785S8neX/KuT0Kf/nLX3b7NO6hhx6a4cOHd9zH+vXrc+WVV+4Uq53p27dvNm7cmCRZt25dDj30\n0DQ1NeXtt9/O/Pnzs3nz5o7bbdq0Kbu+BmzMmDH553/+57zzzjvZunVr/umf/ilnnnlmt9beVevW\nrcsJJ5yQhoaGzJ07N++8885O+7f9utQXX3wxq1evzkknndQr6wCAeicsS2js2LFZsWJFxo0bl7PP\nPjurVq3KpZdemqFDh+bGG2/MZZddlrPPPjszZszIJz/5ySTJ5MmT8/LLL+fjH/947rvvvowdO3a3\nV0/vTUNDQ2699dZ8+9vfzvjx4zNp0qR87GMf6zilvCe///u/n6VLl2bixIk555xz0tLSko9//OO5\n6qqrcsUVV+T111/PTTfdlFNOOSVvvPFGRo0atdPp5/Hjx2f06NGZMGFCzjnnnAwfPjyf+9znenbg\n9uHyyy/PZZddlj/+4z/Oli1bcsEFF+SGG27IK6+8kuT9a1vPPffcfPazn831119vYgkAvcTbDVWB\n9vb2jpicOnVqTjnllFxyySVlXlV1OO644/LjH/+444VHAEDvMbGscA899FAmT56ctra2rFu3Ls88\n80x+7/d+r9zLAgDYjRfvVLhPf/rTeeaZZzJu3Lg0Njbm85///G5vOQQAUAmcCgcAoBBOhQMAUAhh\nCQBAIcp6jWV33jYH6DlXvABQCiaWAAAUQlgCAFAIYQkAQCGEJQAAhRCWAAAUQlgCAFAIYQkAQCGE\nJQAAhRCWAAAUQlgCAFAIYQkAQCGEJQAAhRCWAAAUQlgCAFAIYQkAQCGEJQAAhRCWAAAUQlgCAFAI\nYQkAQCGEJQAAhRCWAAAUQlgCAFAIYQkAQCGEJQAAhRCWAAAUQlgCAFAIYQkAQCGEJQAAhRCWAAAU\nQlgCAFAIYQkAQCGEJQAAhRCWAAAUom+5F1DtFjc37/a5MZ18DgCg1jW0t7e3l23jDQ3l2vR+6Swm\n90RkUgnK+GMOQB0Rll3QnZDcE4FJOQlLAErBNZb7UERUFnk/AACVysRyL3orBk0vKTUTSwBKwcQS\nAIBCCMs96M1T106LAwC1SFiWibgEAGqNsOyE6AMA6D5hCQBAIYRlGZmMAgC1RFjuQuwBAPSMsAQA\noBDCEgCAQghLAAAKISwBACiEsNxBqV+443eGAwC1RFgCAFAIYQkAQCGE5f/x/pUAAPtHWAIAUIiG\n9vb29rJtvKGhXJveSbmmlYu7cJvmTta26+c6uw3sqIw/5gDUkb7lXgD/ryeBKCoBgEpR96fCK+Xa\nSoEIAFQ7E8sqUo3x2Vm4e/9OAKhNdR2W5ZxWLu7m7btyrWUl2dux3fVrQhMAakNdh2U5NTc3d4Rh\nJQdiT3Q32LffvqjANCUFgPKo22ssq+nayloLzz3Z38dkcXPzHu+jUh5vAKhlJpZlVIvBWEQcJt2b\nMHZ1mzvezgQTAIpXlxPLSphedXUN1RSfRR7XnsRib9w/ANB1dfcG6ZUSFF2dmO0pLCstOHvzuHZ2\nrIrcXj1ML71BOgClUJcTy2qy44t8dvxcPdkxIvd2HWUR9w8A9JyJZZnU0pSsUo7p/qqlx2RXJpYA\nlIKJJfulVqIyqa19AYByEJawA3EJAD1XV2EpGopVq8ezVvcLAHpbXYUlAAC9p25evFOJU6gxnbzi\ne7tKf+V3JR7PotXSi3m8eAeAUvCbd8pocXNzFu/la0l2+3olBGc9RCUA0H01P7Gs9giqxKlZtR/T\n7qjE498TJpYAlEJNX2NZCwFUC/sAANSHmg1LQdY7HFcAYE9qMizFD0XxvQQAXVdzYSkEAADKo+bC\nshZVSixXyjpKrV73G6ASNTQ0VOx/CEsAAApSU2FZy5Olcu9bubdfbvW+/wDQFTUVlvQOUfU+xwEA\n9s5v3mGPhBQA0B01E5YiqDiOJQDQE06FV5FSBJ+o3DvHBwD2rCbC0pN9MRxHAGB/VH1YiqFiOI4A\nwP6q+rBk/4lKAKAIwrLKiMDy8xgAQOeEZZ0TSQBAUYQl9IAgB4DdVXVYenKnnHz/AcDOqjos65Wg\nAQAqkbCsUuKyMngcAOD/CUsAgF42Z86cfPWrXy353y3ShAkTsmbNmr3eRlhWMdOyyuBxAID39S33\nAnrKkzkAUE3WrFmTP//zP8/rr7+eSy65JP37989DDz2UxsbGHHPMMbnxxhvT2tqaa665JmvXrs2A\nAQMya9asne7jlltuyW/+5m/m4osvztSpU/Puu+/mzDPPzCOPPJJFixZl3LhxGT16dA4++OB8+tOf\nzrXXXpvW1tY0NDTkK1/5ShoaGjJ16tTMmTMnyftTyDvuuCNf//rXM3To0KxYsSK/+tWvcvPNN2fE\niBH58pe/nOXLl+eoo45Ka2vrPvfRxBIAoAT++7//O3feeWcefPDB3HHHHdmyZUvuueeePPzww3np\npZfyn//5n5k3b16GDBmShx9+OOeff36eeuqpjr8/f/78vPbaa5kyZUrmzZuX3/qt38p3vvOdHHDA\nAR232bp1a0aPHp3Jkyfn9ttvz2c+85nMnj07F110Ub7+9a/vdX3vvfde7r333nzuc5/LvHnzsmrV\nqjz33HP57ne/m6uuuiovv/zyPvdRWEIBTNAB2JeTTz45/fr1ywc/+MEMHjw4Bx10UKZMmZJJkybl\nxRdfTEtLS1asWJGTTz45SfKpT30qF110UZJk5cqVufnmm/OVr3wlSfLiiy923G7s2LE7bWfkyJFJ\nkueffz6nnXZakuT000/PCy+8sNf1nXrqqUmS4cOHZ9OmTVm1alVOOumkNDY25kMf+lAOO+ywfe6j\nsKxy+xM0YggASqehoWGnj6+66qrcdttteeihh3LSSSclSfr06ZO2trbd/u7atWtzzDHHZMGCBUmS\n9vb2NDY2dnq//fr16/h8e3t7kqS1tTWNjY273Xbr1q0df+7Tp0/Hn9vb23faRpJO17UrYVmnRGXx\nHFMA9ubnP/95tm3blvXr1+e1115LU1NTDjnkkLz22mt5/vnn09ramhNPPDFLly5NkvzoRz/KP/zD\nPyRJxowZk5kzZ+bOO+/MW2+9lcMPPzzPP/98kmTJkiWdbu/EE0/MsmXLkiT/+q//mhNOOCGDBw/O\nunXr0t7enjfffDOvvvrqHtd71FFHZcWKFWlvb8/atWuzdu3afe5jVb54xxP4/nH8AKD0jj766Fx+\n+eVZvXp1mpub8/TTT2fixIk5/vjj84UvfCF/93d/l7lz5+ZnP/tZJk2alL59++arX/1qfvrTnyZJ\nmpqaMnXq1DQ3N2fGjBmZMmVKLr744pxxxhk7TRa3mzp1aq677ro88sgj6devX2bOnJkDDzwwZ5xx\nRsd2f+d3fmeP6z3++ONz7LHH5oILLsiRRx6Z448/fp/72NC+fUZaBruOY7tKGO1sTDeOh2PX+7rz\neJRKGX/MAQrV03YohVL+v3bt2rV56aWXMmrUqCxfvjxf+9rXct9995Vs+3tSlRNLAIB6dsABB+SB\nBx7IN77xjSTJddddV+YVvU9YQsEWNzdX5NQSgNrxgQ98IPfee2+5l7GbqnvxjlO5AACVqerCkp4T\n5QBAbxKWNUAwVh6PCQD1qKrC0pN1zzl2peeYA1Bvqios6RmBAwCUgrCsEeKxMnlcAKgnwrLGCRsA\n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\n", "text/plain": [ "" ] }, "metadata": { "tags": [] } } ] }, { "metadata": { "id": "7XrFNGsxzSIB", "colab_type": "code", "colab": { "autoexec": { "startup": false, "wait_interval": 0 } } }, "cell_type": "code", "source": [ "" ], "execution_count": 0, "outputs": [] } ] }