From 61653f54dd1d4e8cd4ffb3270190f6e9f04556c4 Mon Sep 17 00:00:00 2001 From: Cezanne Date: Thu, 26 Apr 2018 00:46:00 -0700 Subject: [PATCH] add L3 notebooks --- .../1. Harris Corner Detection.ipynb | 121 +++++++++ .../2. Contour detection and features.ipynb | 233 ++++++++++++++++++ .../3. K-means.ipynb | 143 +++++++++++ 3 files changed, 497 insertions(+) create mode 100644 3_Types_of_Features_Image_Segmentation/1. Harris Corner Detection.ipynb create mode 100644 3_Types_of_Features_Image_Segmentation/2. Contour detection and features.ipynb create mode 100644 3_Types_of_Features_Image_Segmentation/3. K-means.ipynb diff --git a/3_Types_of_Features_Image_Segmentation/1. Harris Corner Detection.ipynb b/3_Types_of_Features_Image_Segmentation/1. Harris Corner Detection.ipynb new file mode 100644 index 0000000..a6772ab --- /dev/null +++ b/3_Types_of_Features_Image_Segmentation/1. Harris Corner Detection.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Harris Corner Detection" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import resources and display image" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import cv2\n", + "\n", + "%matplotlib inline\n", + "\n", + "# Read in the image\n", + "image = cv2.imread('images/waffle.jpg')\n", + "\n", + "# Make a copy of the image\n", + "image_copy = np.copy(image)\n", + "\n", + "# Change color to RGB (from BGR)\n", + "image_copy = cv2.cvtColor(image_copy, cv2.COLOR_BGR2RGB)\n", + "\n", + "plt.imshow(image_copy)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Detect corners" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Convert to grayscale\n", + "gray = cv2.cvtColor(image_copy, cv2.COLOR_RGB2GRAY)\n", + "gray = np.float32(gray)\n", + "\n", + "# Detect corners \n", + "dst = cv2.cornerHarris(gray, 2, 3, 0.04)\n", + "\n", + "# Dilate corner image to enhance corner points\n", + "dst = cv2.dilate(dst,None)\n", + "\n", + "plt.imshow(dst, cmap='gray')\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Extract and display strong corners" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## TODO: Define a threshold for extracting strong corners\n", + "# This value vary depending on the image and how many corners you want to detect\n", + "# Try changing this free parameter, 0.1, to be larger or smaller ans see what happens\n", + "thresh = 0.1*dst.max()\n", + "\n", + "# Create an image copy to draw corners on\n", + "corner_image = np.copy(image_copy)\n", + "\n", + "# Iterate through all the corners and draw them on the image (if they pass the threshold)\n", + "for j in range(0, dst.shape[0]):\n", + " for i in range(0, dst.shape[1]):\n", + " if(dst[j,i] > thresh):\n", + " # image, center pt, radius, color, thickness\n", + " cv2.circle( corner_image, (i, j), 1, (0,255,0), 1)\n", + "\n", + "plt.imshow(corner_image)" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "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.6.3" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/3_Types_of_Features_Image_Segmentation/2. Contour detection and features.ipynb b/3_Types_of_Features_Image_Segmentation/2. Contour detection and features.ipynb new file mode 100644 index 0000000..8c7f0c3 --- /dev/null +++ b/3_Types_of_Features_Image_Segmentation/2. Contour detection and features.ipynb @@ -0,0 +1,233 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Finding Contours" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import resources and display image" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import cv2\n", + "\n", + "%matplotlib inline\n", + "\n", + "# Read in the image\n", + "image = cv2.imread('images/thumbs_up_down.jpg')\n", + "\n", + "# Change color to RGB (from BGR)\n", + "image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n", + "\n", + "plt.imshow(image)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Produce a binary image for finding contours" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Convert to grayscale\n", + "gray = cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)\n", + "\n", + "# Create a binary thresholded image\n", + "retval, binary = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)\n", + "\n", + "plt.imshow(binary, cmap='gray')\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Find and draw the contours" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Find contours from thresholded, binary image\n", + "retval, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)\n", + "\n", + "# Draw all contours on a copy of the original image\n", + "contours_image = np.copy(image)\n", + "contours_image = cv2.drawContours(contours_image, contours, -1, (0,255,0), 3)\n", + "\n", + "plt.imshow(contours_image)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Contour Features\n", + "\n", + "Every contour has a number of features that you can calculate, including the area of the contour, it's orientation (the direction that most of the contour is pointing in), it's perimeter, and many other properties outlined in [OpenCV documentation, here](http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contour_properties/py_contour_properties.html).\n", + "\n", + "In the next cell, you'll be asked to identify the orientations of both the left and right hand contours. The orientation should give you an idea of which hand has its thumb up and which one has its thumb down!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Orientation\n", + "\n", + "The orientation of an object is the angle at which an object is directed. To find the angle of a contour, you should first find an ellipse that fits the contour and then extract the `angle` from that shape.\n", + " \n", + "```python\n", + "# Fit an ellipse to a contour and extract the angle from that ellipse\n", + "(x,y), (MA,ma), angle = cv2.fitEllipse(selected_contour)\n", + "```\n", + "\n", + "**Orientation values**\n", + "\n", + "These orientation values are in degrees measured from the x-axis. A value of zero means a flat line, and a value of 90 means that a contour is pointing straight up!\n", + "\n", + "So, the orientation angles that you calculated for each contour should be able to tell us something about the general position of the hand. The hand with it's thumb up, should have a higher (closer to 90 degrees) orientation than the hand with it's thumb down.\n", + "\n", + "### TODO: Find the orientation of each contour" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## TODO: Complete this function so that \n", + "## it returns the orientations of a list of contours\n", + "## The list should be in the same order as the contours\n", + "## i.e. the first angle should be the orientation of the first contour\n", + "def orientations(contours):\n", + " \"\"\"\n", + " Orientation \n", + " :param contours: a list of contours\n", + " :return: angles, the orientations of the contours\n", + " \"\"\"\n", + " \n", + " # Create an empty list to store the angles in\n", + " # Tip: Use angles.append(value) to add values to this list\n", + " angles = []\n", + " \n", + " return angles\n", + "\n", + "\n", + "# ---------------------------------------------------------- #\n", + "# Print out the orientation values\n", + "angles = orientations(contours)\n", + "print('Angles of each contour (in degrees): ' + str(angles))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Bounding Rectangle\n", + "\n", + "In the next cell, you'll be asked to find the bounding rectangle around the *left* hand contour, which has its thumb up, then use that bounding rectangle to crop the image and better focus on that one hand!\n", + "\n", + "```python\n", + "# Find the bounding rectangle of a selected contour\n", + "x,y,w,h = cv2.boundingRect(selected_contour)\n", + "\n", + "# Draw the bounding rectangle as a purple box\n", + "box_image = cv2.rectangle(contours_image, (x,y), (x+w,y+h), (200,0,200),2)\n", + "```\n", + "\n", + "And to crop the image, select the correct width and height of the image to include.\n", + "\n", + "```python\n", + "# Crop using the dimensions of the bounding rectangle (x, y, w, h)\n", + "cropped_image = image[y: y + h, x: x + w] \n", + "```\n", + "\n", + "### TODO: Crop the image around a contour" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## TODO: Complete this function so that\n", + "## it returns a new, cropped version of the original image\n", + "def left_hand_crop(image, selected_contour):\n", + " \"\"\"\n", + " Left hand crop \n", + " :param image: the original image\n", + " :param selectec_contour: the contour that will be used for cropping\n", + " :return: cropped_image, the cropped image around the left hand\n", + " \"\"\"\n", + " \n", + " ## TODO: Detect the bounding rectangle of the left hand contour\n", + " \n", + " ## TODO: Crop the image using the dimensions of the bounding rectangle\n", + " # Make a copy of the image to crop\n", + " cropped_image = np.copy(image)\n", + " \n", + " return cropped_image\n", + "\n", + "\n", + "## TODO: Select the left hand contour from the list\n", + "## Replace this value\n", + "selected_contour = None\n", + "\n", + "\n", + "# ---------------------------------------------------------- #\n", + "# If you've selected a contour\n", + "if(selected_contour is not None):\n", + " # Call the crop function with that contour passed in as a parameter\n", + " cropped_image = left_hand_crop(image, selected_contour)\n", + " plt.imshow(cropped_image)" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "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.6.3" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/3_Types_of_Features_Image_Segmentation/3. K-means.ipynb b/3_Types_of_Features_Image_Segmentation/3. K-means.ipynb new file mode 100644 index 0000000..c2f2e5c --- /dev/null +++ b/3_Types_of_Features_Image_Segmentation/3. K-means.ipynb @@ -0,0 +1,143 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# K-means Clustering" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import resources and display image" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import cv2\n", + "\n", + "%matplotlib inline\n", + "\n", + "# Read in the image\n", + "## TODO: Check out the images directory to see other images you can work with\n", + "# And select one!\n", + "image = cv2.imread('images/monarch.jpg')\n", + "\n", + "# Change color to RGB (from BGR)\n", + "image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n", + "\n", + "plt.imshow(image)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Prepare data for k-means" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Reshape image into a 2D array of pixels and 3 color values (RGB)\n", + "pixel_vals = image.reshape((-1,3))\n", + "\n", + "# Convert to float type\n", + "pixel_vals = np.float32(pixel_vals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Implement k-means clustering" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# define stopping criteria\n", + "# you can change the number of max iterations for faster convergence!\n", + "criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2)\n", + "\n", + "## TODO: Select a value for k\n", + "# then perform k-means clustering\n", + "k = 3\n", + "retval, labels, centers = cv2.kmeans(pixel_vals, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)\n", + "\n", + "# convert data into 8-bit values\n", + "centers = np.uint8(centers)\n", + "segmented_data = centers[labels.flatten()]\n", + "\n", + "# reshape data into the original image dimensions\n", + "segmented_image = segmented_data.reshape((image.shape))\n", + "labels_reshape = labels.reshape(image.shape[0], image.shape[1])\n", + "\n", + "plt.imshow(segmented_image)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## TODO: Visualize one segment, try to find which is the leaves, background, etc!\n", + "plt.imshow(labels_reshape==0, cmap='gray')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# mask an image segment by cluster\n", + "\n", + "cluster = 0 # the first cluster\n", + "\n", + "masked_image = np.copy(image)\n", + "# turn the mask green!\n", + "masked_image[labels_reshape == cluster] = [0, 255, 0]\n", + "\n", + "plt.imshow(masked_image)" + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "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.6.3" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +}