{"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":"# [Create U-Net from scratch -Image segmentation with U-Net in Keras and TensorFlow](https://www.machinelearningnuggets.com/image-segmentation-with-u-net-define-u-net-model-from-scratch-in-keras-and-tensorflow)","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nimport os\nimport random\nimport numpy as np\n \nfrom tqdm import tqdm \n\nfrom skimage.io import imread, imshow\nfrom skimage.transform import resize\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split\n","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:44:53.105057Z","iopub.execute_input":"2022-12-18T06:44:53.106009Z","iopub.status.idle":"2022-12-18T06:44:58.789647Z","shell.execute_reply.started":"2022-12-18T06:44:53.105905Z","shell.execute_reply":"2022-12-18T06:44:58.788697Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from zipfile import ZipFile\nwith ZipFile(\"../input/data-science-bowl-2018/stage1_train.zip\",\"r\") as zip_ref:\n    zip_ref.extractall(\"./stage1_train\")\n    \nwith ZipFile(\"../input/data-science-bowl-2018/stage1_test.zip\",\"r\") as zip_ref:\n    zip_ref.extractall(\"./stage1_test\")","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:44:58.792290Z","iopub.execute_input":"2022-12-18T06:44:58.793048Z","iopub.status.idle":"2022-12-18T06:45:04.503600Z","shell.execute_reply.started":"2022-12-18T06:44:58.792997Z","shell.execute_reply":"2022-12-18T06:45:04.502651Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"seed = 42\nnp.random.seed = seed\n\nIMG_WIDTH = 128\nIMG_HEIGHT = 128\nIMG_CHANNELS = 3\n\nTRAIN_PATH = 'stage1_train/'\nTEST_PATH = 'stage1_test/'\n\ntrain_ids = next(os.walk(TRAIN_PATH))[1]\ntest_ids = next(os.walk(TEST_PATH))[1]\n\nX = np.zeros((len(train_ids), IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS), dtype=np.uint8)\ny = np.zeros((len(train_ids), IMG_HEIGHT, IMG_WIDTH, 1), dtype=bool)","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:45:04.505122Z","iopub.execute_input":"2022-12-18T06:45:04.505480Z","iopub.status.idle":"2022-12-18T06:45:04.515437Z","shell.execute_reply.started":"2022-12-18T06:45:04.505445Z","shell.execute_reply":"2022-12-18T06:45:04.514527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"__author__ = \"Sreenivas Bhattiprolu\"\n__license__ = \"Feel free to copy, I appreciate if you acknowledge Python for Microscopists\"\n\n# Credits https://github.com/bnsreenu/python_for_microscopists \n\n\"\"\"\n@author: Sreenivas Bhattiprolu\n\"\"\"\n\nprint('Resizing training images and masks')\nfor n, id_ in tqdm(enumerate(train_ids), total=len(train_ids)):   \n    path = TRAIN_PATH + id_\n    img = imread(path + '/images/' + id_ + '.png')[:,:,:IMG_CHANNELS]  \n    img = resize(img, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True)\n    X[n] = img  #Fill empty X_train with values from img\n    mask = np.zeros((IMG_HEIGHT, IMG_WIDTH, 1), dtype=bool)\n    for mask_file in next(os.walk(path + '/masks/'))[2]:\n        mask_ = imread(path + '/masks/' + mask_file)\n        mask_ = np.expand_dims(resize(mask_, (IMG_HEIGHT, IMG_WIDTH), mode='constant',  \n                                      preserve_range=True), axis=-1)\n        mask = np.maximum(mask, mask_)  \n            \n    y[n] = mask ","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:45:04.518429Z","iopub.execute_input":"2022-12-18T06:45:04.518954Z","iopub.status.idle":"2022-12-18T06:49:00.837569Z","shell.execute_reply.started":"2022-12-18T06:45:04.518820Z","shell.execute_reply":"2022-12-18T06:49:00.836500Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:00.839285Z","iopub.execute_input":"2022-12-18T06:49:00.840020Z","iopub.status.idle":"2022-12-18T06:49:00.861767Z","shell.execute_reply.started":"2022-12-18T06:49:00.839981Z","shell.execute_reply":"2022-12-18T06:49:00.860882Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# test images\ntest_images = np.zeros((len(test_ids), IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS), dtype=np.uint8)\nsizes_test = []\nprint('Resizing test images') \nfor n, id_ in tqdm(enumerate(test_ids), total=len(test_ids)):\n    path = TEST_PATH + id_\n    img = imread(path + '/images/' + id_ + '.png')[:,:,:IMG_CHANNELS]\n    sizes_test.append([img.shape[0], img.shape[1]])\n    img = resize(img, (IMG_HEIGHT, IMG_WIDTH), mode='constant', preserve_range=True)\n    test_images[n] = img\n\nprint('Done!')","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:00.863453Z","iopub.execute_input":"2022-12-18T06:49:00.863823Z","iopub.status.idle":"2022-12-18T06:49:02.242990Z","shell.execute_reply.started":"2022-12-18T06:49:00.863789Z","shell.execute_reply":"2022-12-18T06:49:02.241879Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_x = random.randint(0, len(X_train))\nplt.axis(\"off\")\nimshow(X_train[image_x])\nplt.show()\nplt.axis(\"off\")\nimshow(np.squeeze(y_train[image_x]))\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:02.244658Z","iopub.execute_input":"2022-12-18T06:49:02.245328Z","iopub.status.idle":"2022-12-18T06:49:02.557010Z","shell.execute_reply.started":"2022-12-18T06:49:02.245290Z","shell.execute_reply":"2022-12-18T06:49:02.555774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_classes = 1","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:02.560212Z","iopub.execute_input":"2022-12-18T06:49:02.562351Z","iopub.status.idle":"2022-12-18T06:49:02.568137Z","shell.execute_reply.started":"2022-12-18T06:49:02.562303Z","shell.execute_reply":"2022-12-18T06:49:02.566684Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Build the model\ninputs = tf.keras.layers.Input((IMG_HEIGHT, IMG_WIDTH, IMG_CHANNELS))\n\n#Contraction path\nc1 = tf.keras.layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(inputs)\nc1 = tf.keras.layers.Dropout(0.1)(c1)\nc1 = tf.keras.layers.Conv2D(16, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c1)\nb1 = tf.keras.layers.BatchNormalization()(c1)\nr1 = tf.keras.layers.ReLU()(b1)\np1 = tf.keras.layers.MaxPooling2D((2, 2))(r1)\n\nc2 = tf.keras.layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p1)\nc2 = tf.keras.layers.Dropout(0.1)(c2)\nc2 = tf.keras.layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c2)\nb2 = tf.keras.layers.BatchNormalization()(c2)\nr2 = tf.keras.layers.ReLU()(b2)\np2 = tf.keras.layers.MaxPooling2D((2, 2))(r2)\n \nc3 = tf.keras.layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p2)\nc3 = tf.keras.layers.Dropout(0.2)(c3)\nc3 = tf.keras.layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c3)\nb3 = tf.keras.layers.BatchNormalization()(c3)\nr3 = tf.keras.layers.ReLU()(b3)\np3 = tf.keras.layers.MaxPooling2D((2, 2))(r3)\n \nc4 = tf.keras.layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p3)\nc4 = tf.keras.layers.Dropout(0.2)(c4)\nc4 = tf.keras.layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c4)\nb4 = tf.keras.layers.BatchNormalization()(c4)\nr4 = tf.keras.layers.ReLU()(b4)\np4 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(r4)\n \nc5 = tf.keras.layers.Conv2D(256, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(p4)\nb5 = tf.keras.layers.BatchNormalization()(c5)\nr5 = tf.keras.layers.ReLU()(b5)\nc5 = tf.keras.layers.Dropout(0.3)(r5)\nc5 = tf.keras.layers.Conv2D(256, (3, 3), activation='relu', kernel_initializer='he_normal', padding='same')(c5)\n\n#Expansive path \nu6 = tf.keras.layers.Conv2DTranspose(128, (2, 2), strides=(2, 2), padding='same')(c5)\nu6 = tf.keras.layers.concatenate([u6, c4])\nu6 = tf.keras.layers.BatchNormalization()(u6)\nu6 = tf.keras.layers.ReLU()(u6)\n\n \nu7 = tf.keras.layers.Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same')(u6)\nu7 = tf.keras.layers.concatenate([u7, c3])\nu7 = tf.keras.layers.BatchNormalization()(u7)\nu7 = tf.keras.layers.ReLU()(u7)\n\n \nu8 = tf.keras.layers.Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same')(u7)\nu8 = tf.keras.layers.concatenate([u8, c2])\nu8 = tf.keras.layers.BatchNormalization()(u8)\nu8 = tf.keras.layers.ReLU()(u8)\n \nu9 = tf.keras.layers.Conv2DTranspose(16, (2, 2), strides=(2, 2), padding='same')(u8)\nu9 = tf.keras.layers.concatenate([u9, c1], axis=3)\nu9 = tf.keras.layers.BatchNormalization()(u9)\nu9 = tf.keras.layers.ReLU()(u9)\n\n \noutputs = tf.keras.layers.Conv2D(num_classes, (1, 1), activation='sigmoid')(u9)\n \nmodel = tf.keras.Model(inputs=[inputs], outputs=[outputs])\nmodel.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])\nmodel.summary()\n","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:02.570689Z","iopub.execute_input":"2022-12-18T06:49:02.572135Z","iopub.status.idle":"2022-12-18T06:49:06.393262Z","shell.execute_reply.started":"2022-12-18T06:49:02.572091Z","shell.execute_reply":"2022-12-18T06:49:06.392111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tf.keras.utils.plot_model(model, \"model.png\")\n","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:06.396854Z","iopub.execute_input":"2022-12-18T06:49:06.397134Z","iopub.status.idle":"2022-12-18T06:49:07.503335Z","shell.execute_reply.started":"2022-12-18T06:49:06.397109Z","shell.execute_reply":"2022-12-18T06:49:07.502271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"callbacks = [\n        tf.keras.callbacks.EarlyStopping(patience=2, monitor='val_loss'),\n        tf.keras.callbacks.TensorBoard(log_dir='logs')]\n\nmodel.fit(X_train, y_train, validation_data=(X_test,y_test), batch_size=16, epochs=25, callbacks=callbacks)","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:07.504937Z","iopub.execute_input":"2022-12-18T06:49:07.505675Z","iopub.status.idle":"2022-12-18T06:49:25.882788Z","shell.execute_reply.started":"2022-12-18T06:49:07.505628Z","shell.execute_reply":"2022-12-18T06:49:25.881865Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss = model.history.history['loss']\nval_loss = model.history.history['val_loss']\n\nplt.figure()\nplt.plot( loss, 'r', label='Training loss')\nplt.plot( val_loss, 'bo', label='Validation loss')\nplt.title('Training and Validation Loss')\nplt.xlabel('Epoch')\nplt.ylabel('Loss Value')\nplt.ylim([0, 1])\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:25.884358Z","iopub.execute_input":"2022-12-18T06:49:25.884720Z","iopub.status.idle":"2022-12-18T06:49:26.091688Z","shell.execute_reply.started":"2022-12-18T06:49:25.884685Z","shell.execute_reply":"2022-12-18T06:49:26.090819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"accuracy = model.history.history['accuracy']\nval_accuracy = model.history.history['val_accuracy']\n\nplt.figure()\nplt.plot( accuracy, 'r', label='Training accuracy')\nplt.plot( val_accuracy, 'bo', label='Validation accuracy')\nplt.title('Training and Validation accuracy')\nplt.xlabel('Epoch')\nplt.ylabel('Loss Value')\nplt.ylim([0, 1])\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:26.092918Z","iopub.execute_input":"2022-12-18T06:49:26.093258Z","iopub.status.idle":"2022-12-18T06:49:26.292285Z","shell.execute_reply.started":"2022-12-18T06:49:26.093224Z","shell.execute_reply":"2022-12-18T06:49:26.291341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def display(display_list):\n  plt.figure(figsize=(15, 15))\n\n  title = ['Input image', 'True mask', 'Predicted mask']\n\n  for i in range(len(display_list)):\n    plt.subplot(1, len(display_list), i+1)\n    plt.title(title[i])\n    plt.imshow(tf.keras.utils.array_to_img(display_list[i]))\n    plt.axis('off')\n  plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:26.293460Z","iopub.execute_input":"2022-12-18T06:49:26.293782Z","iopub.status.idle":"2022-12-18T06:49:26.300614Z","shell.execute_reply.started":"2022-12-18T06:49:26.293749Z","shell.execute_reply":"2022-12-18T06:49:26.299454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"i = random.randint(0, len(X_test))\nsample_image = X_test[i]\nsample_mask = y_test[i]","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:26.302259Z","iopub.execute_input":"2022-12-18T06:49:26.302761Z","iopub.status.idle":"2022-12-18T06:49:26.308802Z","shell.execute_reply.started":"2022-12-18T06:49:26.302726Z","shell.execute_reply":"2022-12-18T06:49:26.307737Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"prediction = model.predict(sample_image[tf.newaxis, ...])[0]","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:26.310279Z","iopub.execute_input":"2022-12-18T06:49:26.311500Z","iopub.status.idle":"2022-12-18T06:49:26.661587Z","shell.execute_reply.started":"2022-12-18T06:49:26.311465Z","shell.execute_reply":"2022-12-18T06:49:26.660584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predicted_mask = (prediction > 0.5).astype(np.uint8)","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:26.662944Z","iopub.execute_input":"2022-12-18T06:49:26.663288Z","iopub.status.idle":"2022-12-18T06:49:26.670989Z","shell.execute_reply.started":"2022-12-18T06:49:26.663254Z","shell.execute_reply":"2022-12-18T06:49:26.669895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display([sample_image, sample_mask,predicted_mask])","metadata":{"execution":{"iopub.status.busy":"2022-12-18T06:49:26.674211Z","iopub.execute_input":"2022-12-18T06:49:26.674481Z","iopub.status.idle":"2022-12-18T06:49:26.925595Z","shell.execute_reply.started":"2022-12-18T06:49:26.674457Z","shell.execute_reply":"2022-12-18T06:49:26.924725Z"},"trusted":true},"execution_count":null,"outputs":[]}]}