## https://www.pyimagesearch.com/2016/04/11/finding-extreme-points-in-contours-with-opencv/
# import the necessary packages
import imutils
import cv2
import matplotlib.pyplot
# ensure the plots are inside this notebook, not an external window
%matplotlib inline
# load the image, convert it to grayscale, and blur it slightly
image = cv2.imread("images/hand4.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
grayGaussian = cv2.GaussianBlur(gray, (5, 5), 0)
# plot different versions of the hand
f, axarr = matplotlib.pyplot.subplots(1,3, figsize = (18,5))
axarr[0].imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB), aspect='auto', interpolation='nearest')
axarr[1].imshow(gray, cmap='Greys_r', aspect='auto', interpolation='nearest')
axarr[2].imshow(grayGaussian, cmap='Greys_r', aspect='auto', interpolation='nearest')
<matplotlib.image.AxesImage at 0x1215498d0>
# threshold the image, then perform a series of erosions +
# dilations to remove any small regions of noise
thresh = cv2.threshold(grayGaussian, 45, 255, cv2.THRESH_BINARY)[1]
threshErode = cv2.erode(thresh, None, iterations=2)
threshDilate = cv2.dilate(threshErode, None, iterations=2)
# plot different versions of the hand
f, axarr = matplotlib.pyplot.subplots(1,3, figsize = (18,5))
axarr[0].imshow(thresh, cmap='Greys_r', aspect='auto', interpolation='nearest')
axarr[1].imshow(threshErode, cmap='Greys_r', aspect='auto', interpolation='nearest')
axarr[2].imshow(threshDilate, cmap='Greys_r', aspect='auto', interpolation='nearest')
<matplotlib.image.AxesImage at 0x1211340f0>
# find contours in thresholded image, then grab the largest one
cnts = cv2.findContours(threshDilate.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
c = max(cnts, key=cv2.contourArea)
# determine the most extreme points along the contour
extLeft = tuple(c[c[:, :, 0].argmin()][0])
extRight = tuple(c[c[:, :, 0].argmax()][0])
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])
# draw the outline of the object, then draw each of the
# extreme points, where the left-most is red, right-most
# is green, top-most is blue, and bottom-most is teal
cv2.drawContours(image, [c], -1, (0, 255, 255), 2)
cv2.circle(image, extLeft, 8, (0, 0, 255), -1)
cv2.circle(image, extRight, 8, (0, 255, 0), -1)
cv2.circle(image, extTop, 8, (255, 0, 0), -1)
cv2.circle(image, extBot, 8, (255, 255, 0), -1)
array([[[15, 14, 9], [15, 14, 9], [15, 14, 9], ..., [23, 21, 13], [23, 21, 13], [23, 21, 13]], [[15, 14, 9], [15, 14, 9], [15, 14, 9], ..., [23, 21, 13], [23, 21, 13], [23, 21, 13]], [[15, 15, 9], [15, 15, 9], [15, 15, 9], ..., [23, 21, 13], [23, 21, 13], [23, 21, 13]], ..., [[13, 13, 9], [13, 13, 9], [13, 13, 9], ..., [18, 18, 12], [18, 18, 12], [18, 18, 12]], [[13, 13, 9], [13, 13, 9], [13, 13, 9], ..., [18, 18, 12], [18, 18, 12], [18, 18, 12]], [[13, 13, 9], [13, 13, 9], [13, 13, 9], ..., [18, 18, 12], [18, 18, 12], [18, 18, 12]]], dtype=uint8)
matplotlib.pyplot.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
<matplotlib.image.AxesImage at 0x122434828>
c[2]
array([[479, 103]], dtype=int32)