{"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":"# Introduction\n\nHere, I am going to crop leaf image using Canny edge detection on Plant pathology competion images.<br>\nI hope croping leaf from original image and, train model on it will increase overall metric scores.<br>\nBellow is the notebook that I refered to. You should check this since it's very helpful and interesting !!<br>\nhttps://www.kaggle.com/tarunpaparaju/plant-pathology-2020-eda-models#Image-processing-and-augmentation-\n<br>\n\nContents of this notebook is as follows\n1. What is Canny edge detection\n2. Understanding images in Plant pathology competion\n3. How to crop leaf from original image using Canny detection","metadata":{}},{"cell_type":"markdown","source":"# What is Canny edge detection?\n Canny Edge Detection is a popular edge detection algorithm. It is often used in image processing.<br>\n We can crop the area of leaf for image in plant pathology competion, since images contains only single leaf and background.<br>\n See bellow for detail in algorithm of Canny Edge detection.<br>\n https://docs.opencv.org/master/da/d22/tutorial_py_canny.html","metadata":{}},{"cell_type":"markdown","source":"# Understanding images in Plant pathology competion\nFirst we load dataPILnd see the distribution of labels and show a few images.<br>\nAfter preform statistical anaysis on dataset.","metadata":{}},{"cell_type":"markdown","source":"## Imports","metadata":{}},{"cell_type":"code","source":"import os\nimport glob\nimport math\nimport json\n\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport matplotlib.gridspec as gridspec\nimport cv2","metadata":{"execution":{"iopub.status.busy":"2021-08-03T22:16:52.445948Z","iopub.execute_input":"2021-08-03T22:16:52.446576Z","iopub.status.idle":"2021-08-03T22:16:53.507457Z","shell.execute_reply.started":"2021-08-03T22:16:52.446488Z","shell.execute_reply":"2021-08-03T22:16:53.50633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load data","metadata":{}},{"cell_type":"code","source":"BASE_DIR = \"../input/plant-pathology-2021-fgvc8\"","metadata":{"execution":{"iopub.status.busy":"2021-08-03T22:16:53.508922Z","iopub.execute_input":"2021-08-03T22:16:53.509228Z","iopub.status.idle":"2021-08-03T22:16:53.513274Z","shell.execute_reply.started":"2021-08-03T22:16:53.509188Z","shell.execute_reply":"2021-08-03T22:16:53.512206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Training data image path and label\ntrain_image_path = glob.glob(os.path.join(BASE_DIR, \"train_images/*.jpg\"))\nlabel_df = pd.read_csv(os.path.join(BASE_DIR, \"train.csv\"))\n\n# Diplay number of images and label dataframe\nprint(\"Number of training images: {}\".format(len(train_image_path)))\ndisplay(label_df.head(10))","metadata":{"execution":{"iopub.status.busy":"2021-08-03T22:16:53.515463Z","iopub.execute_input":"2021-08-03T22:16:53.515977Z","iopub.status.idle":"2021-08-03T22:16:53.987356Z","shell.execute_reply.started":"2021-08-03T22:16:53.515934Z","shell.execute_reply":"2021-08-03T22:16:53.986331Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Long label name is included such as \"scab frog_eye_leaf_spot complex\".<br>\nImage that has multible labels. We are going to see those images later","metadata":{}},{"cell_type":"markdown","source":"## Label distribution","metadata":{}},{"cell_type":"code","source":"# Count number of labels\nlabel_count = pd.DataFrame(label_df.labels.value_counts())\nlabel_count[\"proportion\"] = label_count / len(label_df) * 100\ndisplay(label_count)","metadata":{"execution":{"iopub.status.busy":"2021-08-03T22:39:13.357221Z","iopub.execute_input":"2021-08-03T22:39:13.357721Z","iopub.status.idle":"2021-08-03T22:39:13.397649Z","shell.execute_reply.started":"2021-08-03T22:39:13.357674Z","shell.execute_reply":"2021-08-03T22:39:13.396741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Show distribution for label by bar graph and pie chart \nfig, ax = plt.subplots(nrows=1, ncols=2, figsize=(20, 6))\nlabel_count[\"labels\"].plot.bar(ax=ax[0], title=\"Number of data per label\", rot=90, fontsize=15)\nlabel_count[\"proportion\"].plot.pie(ax=ax[1], title=\"Ratio of label\", autopct='%1.1f%%', fontsize=15)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-01T23:43:31.191246Z","iopub.execute_input":"2021-08-01T23:43:31.191728Z","iopub.status.idle":"2021-08-01T23:43:31.72463Z","shell.execute_reply.started":"2021-08-01T23:43:31.191654Z","shell.execute_reply":"2021-08-01T23:43:31.723704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"From above label distribution we could see bellow <br>\n1. Main categories are bellow<br>\n    - Healthy\n    - Scab\n    - Frog_eye_leaf_spot\n    - Rust\n    - Powdery_mildew\n    - Complex\n    - Multiple label of above\n2. Mixed labels consists of 20% of total","metadata":{}},{"cell_type":"markdown","source":"## Show few images\nWe have seen label distribution of images at former section. Here I am showing a few images for each label.","metadata":{}},{"cell_type":"code","source":"display_image_num = 9\n\nfor label in label_count.index:\n    df_tmp = label_df[label_df.labels == label]\n    image_file_names = df_tmp.sample(display_image_num).image.values\n    images = [os.path.join(BASE_DIR, \"train_images/\", file_name) for file_name in image_file_names]\n    \n    # Show 3X3 images per each label\n    plt.figure(figsize=(15, 15))\n    for idx, image in enumerate(images):\n        plt.subplot(math.ceil(display_image_num / 3), 3, idx + 1)\n        im = plt.imread(image)\n        plt.imshow(im)\n    print(\"\\n==================== Label:{} ===================\".format(label))\n    plt.tight_layout()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-01T23:43:31.725906Z","iopub.execute_input":"2021-08-01T23:43:31.726218Z","iopub.status.idle":"2021-08-01T23:46:01.77111Z","shell.execute_reply.started":"2021-08-01T23:43:31.726189Z","shell.execute_reply":"2021-08-01T23:46:01.76995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"From images we can see bellow\n- “complex” is leaves with too many diseases to classify (Mentioned in official discription)\n- Labels \"frog_eye_leaf_spot\", \"rust\", \"powdery_mildew\" seems easy to identify\n- “scab” seems difficult to identify spots<br>\n    -> Consider applying filter to emphasize scab","metadata":{}},{"cell_type":"markdown","source":"## Statistical analysis on image data\nHere we statisticaly analyze image data to get insight on image pattern.","metadata":{}},{"cell_type":"markdown","source":"## Image size distribution\nImage size is important because we need to resize all the image to same size in order to train model.","metadata":{}},{"cell_type":"code","source":"# Get image size\nimage_property = {\"image\": [], \"width\": [], \"height\": []}\nfor image_path in train_image_path:\n    im = Image.open(image_path)\n    width, height = im.size\n    file_name = os.path.basename(image_path)\n    image_property[\"image\"].append(file_name)\n    image_property[\"width\"].append(width)\n    image_property[\"height\"].append(height)","metadata":{"execution":{"iopub.status.busy":"2021-08-01T23:46:01.772879Z","iopub.execute_input":"2021-08-01T23:46:01.773222Z","iopub.status.idle":"2021-08-01T23:51:35.956257Z","shell.execute_reply.started":"2021-08-01T23:46:01.773188Z","shell.execute_reply":"2021-08-01T23:51:35.953823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Merge width, height info with label data\nimage_size = pd.DataFrame(image_property)\nimage_size = pd.merge(image_size, label_df, on=\"image\", how=\"outer\")\ndisplay(image_size.head())\ndisplay(image_size.info())","metadata":{"execution":{"iopub.status.busy":"2021-08-01T23:51:35.962543Z","iopub.execute_input":"2021-08-01T23:51:35.963012Z","iopub.status.idle":"2021-08-01T23:51:36.076534Z","shell.execute_reply.started":"2021-08-01T23:51:35.962971Z","shell.execute_reply":"2021-08-01T23:51:36.075089Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Plot (width, height) pair\nimage_size.plot(x=\"width\", y=\"height\", linestyle=\"none\", marker = \"x\")","metadata":{"execution":{"iopub.status.busy":"2021-08-01T23:51:36.078741Z","iopub.execute_input":"2021-08-01T23:51:36.07908Z","iopub.status.idle":"2021-08-01T23:51:36.283238Z","shell.execute_reply.started":"2021-08-01T23:51:36.07905Z","shell.execute_reply":"2021-08-01T23:51:36.282129Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Count value pair for (width, height)\nimage_size.groupby([\"width\", \"height\"]).count()","metadata":{"execution":{"iopub.status.busy":"2021-08-01T23:51:36.284576Z","iopub.execute_input":"2021-08-01T23:51:36.284863Z","iopub.status.idle":"2021-08-01T23:51:36.307026Z","shell.execute_reply.started":"2021-08-01T23:51:36.284836Z","shell.execute_reply":"2021-08-01T23:51:36.306134Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can see\n- All the images do not have the same size.\n- There are 9 types of images size\n- 4000X2672 is the most popular size","metadata":{}},{"cell_type":"markdown","source":"### Analysis on single image\nLet's take a look at single image and see the pixel value distribution to get an insight.","metadata":{}},{"cell_type":"code","source":"# Sampling image to analayse\nidx = 2399 # Randomly selected index\nimg_path, label = label_df.iloc[idx].values\nimg_path = os.path.join(BASE_DIR, \"train_images/\", img_path)\nimg_sample = plt.imread(img_path)\nprint(\"Array shape: {}\".format(img_sample.shape))\nplt.imshow(img_sample)\nplt.title(label)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-01T23:51:36.308463Z","iopub.execute_input":"2021-08-01T23:51:36.308924Z","iopub.status.idle":"2021-08-01T23:51:37.637702Z","shell.execute_reply.started":"2021-08-01T23:51:36.308883Z","shell.execute_reply":"2021-08-01T23:51:37.636752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Extract RGB channel\nred_channel   = img_sample[:,:,0].flatten()\ngreen_channel = img_sample[:,:,1].flatten()\nblue_channel  = img_sample[:,:,2].flatten()\nprint(\"red_channel shape: {}\".format(red_channel.shape))\nprint(\"green_channel shape: {}\".format(green_channel.shape))\nprint(\"blue_channel shape: {}\".format(blue_channel.shape))","metadata":{"execution":{"iopub.status.busy":"2021-08-01T23:51:37.638984Z","iopub.execute_input":"2021-08-01T23:51:37.639276Z","iopub.status.idle":"2021-08-01T23:51:37.66632Z","shell.execute_reply.started":"2021-08-01T23:51:37.639247Z","shell.execute_reply":"2021-08-01T23:51:37.664753Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Show distribution for each channel\ny_min, y_max = 0., 0.018\nplt.figure(figsize=(20,4))\nplt.subplot(1,3,1)\nplt.hist(red_channel,bins=50, color=\"red\", alpha=0.3, density=True)\nplt.title(\"Red channel distribution\")\nplt.ylim([y_min, y_max])\n\nplt.subplot(1,3,2)\nplt.hist(green_channel,bins=50, color=\"green\", alpha=0.3, density=True)\nplt.title(\"Green channel distribution\")\nplt.ylim([y_min, y_max])\n\nplt.subplot(1,3,3)\nplt.hist(blue_channel,bins=50, color=\"blue\", alpha=0.3, density=True)\nplt.title(\"Blue channel distribution\")\nplt.ylim([y_min, y_max])\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-01T23:51:37.668491Z","iopub.execute_input":"2021-08-01T23:51:37.669114Z","iopub.status.idle":"2021-08-01T23:51:39.168054Z","shell.execute_reply.started":"2021-08-01T23:51:37.66906Z","shell.execute_reply":"2021-08-01T23:51:39.1669Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# View all channel together\nplt.hist(red_channel,bins=50, color=\"red\", alpha=0.3, density=True)\nplt.hist(green_channel,bins=50, color=\"green\", alpha=0.3, density=True)\nplt.hist(blue_channel,bins=50, color=\"blue\", alpha=0.3, density=True)\nplt.ylim([y_min, y_max])\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-01T23:51:39.169442Z","iopub.execute_input":"2021-08-01T23:51:39.169771Z","iopub.status.idle":"2021-08-01T23:51:40.180989Z","shell.execute_reply.started":"2021-08-01T23:51:39.16974Z","shell.execute_reply":"2021-08-01T23:51:40.179928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"From the distribution from above we can see<br>\n1. Green channel has larger density overall\n2. Green channel is dense around value 250\n3. Red and Blue channel has similar distribution\n<br>\n\nThe fact that green channel has high density is consistent to tha fact that, images we are handling is leaf therefore contains a lot of green pixles.","metadata":{}},{"cell_type":"markdown","source":"### Analysis on entire image\nHere we analyze pixel values dependencies for each label.<br>\nSince there are only a few images with multiple labels, we only analyze images with labels bellow<br>\n\"scab\", \"healthy\", \"frog_eye_leaf_spot\", \"rust\", \"complex\", \"powdery_mildew\"<br>\n\nSteps to analyze are as follows\n1. Extract images with certain label\n2. Calculate mean value of red, green, blue channel for each image\n3. Plot RGB mean values distribution for certain label images\n4. Repeat 1. to 3. for all 6 labels","metadata":{}},{"cell_type":"code","source":"lables_to_analyze = [\"scab\", \"healthy\", \"frog_eye_leaf_spot\", \"rust\", \"complex\", \"powdery_mildew\"]","metadata":{"execution":{"iopub.status.busy":"2021-08-03T23:06:24.689145Z","iopub.execute_input":"2021-08-03T23:06:24.689539Z","iopub.status.idle":"2021-08-03T23:06:24.694749Z","shell.execute_reply.started":"2021-08-03T23:06:24.689508Z","shell.execute_reply":"2021-08-03T23:06:24.693494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"results = dict((key, None) for key in lables_to_analyze)\n\nfor label in lables_to_analyze:\n    # File name with certain label\n    df_tmp = label_df[label_df[\"labels\"]==label]\n    image_file_names = df_tmp.image.values\n    images = [os.path.join(BASE_DIR, \"train_images/\", file_name) for file_name in image_file_names]\n    \n    rc_mean, gc_mean, bc_mean = [], [], []\n    for image in images:\n        im = plt.imread(image)\n        rc_mean.append(im[:,:,0].flatten().mean())\n        gc_mean.append(im[:,:,1].flatten().mean())\n        bc_mean.append(im[:,:,2].flatten().mean())\n    results[label] = {\n        \"r\": rc_mean,\n        \"g\": gc_mean,\n        \"b\": bc_mean\n    }","metadata":{"execution":{"iopub.status.busy":"2021-08-03T23:06:27.193048Z","iopub.execute_input":"2021-08-03T23:06:27.19347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert calculated result to DataFrame\nlabels = list(results.keys())\ndf_list = {}\n\nfor label in labels:\n    data_array = np.array([\n        results[label][\"r\"],\n        results[label][\"g\"],\n        results[label][\"b\"]]).T\n    df_list[label] = pd.DataFrame(\n        data_array, columns=[\"r\", \"g\", \"b\"])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Plot mean RGB distribution for each label\nplt.figure(figsize=(8, 20))\ngs = gridspec.GridSpec(len(labels), 1)\nfor idx, label in enumerate(labels):\n    ax = plt.subplot(gs[idx])\n    \n    df_plot = df_list[label]\n    sns.distplot(df_plot[\"r\"],bins=10, color='crimson')\n    sns.distplot(df_plot[\"b\"],bins=10, color='royalblue')\n    sns.distplot(df_plot[\"g\"],bins=10, color='green')\n    ax.set_xlabel(None)\n    ax.set_title(label, loc='left')\n    ax.legend([\"Red\", \"Blue\", \"Green\"])\n    ax.set_xlim([0, 255])\n    ax.set_ylim([0, 0.05]) ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"From the graphs above we can see that \"rust\" images have realtively flat distribution.<br>\nAlso, \"frog_eye_leaf_spot\", \"complex\", \"powdery_mildew\" has sharp distribution.<br>\nWe categorized the shape of distribution bellow<br>\n- Sharp distribution:<br>\n    \"frog_eye_leaf_spot\", \"complex\", \"powdery_mildew\"\n- Intermediate distribution: <br>\n    \"scab\", \"health\"\n- Wide distribution:　<br>\n    \"rust\"\n    \nImages with simillar distribution may be difficult to identify each other.","metadata":{}},{"cell_type":"markdown","source":"# Crop leaf from original image using Canny detection","metadata":{}},{"cell_type":"markdown","source":"## Apply canny edge detection on single image\n\nFirst of all I will show hot to perform canny edge detection on single image.<br>\nAlso, I will crop leaf part from the entire image.","metadata":{}},{"cell_type":"code","source":"# Extract image for edge detecting sample. (No meaning in index number that is hard coded.)\nsample_index = 2344\nfile_name = label_df.iloc[sample_index][\"image\"]\nsample_img_path = os.path.join(BASE_DIR, \"train_images/\", file_name)\nsample_img = plt.imread(sample_img_path)\n\nplt.imshow(sample_img)","metadata":{"execution":{"iopub.status.busy":"2021-08-02T23:01:27.850654Z","iopub.execute_input":"2021-08-02T23:01:27.851217Z","iopub.status.idle":"2021-08-02T23:01:29.435587Z","shell.execute_reply.started":"2021-08-02T23:01:27.85118Z","shell.execute_reply":"2021-08-02T23:01:29.43431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Apply Cany edge detection\nsample_img_edge1 = cv2.Canny(sample_img, 5, 200)\nprint(sample_img_edge1.shape)\nplt.imshow(sample_img_edge1, cmap=\"gray\")","metadata":{"execution":{"iopub.status.busy":"2021-08-02T00:56:32.435529Z","iopub.execute_input":"2021-08-02T00:56:32.436167Z","iopub.status.idle":"2021-08-02T00:56:33.937201Z","shell.execute_reply.started":"2021-08-02T00:56:32.43612Z","shell.execute_reply":"2021-08-02T00:56:33.93577Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Spot shown in figure above is the pixel where edge is present.<br>\nWe crop leaf image by finding min and max coordinate in X and Y axis.","metadata":{}},{"cell_type":"code","source":"# Crop leaf image from edge detected image\n# Extracting boundary box\ny_idxs, x_idxs = np.where(sample_img_edge1 > 0)\nx_min, x_max = x_idxs.min(), x_idxs.max()\ny_min, y_max = y_idxs.min(), y_idxs.max()\n\n# Add boundary to original image\nimg_with_boundary = sample_img.copy()\nline_size = 10\n\n# Vertical boundary (Left)\nimg_with_boundary[y_min:y_max, x_min-line_size:x_min+line_size, 0] = 255\n# Vertical boundary (Right)\nimg_with_boundary[y_min:y_max, x_max-line_size:x_max+line_size, 0] = 255\n# Horizontal boundary (Lower)\nimg_with_boundary[y_min-line_size:y_min+line_size, x_min:x_max, 0] = 255\n# Vertical boundary (Upper)\nimg_with_boundary[y_max-line_size:y_max+line_size, x_min:x_max, 0] = 255\n\nplt.figure(figsize=(15, 4))\nplt.subplot(121)\nplt.imshow(img_with_boundary)\nplt.title(\"Leaf image with bounding box\")\nplt.subplot(122)\nplt.imshow(img_with_boundary[y_min:y_max, x_min:x_max])\nplt.title(\"Croped leaf image\")","metadata":{"execution":{"iopub.status.busy":"2021-08-02T00:56:33.939066Z","iopub.execute_input":"2021-08-02T00:56:33.939486Z","iopub.status.idle":"2021-08-02T00:56:36.088723Z","shell.execute_reply.started":"2021-08-02T00:56:33.939441Z","shell.execute_reply":"2021-08-02T00:56:36.087842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Not a good croping though the leaf is foucused.<br>\n\nCany edge detection requires min and max threshold for detecting.<br>\nWe need to find best values since this affects detection result.<br>\nLet's start with defining function to crop image.","metadata":{}},{"cell_type":"code","source":"def get_boundary(img, min_thresh, max_thresh):\n    edge_image = cv2.Canny(img, min_thresh, max_thresh)\n    y_idxs, x_idxs = np.where(edge_image > 0)\n    x_min, x_max = x_idxs.min(), x_idxs.max()\n    y_min, y_max = y_idxs.min(), y_idxs.max()\n    return x_min, x_max, y_min, y_max\n\ndef get_image_with_boundary(img, x_min, x_max, y_min, y_max):\n    img_with_boundary = img.copy()\n    line_size = 10\n    \n    # Vertical boundary (Left)\n    img_with_boundary[y_min:y_max, x_min-line_size:x_min+line_size, 0] = 255\n    # Vertical boundary (Right)\n    img_with_boundary[y_min:y_max, x_max-line_size:x_max+line_size, 0] = 255\n    # Horizontal boundary (Lower)\n    img_with_boundary[y_min-line_size:y_min+line_size, x_min:x_max, 0] = 255\n    # Vertical boundary (Upper)\n    img_with_boundary[y_max-line_size:y_max+line_size, x_min:x_max, 0] = 255\n    \n    return img_with_boundary\n\ndef get_and_plot_image_with_boundary(img, min_thresh, max_thresh):\n    x_min, x_max, y_min, y_max = get_boundary(img, min_thresh, max_thresh)\n    img_with_boundary = get_image_with_boundary(img, x_min, x_max, y_min, y_max)\n    plt.imshow(img_with_boundary)","metadata":{"execution":{"iopub.status.busy":"2021-08-03T22:39:29.882621Z","iopub.execute_input":"2021-08-03T22:39:29.883146Z","iopub.status.idle":"2021-08-03T22:39:29.892498Z","shell.execute_reply.started":"2021-08-03T22:39:29.883112Z","shell.execute_reply":"2021-08-03T22:39:29.891739Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Perform edge detection with various threshold\nplt.figure(figsize=(15,6))\n\n# minThresh=5, maxThresh=200\nplt.subplot(2,3,1)\nget_and_plot_image_with_boundary(sample_img, 5, 200)\nplt.title(\"minThresh=5, maxThresh=200\")\n\n# minThresh=50, maxThresh=200\nplt.subplot(2,3,2)\nget_and_plot_image_with_boundary(sample_img, 50, 200)\nplt.title(\"minThresh=50, maxThresh=200\")\n\n# minThresh=100, maxThresh=200\nplt.subplot(2,3,3)\nget_and_plot_image_with_boundary(sample_img, 100, 200)\nplt.title(\"minThresh=100, maxThresh=200\")\n\n# minThresh=5, maxThresh=100\nplt.subplot(2,3,4)\nget_and_plot_image_with_boundary(sample_img, 5, 100)\nplt.title(\"minThresh=5, maxThresh=100\")\n\n# minThresh=30, maxThresh=100\nplt.subplot(2,3,5)\nget_and_plot_image_with_boundary(sample_img, 30, 100)\nplt.title(\"minThresh=30, maxThresh=100\")\n\n# minThresh=50, maxThresh=100\nplt.subplot(2,3,6)\nget_and_plot_image_with_boundary(sample_img, 50, 100)\nplt.title(\"minThresh=50, maxThresh=100\")\n\nplt.tight_layout()","metadata":{"execution":{"iopub.status.busy":"2021-08-02T23:05:28.577992Z","iopub.execute_input":"2021-08-02T23:05:28.578416Z","iopub.status.idle":"2021-08-02T23:05:36.440021Z","shell.execute_reply.started":"2021-08-02T23:05:28.578378Z","shell.execute_reply":"2021-08-02T23:05:36.439062Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"With threshold range is bellow 100 (images at 2nd row), entire image has been croped which is meaningless.<br>\nWith threshold range is bellow 200 (images at 1st row), leaf part is croped but no big differnece with each other.<br>\nNext we are going to see how minThresh, maxThresh affects cropping.","metadata":{}},{"cell_type":"markdown","source":"## Crop leaf from image\n\nNow that we sawa how to perform Canny edge detection and crop leaf on a single image,<br>\nwe are going to apply it for other images.","metadata":{}},{"cell_type":"code","source":"# Sample images\nsample_image = {}\nfor label in label_count.index:\n    df_tmp = label_df[label_df.labels == label]\n    image_file_names = df_tmp.sample(display_image_num).image.values\n    images = [os.path.join(BASE_DIR, \"train_images/\", file_name) for file_name in image_file_names]\n    sample_image[label] = images","metadata":{"execution":{"iopub.status.busy":"2021-08-03T22:43:01.64498Z","iopub.execute_input":"2021-08-03T22:43:01.645741Z","iopub.status.idle":"2021-08-03T22:43:01.699844Z","shell.execute_reply.started":"2021-08-03T22:43:01.645671Z","shell.execute_reply":"2021-08-03T22:43:01.698727Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function to plot croped image \ndef show_3x3_images(image_dict, min_thresh=100, max_thresh=200):\n    display_image_num = 9\n    for label, images in sample_image.items():\n        # Show 3X3 images per each label\n        plt.figure(figsize=(15, 8))\n        for idx, image in enumerate(images):\n            plt.subplot(math.ceil(display_image_num / 3), 3, idx + 1)\n            img = plt.imread(image)\n            get_and_plot_image_with_boundary(img, min_thresh, max_thresh)\n        print(\"\\n==================== Label:{} ===================\".format(label))\n        plt.tight_layout()\n        plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-08-03T22:46:25.551479Z","iopub.execute_input":"2021-08-03T22:46:25.551876Z","iopub.status.idle":"2021-08-03T22:46:25.559151Z","shell.execute_reply.started":"2021-08-03T22:46:25.551837Z","shell.execute_reply":"2021-08-03T22:46:25.558172Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We show the coroped images with different threshold.<br>\nWe could not find wich threshold might be the best, however we could croped leaf part from most of the images.<br>\nI hope cropping images before applying to machine learning model would increase performance.","metadata":{}},{"cell_type":"code","source":"show_3x3_images(sample_image, 5, 200)","metadata":{"execution":{"iopub.status.busy":"2021-08-03T22:49:45.264523Z","iopub.execute_input":"2021-08-03T22:49:45.264908Z","iopub.status.idle":"2021-08-03T22:52:01.461484Z","shell.execute_reply.started":"2021-08-03T22:49:45.264877Z","shell.execute_reply":"2021-08-03T22:52:01.460438Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_3x3_images(sample_image, 50, 200)","metadata":{"execution":{"iopub.status.busy":"2021-08-03T22:52:01.463318Z","iopub.execute_input":"2021-08-03T22:52:01.464028Z","iopub.status.idle":"2021-08-03T22:54:12.895794Z","shell.execute_reply.started":"2021-08-03T22:52:01.463982Z","shell.execute_reply":"2021-08-03T22:54:12.894778Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_3x3_images(sample_image, 100, 200)","metadata":{"execution":{"iopub.status.busy":"2021-08-03T22:46:48.194027Z","iopub.execute_input":"2021-08-03T22:46:48.194586Z","iopub.status.idle":"2021-08-03T22:49:01.328749Z","shell.execute_reply.started":"2021-08-03T22:46:48.194536Z","shell.execute_reply":"2021-08-03T22:49:01.327526Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}