1.
MORPHOLOGICAL OPERATIONS
EROSION
# import the necessary packages
import argparse
import cv2
# construct the argument parser and parse the arguments
ap = [Link]()
ap.add_argument("-i", "--image", required=True,
help="path to input image")
args = vars(ap.parse_args())
# load the image, convert it to grayscale, and display it
image = [Link](args["image"])
gray = [Link](image, cv2.COLOR_BGR2GRAY)
[Link]("Original", image)
# apply a series of erosions
for i in range(0, 3):
eroded = [Link]([Link](), None, iterations=i + 1)
[Link]("Eroded {} times".format(i + 1), eroded)
[Link](0)
DILATION
# close all windows to cleanup the screen
[Link]()
[Link]("Original", image)
# apply a series of dilations
for i in range(0, 3):
dilated = [Link]([Link](), None, iterations=i + 1)
[Link]("Dilated {} times".format(i + 1), dilated)
[Link](0)
OPENING
# close all windows to cleanup the screen, then initialize
# a list of # of kernels sizes that will be applied
[Link]()
[Link]("Original", image)
kernelSizes = [(3, 3), (5, 5), (7, 7)]
# loop over the kernels sizes
for kernelSize in kernelSizes:
# construct a rectangular kernel from the current size and
# apply an "opening" operation
kernel = [Link](cv2.MORPH_RECT, kernelSize)
opening = [Link](gray, cv2.MORPH_OPEN, kernel)
[Link]("Opening: ({}, {})".format(
kernelSize[0], kernelSize[1]), opening)
[Link](0)
CLOSING
# close all windows to cleanup the screen
[Link]()
[Link]("Original", image)
# loop over the kernels sizes again
for kernelSize in kernelSizes:
# construct a rectangular kernel form the current size, but this
# time apply a "closing" operation
kernel = [Link](cv2.MORPH_RECT, kernelSize)
closing = [Link](gray, cv2.MORPH_CLOSE, kernel)
[Link]("Closing: ({}, {})".format(
kernelSize[0], kernelSize[1]), closing)
[Link](0)
MORPHOLOGICAL GRADIENT
# close all windows to cleanup the screen
[Link]()
[Link]("Original", image)
# loop over the kernels a final time
for kernelSize in kernelSizes:
# construct a rectangular kernel and apply a "morphological
# gradient" operation to the image
kernel = [Link](cv2.MORPH_RECT, kernelSize)
gradient = [Link](gray, cv2.MORPH_GRADIENT, kernel)
[Link]("Gradient: ({}, {})".format(
kernelSize[0], kernelSize[1]), gradient)
[Link](0)
BLACK HAT
# import the necessary packages
import argparse
import cv2
# construct the argument parser
#and parse the arguments
ap = [Link]()
ap.add_argument("-i", "--image",
required=True,
help="path to input image")
args = vars(ap.parse_args())
# load the image and convert it to grayscale
image = [Link](args["image"])
gray = [Link](image, cv2.COLOR_BGR2GRAY)
# construct a rectangular kernel (13x5) and apply a blackhat
# operation which enables us to find dark regions on a light
# background
rectKernel = [Link](cv2.MORPH_RECT, (13, 5))
blackhat = [Link](gray, cv2.MORPH_BLACKHAT, rectKernel)
WHITE/TOP HAT
# similarly, a tophat (also called a "whitehat") operation will
# enable us to find light regions on a dark background
tophat = [Link](gray, cv2.MORPH_TOPHAT, rectKernel)
# show the output images
[Link]("Original", image)
[Link]("Blackhat", blackhat)
[Link]("Tophat", tophat)
[Link](0)
2. SMOOTHING AND BLURRING
AVERAGE BLURRING
# import the necessary packages
import argparse
import cv2
# construct the argument parser and parse the arguments
ap = [Link]()
ap.add_argument("-i", "--image", type=str, default="[Link]",
help="path to input image")
args = vars(ap.parse_args())
# load the image, display it to our screen, and initialize a list of kernel sizes
# (to evaluate the relationship between kernel size and amount of blurring)
image = [Link](args["image"])
[Link]("Original", image)
kernelSizes = [(3, 3), (9, 9), (15, 15)]
# loop over the kernel sizes
for (kX, kY) in kernelSizes:
# apply an "average" blur to the image using the current kernel size
blurred = [Link](image, (kX, kY))
[Link]("Average ({}, {})".format(kX, kY), blurred)
[Link](0)
GAUSSIAN BLURRING
# close all windows to cleanup the screen
[Link]()
[Link]("Original", image)
# loop over the kernel sizes again
for (kX, kY) in kernelSizes:
# apply a "Gaussian" blur to the image
blurred = [Link](image, (kX, kY), 0)
[Link]("Gaussian ({}, {})".format(kX, kY), blurred)
[Link](0)
MEDIAN BLURRING
# close all windows to cleanup the screen
[Link]()
[Link]("Original", image)
# loop over the kernel sizes a final time
for k in (3, 9, 15):
# apply a "median" blur to the image
blurred = [Link](image, k)
[Link]("Median {}".format(k), blurred)
[Link](0)
BILATERAL BLURRING
# import the necessary packages
import argparse
import cv2
ap = [Link]()
ap.add_argument("-i", "--image", type=str, default="[Link]",
help="path to input image")
args = vars(ap.parse_args())
# load, display and construct a list of bilateral filtering parameters
image = [Link](args["image"])
[Link]("Original", image)
params = [(11, 21, 7), (11, 41, 21), (11, 61, 39)]
# loop over the diameter, sigma color, and sigma space
for (diameter, sigmaColor, sigmaSpace) in params:
# apply bilateral filtering to the image using the current set of parameters
blurred = [Link](image, diameter, sigmaColor, sigmaSpace)
# show the output image and associated parameters
title = "Blurred d={}, sc={}, ss={}".format(diameter, sigmaColor, sigmaSpace)
[Link](title, blurred)
[Link](0)
3. COLOR SPACES
RGB
# import the necessary packages
import argparse
import cv2
# construct the argument parser and parse the arguments
ap = [Link]()
ap.add_argument("-i", "--image", type=str, default="[Link]",
help="path to input image")
args = vars(ap.parse_args())
# load the original image and show it
image = [Link](args["image"])
[Link]("RGB", image)
# loop over each of the individual channels and display them
for (name, chan) in zip(("B", "G", "R"), [Link](image)):
[Link](name, chan)
# wait for a keypress, then close all open windows
[Link](0)
[Link]()
HSV
# convert the image to the HSV color space and show it
hsv = [Link](image, cv2.COLOR_BGR2HSV)
[Link]("HSV", hsv)
# loop over each of the individual channels and display them
for (name, chan) in zip(("H", "S", "V"), [Link](hsv)): [Link](name, chan)
# wait for a keypress, then close all open windows
[Link](0)
[Link]()
LAB
# convert the image to the L*a*b* color space and show it
lab = [Link](image, cv2.COLOR_BGR2LAB)
[Link]("L*a*b*", lab)
# loop over each of the individual channels and display them
for (name, chan) in zip(("L*", "a*", "b*"), [Link](lab)):
[Link](name, chan)
# wait for a keypress, then close all open windows
[Link](0)
[Link]()
GRAYSCALE
# show the original and grayscale versions of the image
gray = [Link](image, cv2.COLOR_BGR2GRAY)
[Link]("Original", image)
[Link]("Grayscale", gray)
[Link](0)
4. THRESHOLDING
SIMPLE THRESHOLDING
# import the necessary packages
import argparse
import cv2
# construct the argument parser and parse the arguments
ap = [Link]()
ap.add_argument("-i", "--image", type=str, required=True,
help="path to input image")
args = vars(ap.parse_args())
# load the image and display it
image = [Link](args["image"])
[Link]("Image", image)
# convert the image to grayscale and blur it slightly
gray = [Link](image, cv2.COLOR_BGR2GRAY)
blurred = [Link](gray, (7, 7), 0)
# apply basic thresholding -- the first parameter is the image
# we want to threshold, the second value is is our threshold
# check; if a pixel value is greater than our threshold (in this
# case, 200), we set it to be *black, otherwise it is *white*
(T, threshInv) = [Link](blurred, 200, 255,
cv2.THRESH_BINARY_INV)
[Link]("Threshold Binary Inverse", threshInv)
# using normal thresholding (rather than inverse thresholding)
(T, thresh) = [Link](blurred, 200, 255, cv2.THRESH_BINARY)
[Link]("Threshold Binary", thresh)
# visualize only the masked regions in the image
masked = cv2.bitwise_and(image, image, mask=threshInv)
[Link]("Output", masked)
[Link](0)
OTSU’S THRESHOLDING
# import the necessary packages
import argparse
import cv2
# construct the argument parser and parse the arguments
ap = [Link]()
ap.add_argument("-i", "--image", type=str, required=True,
help="path to input image")
args = vars(ap.parse_args())
# load the image and display it
image = [Link](args["image"])
[Link]("Image", image)
# convert the image to grayscale and blur it slightly
gray = [Link](image, cv2.COLOR_BGR2GRAY)
blurred = [Link](gray, (7, 7), 0)
# apply Otsu's automatic thresholding which automatically
determines
# the best threshold value
(T, threshInv) = [Link](blurred, 0, 255,
cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
[Link]("Threshold", threshInv)
print("[INFO] otsu's thresholding value: {}".format(T))
# visualize only the masked regions in the image
masked = cv2.bitwise_and(image, image, mask=threshInv)
[Link]("Output", masked)
[Link](0)
ADAPTIVE THRESHOLDING
# import the necessary packages
import argparse
import cv2
# construct the argument parser and parse the arguments
ap = [Link]()
ap.add_argument("-i", "--image", type=str, required=True,
help="path to input image")
args = vars(ap.parse_args())
# load the image and display it
image = [Link](args["image"])
[Link]("Image", image)
# convert the image to grayscale and blur it slightly
gray = [Link](image, cv2.COLOR_BGR2GRAY)
blurred = [Link](gray, (7, 7), 0)
# apply simple thresholding with a hardcoded threshold
(T, threshInv) = [Link](blurred, 230, 255,
cv2.THRESH_BINARY_INV)
[Link]("Simple Thresholding", threshInv)
[Link](0)
# apply Otsu's automatic thresholding
(T, threshInv) = [Link](blurred, 0, 255,
cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
[Link]("Otsu Thresholding", threshInv)
[Link](0)
# instead of manually specifying the threshold value, we can use
# adaptive thresholding to examine neighborhoods of pixels and
# adaptively threshold each neighborhood
thresh = [Link](blurred, 255,
cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 21, 10)
[Link]("Mean Adaptive Thresholding", thresh)[Link](0)
# perform adaptive thresholding again, this time using a Gaussian
# weighting versus a simple mean to compute our local threshold
# value
thresh = [Link](blurred, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 21, 4)
[Link]("Gaussian Adaptive Thresholding", thresh)
[Link](0)
6. CONVOLUTIONS
# import the necessary packages
from [Link] import rescale_intensity
import numpy as np
import argparse
import cv2
def convolve(image, kernel):
# grab the spatial dimensions of the image, along with the spatial dimensions
# of the kernel
(iH, iW) = [Link][:2]
(kH, kW) = [Link][:2]
# allocate memory for the output image, taking care to "pad" the borders of the
# input image so the spatial size (i.e., width and height) are not reduced
pad = (kW - 1) // 2
image = [Link](image, pad, pad, pad, pad,
cv2.BORDER_REPLICATE)
output = [Link]((iH, iW), dtype="float32")
# loop over the input image, "sliding" the kernel across each (x, y)-coordinate
# from left-to-right and top to bottom
for y in [Link](pad, iH + pad):
for x in [Link](pad, iW + pad):
# extract the ROI of the image by extracting the *center* region of the current
# (x, y)-coordinates dimensions
roi = image[y - pad:y + pad + 1, x - pad:x + pad + 1]
# perform the actual convolution by taking the element-wise multiplicate
# between the ROI and the kernel, then summing the matrix
k = (roi * kernel).sum()
# store the convolved value in the output (x,y)- coordinate of the output image
output[y - pad, x - pad] = k
# rescale the output image to be in the range [0, 255]
output = rescale_intensity(output, in_range=(0, 255))
output = (output * 255).astype("uint8")
# return the output image
return output
# construct the argument parse and parse the arguments
ap = [Link]()
ap.add_argument("-i", "--image", required=True,
help="path to the input image")
args = vars(ap.parse_args())
# construct average blurring kernels used to smooth an image
smallBlur = [Link]((7, 7), dtype="float") * (1.0 / (7 * 7))
largeBlur = [Link]((21, 21), dtype="float") * (1.0 / (21 * 21))
# construct a sharpening filter
sharpen = [Link]((
[0, -1, 0],
[-1, 5, -1],
[0, -1, 0]), dtype="int")
# construct the Laplacian kernel used to detect edge-like Regions of an image
laplacian = [Link]((
[0, 1, 0],
[1, -4, 1],
[0, 1, 0]), dtype="int")
# construct the Sobel x-axis kernel
sobelX = [Link]((
[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]), dtype="int")
# construct the Sobel y-axis kernel
sobelY = [Link]((
[-1, -2, -1],
[0, 0, 0],
[1, 2, 1]), dtype="int")
# construct the kernel bank, a list of kernels we're going to apply using both
# our custom `convole` function and OpenCV's `filter2D` function
kernelBank = (
("small_blur", smallBlur),
("large_blur", largeBlur),
("sharpen", sharpen),
("laplacian", laplacian),
("sobel_x", sobelX),
("sobel_y", sobelY)
)
# load the input image and convert it to grayscale
image = [Link](args["image"])
gray = [Link](image, cv2.COLOR_BGR2GRAY)
# loop over the kernels
for (kernelName, kernel) in kernelBank:
# apply the kernel to the grayscale image using both our custom `convole`
# function and OpenCV's `filter2D` function
print("[INFO] applying {} kernel".format(kernelName))
convoleOutput = convolve(gray, kernel)
opencvOutput = cv2.filter2D(gray, -1, kernel)
# show the output images
[Link]("original", gray)
[Link]("{} - convole".format(kernelName), convoleOutput)
[Link]("{} - opencv".format(kernelName), opencvOutput)
[Link](0)
[Link]()
7. IMAGE GRADIENTS
# import the necessary packages
import argparse
import cv2
# construct the argument parser and parse the arguments
ap = [Link]()
ap.add_argument("-i", "--image", type=str, required=True,
help="path to input image")
ap.add_argument("-s", "--scharr", type=int, default=0,
help="path to input image")
args = vars(ap.parse_args())
# load the image, convert it to grayscale, and display the original
# grayscale image
image = [Link](args["image"])
gray = [Link](image, cv2.COLOR_BGR2GRAY)
[Link]("Gray", gray)
# set the kernel size, depending on whether we are using the Sobel
# operator of the Scharr operator, then compute the gradients along
# the x and y axis, respectively
ksize = -1 if args["scharr"] > 0 else 3
gX = [Link](gray, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=ksize)
gY = [Link](gray, ddepth=cv2.CV_32F, dx=0, dy=1, ksize=ksize)
# the gradient magnitude images are now of the floating point data
# type, so we need to take care to convert them back a to unsigned
# 8-bit integer representation so other OpenCV functions can operate
# on them and visualize them
gX = [Link](gX)
gY = [Link](gY)
# combine the gradient representations into a single image
combined = [Link](gX, 0.5, gY, 0.5, 0)
# show our output images
[Link]("Sobel/Scharr X", gX)
[Link]("Sobel/Scharr Y", gY)
[Link]("Sobel/Scharr Combined", combined)
[Link](0)
$ python opencv_sobel_scharr.py --image images/clonazepam_1mg.png
Top: Our original input image of the frontside and backside of a pill. Bottom
Left: Computing the image gradient along the x direction. Bottom Center: The
image gradients along the y direction. Bottom Right: Combining the x and y
gradient representations together.
$ python opencv_sobel_scharr.py --image images/clonazepam_1mg.png \
--scharr 1
# import the necessary packages
import [Link] as plt
import numpy as np
import argparse
import cv2
# construct the argument parser and parse the arguments
ap = [Link]()
ap.add_argument("-i", "--image", type=str, required=True,
help="path to input image")
args = vars(ap.parse_args())
# load the input image and convert it to grayscale
image = [Link](args["image"])
gray = [Link](image, cv2.COLOR_BGR2GRAY)
# compute gradients along the x and y axis, respectively
gX = [Link](gray, cv2.CV_64F, 1, 0)
gY = [Link](gray, cv2.CV_64F, 0, 1)
# compute the gradient magnitude and orientation
magnitude = [Link]((gX ** 2) + (gY ** 2))
orientation = np.arctan2(gY, gX) * (180 / [Link]) % 180
# initialize a figure to display the input grayscale image along with
# the gradient magnitude and orientation representations, respectively
(fig, axs) = [Link](nrows=1, ncols=3, figsize=(8, 4))
# plot each of the images
axs[0].imshow(gray, cmap="gray")
axs[1].imshow(magnitude, cmap="jet")
axs[2].imshow(orientation, cmap="jet")
# set the titles of each axes
axs[0].set_title("Grayscale")
axs[1].set_title("Gradient Magnitude")
axs[2].set_title("Gradient Orientation [0, 180]")
# loop over each of the axes and turn off the x and y ticks
for i in range(0, 3):
axs[i].get_xaxis().set_ticks([])
axs[i].get_yaxis().set_ticks([])
# show the plots
plt.tight_layout()
[Link]()
8. EDGE DETECTION
# import the necessary packages
import argparse
import cv2
# construct the argument parser and parse the arguments
ap = [Link]()
ap.add_argument("-i", "--image", type=str, required=True,
help="path to input image")
args = vars(ap.parse_args())
# load the image, convert it to grayscale, and blur it slightly
image = [Link](args["image"])
gray = [Link](image, cv2.COLOR_BGR2GRAY)
blurred = [Link](gray, (5, 5), 0)
# show the original and blurred images
[Link]("Original", image)
[Link]("Blurred", blurred)
# compute a "wide", "mid-range", and "tight" threshold for the edges
# using the Canny edge detector
wide = [Link](blurred, 10, 200)
mid = [Link](blurred, 30, 150)
tight = [Link](blurred, 240, 250)
# show the output Canny edge maps
[Link]("Wide Edge Map", wide)
[Link]("Mid Edge Map", mid)
[Link]("Tight Edge Map", tight)
[Link](0)
Applying Canny edge detection to a collection of coins using a wide range, mid
range, and tight range of thresholds.
9. AUTOMATIC CANNY EDGE DETECTION
# import the necessary packages
import numpy as np
import argparse
import glob
import cv2
def auto_canny(image, sigma=0.33):
# compute the median of the single channel pixel intensities
v = [Link](image)
# apply automatic Canny edge detection using the computed median
lower = int(max(0, (1.0 - sigma) * v))
upper = int(min(255, (1.0 + sigma) * v))
edged = [Link](image, lower, upper)
# return the edged image
return edged
# construct the argument parse and parse the arguments
ap = [Link]()
ap.add_argument("-i", "--images", required=True,
help="path to input dataset of images")
args = vars(ap.parse_args())
# loop over the images
for imagePath in [Link](args["images"] + "/*.jpg"):
# load the image, convert it to grayscale, and blur it slightly
image = [Link](imagePath)
gray = [Link](image, cv2.COLOR_BGR2GRAY)
blurred = [Link](gray, (3, 3), 0)
# apply Canny edge detection using a wide threshold, tight
# threshold, and automatically determined threshold
wide = [Link](blurred, 10, 200)
tight = [Link](blurred, 225, 250)
auto = auto_canny(blurred)
# show the images
[Link]("Original", image)
[Link]("Edges", [Link]([wide, tight, auto]))
[Link](0)