-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c19a828
commit 0e368aa
Showing
1 changed file
with
207 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"\"\"\"importing the necessary libraries, numpy for handling the mathematical complexities\n", | ||
"cv2 - OpenCV, for contouring the image and classifying the data points based on colour differences\"\"\"\n", | ||
"\n", | ||
"import cv2\n", | ||
"import numpy as np\n", | ||
"import matplotlib.pyplot as plt" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"#loading the test image to an image variable\n", | ||
"#this part of the code will be changed dynamically to accept images loaded on the RPi\n", | ||
"\n", | ||
"img = cv2.imread(\"/home/siddhant/Pictures/leaf.jpg\", cv2.IMREAD_COLOR)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 4, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"#function to display the image since the process is tedious with multiple lines of code for compatibility in Jupyter Notebooks\n", | ||
"# the kernel will stop working if you simply close an image, you have to press a random key on the keyboard to successfully close the image file\n", | ||
"# opened after this function is executed\n", | ||
"\n", | ||
"def show(img, title=\"img\"):\n", | ||
" cv2.imshow(title, img)\n", | ||
" cv2.waitKey()\n", | ||
" cv2.destroyAllWindows()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 5, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# converting image to gray scale for easy colour segregation\n", | ||
"gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n", | ||
"\n", | ||
"# blur the image to reduce noise as it makes the contouring more accurate. \n", | ||
"blur = cv2.blur(gray, (3, 3))\n", | ||
"\n", | ||
"# binary thresholding of the image. Changes the image into all black or all white and no gray-spots in between.\n", | ||
"# colours closer to black turn complete black and likewise with white\n", | ||
"\n", | ||
"THRESH_VAL = 220 # variable\n", | ||
"ret, thresh = cv2.threshold(blur, THRESH_VAL, 255, cv2.THRESH_BINARY)\n", | ||
"\n", | ||
"show(thresh, title=\"Thresholded Image\")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 6, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# find contours\n", | ||
"# finds a set of joined points around the black and white image borders. Helps in segmentation and auto-selection of parts of the image\n", | ||
"\n", | ||
"contours, hierarchy = cv2.findContours(thresh, \n", | ||
" cv2.RETR_TREE, \n", | ||
" cv2.CHAIN_APPROX_SIMPLE)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 7, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"Length of contours: 17\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"# number of contour arrays, there are 17 arrays in this particular test image\n", | ||
"\n", | ||
"print(\"Length of contours: {}\".format(len(contours)))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 8, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# here we use numpy to draw an image. This is a part I don't quite understand myself enough to document correctly, but it creates a bitmap image.\n", | ||
"# this created image is later filled with the contours we stored in the variable earlier to draw a blueprint of the image parts we're interested in\n", | ||
"\n", | ||
"drawing = np.zeros((thresh.shape[0], thresh.shape[1], 3), np.uint8)\n", | ||
"color_contours = (0, 255, 0) # color for contours\n", | ||
"for i in range(len(contours)):\n", | ||
" cv2.drawContours(drawing, contours, i, color_contours, 2, 8, hierarchy)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 9, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"show(drawing, title='Contours')" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 10, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"Finally: max_x = 1220, max_y = 766\n", | ||
"Finally: min_x = 48, min_y = 92\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"# The important part, here we run two simple loops to find the maximum and minimum distance from the length and the width axes respectively\n", | ||
"# The max and min are recorded after being compared to every single element of the contour array\n", | ||
"\n", | ||
"max_x = 0\n", | ||
"max_y = 0\n", | ||
"min_x = thresh.shape[1]\n", | ||
"min_y = thresh.shape[0]\n", | ||
"\n", | ||
"for i in range(len(contours)):\n", | ||
" # print(\"Finding for: \", contours[i])\n", | ||
" for j in contours[i]:\n", | ||
" if(j[0][0] > max_x and j[0][0] < 1250):\n", | ||
" max_x = j[0][0]\n", | ||
" if(j[0][1] > max_y and j[0][1] < 850):\n", | ||
" max_y = j[0][1]\n", | ||
" if(j[0][0] < min_x and j[0][0] > 10):\n", | ||
" min_x = j[0][0]\n", | ||
" if(j[0][1] < min_y and j[0][1] > 10):\n", | ||
" min_y = j[0][1]\n", | ||
" \n", | ||
"print(\"Finally: max_x = {}, max_y = {}\".format(max_x, max_y))\n", | ||
"print(\"Finally: min_x = {}, min_y = {}\".format(min_x, min_y))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 11, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"Length 1172\n", | ||
"Width: 674\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"# Naturally the length and width of the leaf are the difference between the points of min and max.\n", | ||
"\n", | ||
"print(f'Length {max_x - min_x}')\n", | ||
"print(\"Width: {}\".format(max_y - min_y))\n", | ||
"\n", | ||
"# These values will be sent to a code further to calculate actual value in metric units." | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"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.0" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |