{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# REACTION" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Breast Cancer Detection based on Mammography Image Using Convolutional Neural Network Algorithm" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "bRaZJDt9KQIW" }, "outputs": [], "source": [ "from ipywidgets import Layout, Button, Box, FileUpload, Label, Checkbox, IntSlider, IntText, Button\n", "import ipywidgets as widgets\n", "from IPython.display import display, Image\n", "import threading\n", "import time\n", "\n", "import tensorflow as tf\n", "#\n", "from keras.preprocessing import image\n", "\n", "# uploader to image cv2\n", "import numpy as np\n", "import cv2\n", "import matplotlib.pyplot as plt\n", " \n", "import os\n", "\n", "import plotly\n", "import plotly.graph_objects as go\n", "import plotly.express as px\n", "from plotly.offline import iplot, init_notebook_mode" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 49, "referenced_widgets": [ "915634932fd0483fb4227831f312235f", "b84a7ad88c984bb9b03221b99bbcfb63", "c8e9cde3226c46a7bc0eee77bee52b08" ] }, "id": "j2zmhr3rKUp4", "outputId": "4ec82185-cc44-46b7-847f-0f11c3c831c7" }, "outputs": [], "source": [ "# uploader\n", "uploader = widgets.FileUpload(\n", " accept='image/*', # Accepted file extension e.g. '.txt', '.pdf', 'image/*', 'image/*,.pdf'\n", " multiple=False # True to accept multiple files upload else False\n", " )" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Ds4z8-ScXaGB" }, "outputs": [], "source": [ "# uploader container\n", "image_container = widgets.VBox(\n", " children = ()\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "Q1YNGSAQXiSt" }, "outputs": [], "source": [ "# wrapper\n", "app = widgets.VBox(\n", " children = (uploader, image_container)\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "xZa0p0n6KVkC" }, "outputs": [], "source": [ "# uploader image content and extension\n", "def get_content_and_extension(uploader): \n", " for _, value in uploader.value.items():\n", " return value['content'], value['metadata']['name'].split('.')[-1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "noQ3fJ27KVhC" }, "outputs": [], "source": [ "# image widget from uploader\n", "def image_widget_from_uploader(uploader):\n", " if uploader.value:\n", " file_content, file_extension = get_content_and_extension(uploader)\n", " return widgets.Image(value=file_content, format=file_extension)\n", " else:\n", " warnings.warn(\"NO IMAGE HAS BEEN UPLOADED\", category=Warning)\n", " return widgets.Image()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# image widget from image numpy\n", "def image_widget_from_numpy(image_numpy, extension):\n", " _, encoded_image = cv2.imencode('.'+extension, image_numpy)\n", " image_bytes = encoded_image.tobytes()\n", " return widgets.Image(value=image_bytes, format=extension)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "BgYf_4GIKVee" }, "outputs": [], "source": [ "# image numpy from uploader\n", "def image_numpy_from_uploader(uploader):\n", " file_content, extension = get_content_and_extension(uploader)\n", " arr_from_buf = np.frombuffer(file_content, np.uint8)\n", " image_numpy = cv2.imdecode(arr_from_buf, cv2.IMREAD_COLOR)\n", " return image_numpy, extension" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "kdAZzmmdKVce" }, "outputs": [], "source": [ "def plotly_image(image_numpy):\n", " if len(np.shape(image_numpy)) == 3 and np.shape(image_numpy)[2] == 3:\n", " fig = px.imshow(image_numpy[...,::-1])\n", " else:\n", " fig = px.imshow(image_numpy, color_continuous_scale='gray')\n", " \n", " layout = go.Layout(\n", " margin=go.layout.Margin(\n", " l=0, #left margin\n", " r=0, #right margin\n", " b=0, #bottom margin\n", " t=0 #top margin\n", " )\n", " )\n", "\n", "# Set dragmode and newshape properties; add modebar buttons\n", " update = fig.update_layout(layout,\n", " dragmode='drawrect',\n", " newshape=dict(line_color='cyan'),\n", "# title_text='Drag to add annotations - use modebar to change drawing tool',\n", " )\n", " config = {\n", " 'modeBarButtonsToAdd': ['drawrect','eraseshape']\n", " }\n", " show = fig.show(config=config)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "image_plotly_container = widgets.VBox(\n", " children = ()\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "h5_path = 'modelcnn.h5'\n", "model = tf.keras.models.load_model(h5_path)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# uploader\n", "annotate_image_uploader = widgets.FileUpload(\n", " accept='image/*', # Accepted file extension e.g. '.txt', '.pdf', 'image/*', 'image/*,.pdf'\n", " multiple=False # True to accept multiple files upload else False\n", " )\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# uploader container\n", "image_annotate_container = widgets.VBox(\n", " children = ()\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# wrapper\n", "app_2 = widgets.VBox(\n", " children = (annotate_image_uploader, image_annotate_container,)\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# uploader image content and extension\n", "def get_content_and_extension(annotate_image_uploader): \n", " for _, value in annotate_image_uploader.value.items():\n", " return value['content'], value['metadata']['name'].split('.')[-1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# image widget from annotate_image_uploader\n", "def image_widget_from_uploader(annotate_image_uploader):\n", " if annotate_image_uploader.value:\n", " file_content, file_extension = get_content_and_extension(annotate_image_uploader)\n", " return widgets.Image(value=file_content, format=file_extension)\n", " else:\n", " warnings.warn(\"NO IMAGE HAS BEEN UPLOADED\", category=Warning)\n", " return widgets.Image()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# image numpy from uploader\n", "def image_numpy_from_uploader(annotate_image_uploader):\n", " file_content, extension = get_content_and_extension(annotate_image_uploader)\n", " arr_from_buf = np.frombuffer(file_content, np.uint8)\n", " image_numpy = cv2.imdecode(arr_from_buf, cv2.IMREAD_COLOR)\n", " return image_numpy, extension" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "qNEGnrGrKVY_" }, "outputs": [], "source": [ "def is_cyan(rgb):\n", " match = False\n", " if((rgb[0]>250) & (rgb[1]>250) & (rgb[2]<5)):\n", " match = True\n", " return match" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "pkgIth9cETvZ" }, "outputs": [], "source": [ "def img_coordinate_1(image_numpy):\n", " x1 = 0 # default, top left\n", " y1 = 0 # default, top left\n", " found = False\n", " \n", " for i in range(len(image_numpy)):\n", " for j in range(len(image_numpy[i])):\n", " if is_cyan(image_numpy[i][j]):\n", " x1 = i\n", " y1 = j\n", " found = True\n", " break\n", " if found:\n", " break\n", " \n", " return x1, y1" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "QBJaYnbtKVVw" }, "outputs": [], "source": [ "def img_coordinate_2(image_numpy):\n", " flip_image = cv2.flip(image_numpy, -1)\n", " x2 = 1 # default, bottom right\n", " y2 = 1 # default, bottom right\n", " found = False\n", " \n", " for i in range(len(flip_image)):\n", " for j in range(len(flip_image[i])):\n", " if is_cyan(flip_image[i][j]):\n", " x2 = i\n", " y2 = j\n", " found = True\n", " break\n", " if found:\n", " break\n", " return x2, y2" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "goLQBYxqK_2k" }, "outputs": [], "source": [ "def img_crop(image_numpy, x1, y1, x2, y2):\n", " cropped_image = image_numpy[x1+4:-x2-4, y1+4:-y2-4]\n", " return cropped_image" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "7I6nm-qfuMfy" }, "outputs": [], "source": [ "def image_reshape(image):\n", " image = cv2.resize(image, (256, 256))\n", " image = cv2.cvtColor(image,cv2.COLOR_GRAY2RGB)\n", " image = image.reshape(-1, 256, 256, 3)\n", " return image" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# def prepro_greyscale(image_numpy):\n", "# return cv2.cvtColor(image_numpy, cv2.COLOR_BGR2GRAY)\n", "\n", "def prepro_clahe(image_numpy, clipLimit=2.0, tileGridSize=8):\n", " image_numpy = cv2.cvtColor(image_numpy, cv2.COLOR_BGR2GRAY)\n", " clahe = cv2.createCLAHE(clipLimit, (tileGridSize, tileGridSize))\n", " return clahe.apply(image_numpy)\n", "\n", "def prepro_resize(image_numpy,resize_w=256,resize_l=256):\n", " return cv2.resize(image_numpy,(resize_w,resize_l))\n", "\n", "def prepro_normalize(image_numpy,resize_w=256,resize_l=256):\n", " out_arr = np.zeros((resize_w,resize_l))\n", " return cv2.normalize(image_numpy, out_arr, 0, 255, cv2.NORM_MINMAX)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "FvPHhY9ELZDX" }, "outputs": [], "source": [ "def predicted_image(img_reshape_2, model):\n", "# model = model(input_shape= (32,32,1))\n", " result = model.predict(img_reshape_2)\n", " if result.any() == 0:\n", " prediction = 'NORMAL'\n", " else:\n", " prediction = 'KANKER'\n", "\n", " # prediction = print(prediction)\n", " result = ' ' + str(prediction) + ' '\n", " return result" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "text_result = widgets.Label(value=\"Result will be shown here!\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "text = widgets.VBox(\n", " children = ([text_result]), layout=Layout(\n", " display='flex',\n", " flex_flow='column',\n", " border='solid 2px',\n", " align_items='stretch',\n", " ))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# uploader container\n", "text_container = widgets.VBox(\n", " children = (text,)\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "form_item_layout = Layout(\n", " display='flex',\n", " flex_flow='row',\n", " justify_content='space-between'\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "w9rcp2qzK_vx" }, "outputs": [], "source": [ "# label\n", "label_current_thread = widgets.Label()\n", "label_thread_list = widgets.Label()\n", "\n", "# button \n", "button_stop = widgets.Button(\n", " description = 'stop',\n", " icon = 'fa-stop',\n", " button_style = 'warning',\n", " layout = widgets.Layout(width='100px')\n", ")\n", "def button_stop_click(self):\n", " global thread_status\n", " thread_status = False\n", "button_stop.on_click(button_stop_click)\n", "\n", "button_check_thread = widgets.Button(\n", " description = 'check thread',\n", " button_style = '',\n", " layout = widgets.Layout(width='100px')\n", ")\n", "def button_check_thread_click(self):\n", " # print if work() still running\n", " work_count = 0\n", " name='work'\n", " for thread_object in threading.enumerate():\n", " if thread_object.name == name:\n", " work_count+=1\n", " if work_count > 0:\n", " label_thread_list.value=f'{work_count} thread with name {name} still exist. Consider use exit() and restart kernel'\n", " else:\n", " label_thread_list.value=f'No thread with name {name} exist'\n", "button_check_thread.on_click(button_check_thread_click)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "ga0hso1CK_sG" }, "outputs": [], "source": [ "# main loop\n", "def work():\n", " global thread_status\n", " global model\n", " global image_numpy\n", " global rgb\n", " global img_reshape_2\n", " \n", " if thread_status:\n", " label_current_thread.value = 'Thread On'\n", "\n", " current_state = [uploader.value]\n", " current_state_2 = [annotate_image_uploader.value]\n", " \n", " while thread_status:\n", " \n", " # check if there is a change in uploader.value\n", " if current_state != [uploader.value]:\n", " \n", " # renew state reference\n", " current_state = [uploader.value]\n", " \n", " # image widget from uploader\n", " image_widget_raw = image_widget_from_uploader(uploader)\n", " \n", " # renew container_raw\n", " image_container.children = (image_widget_raw,)\n", "\n", " # read image numpy\n", " image_numpy, extension = image_numpy_from_uploader(uploader)\n", " \n", " # plotly\n", " plotly_image(image_numpy)\n", " \n", " # check if there is a change in uploader.value\n", " if current_state_2 !=[annotate_image_uploader.value]:\n", " \n", " # Preprocessing message\n", " text_result.value = 'Preprocessing...'\n", " text.children = (text_result,)\n", " if text_result.value:\n", " text_container.children = (text,)\n", " \n", " # renew state reference\n", " current_state_2 = [annotate_image_uploader.value] \n", " \n", " image_widget_annotate = image_widget_from_uploader(annotate_image_uploader)\n", " \n", " image_numpy, extension = image_numpy_from_uploader(annotate_image_uploader)\n", " \n", " # preprocess and predict\n", " x1, y1 = img_coordinate_1(image_numpy)\n", " x2, y2 = img_coordinate_2(image_numpy)\n", "\n", " image_numpy = img_crop(image_numpy, x1, y1, x2, y2)\n", " \n", " image_numpy = prepro_clahe(image_numpy)\n", "\n", " image_numpy = prepro_resize(image_numpy)\n", "\n", " image_numpy = prepro_normalize(image_numpy)\n", " \n", " image_numpy_widget = image_widget_from_numpy(image_numpy, extension)\n", " \n", " image_numpy = image_reshape(image_numpy)\n", " \n", " image_annotate_container.children = (image_numpy_widget,)\n", " \n", " # Predict message message\n", " text_result.value = 'Predicting...'\n", " text.children = (text_result,)\n", " if text_result.value:\n", " text_container.children = (text,)\n", " \n", " text_result.value = predicted_image(image_numpy, model)\n", " text.children = (text_result,)\n", " if text_result.value:\n", " text_container.children = (text,)\n", " \n", " # sleep for threading\n", " time.sleep(0.05)\n", " \n", " if not thread_status:\n", " label_current_thread.value = 'Thread Off'" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "9ZL5z-XrZ_06" }, "outputs": [], "source": [ "# restart flag\n", "thread_status = False \n", "thread_status = True\n", "\n", "# create thread\n", "thread_work = threading.Thread(target=work)\n", "thread_work.name = 'work'\n", "\n", "# start thread\n", "thread_work.start()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Box([Label(value='Upload Mammography'), app], layout=form_item_layout)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Box([Label(value='Upload Annotate Image'), app_2], layout=form_item_layout)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Box([Label(value='Result'), text_container], layout=form_item_layout)" ] } ], "metadata": { "colab": { "collapsed_sections": [], "name": "cnn web 2.ipynb", "provenance": [] }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.7" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "915634932fd0483fb4227831f312235f": { "model_module": "@jupyter-widgets/controls", "model_name": "FileUploadModel", "state": { "_counter": 0, "_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "FileUploadModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "1.5.0", "_view_name": "FileUploadView", "accept": "image/*", "button_style": "", "data": [], "description": "Upload", "description_tooltip": null, "disabled": false, "error": "", "icon": "upload", "layout": "IPY_MODEL_c8e9cde3226c46a7bc0eee77bee52b08", "metadata": [], "multiple": false, "style": "IPY_MODEL_b84a7ad88c984bb9b03221b99bbcfb63" } }, "b84a7ad88c984bb9b03221b99bbcfb63": { "model_module": "@jupyter-widgets/controls", "model_name": "ButtonStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "ButtonStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "StyleView", "button_color": null, "font_weight": "" } }, "c8e9cde3226c46a7bc0eee77bee52b08": { "model_module": "@jupyter-widgets/base", "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null } } } } }, "nbformat": 4, "nbformat_minor": 1 }