We're going to use the same sample image used in other pages in this section - a photo I took of two pens on a desk. You will need to import some stuff:
import cv2from matplotlib import pyplot as plt
# read an image with OpenCVimage = cv2.imread('pens.jpg')# transform into RGB as OpenCV reads in BGR (and Matplotlib uses RGB)RGB_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)# show itplt.imshow(RGB_image)plt.grid()plt.show();
Blurring is also called smoothing and it is an operation typically used to reduce noise on the source. It consists in applying a filter to the image. Let's see what this means.
The operation goes like this:
whererepresents the transformed value of the pixel at position ,is the kernel andrepresents the original pixels. What the sum is doing is weighing every pixel by the kernel and considering its neighbourhood. The kernel is a matrix which determines how should the neighbourhood be factored in.
In the following, we'll go through some common types of filters and we'll try them out on the image.
Each pixel value gets transformed into the mean of its neighbours, each of which contributes with equal weight. The kernelis a matrix with the same value at each place, and this value is
whereare the (width and height) dimensions of the matrix. In other words, this filter is considering a neighbourhood rectangle of dimensionaround each pixel and averaging the intensities values inside it, assigning to pixels.
# a normalised box filter with kernel 50X50 and showing resultnb = cv2.blur(RGB_image, (50, 50))plt.imshow(nb)plt.grid()plt.show();
It's the most popular but not the fastest. The kernel is given by a gaussian in 2 dimensions, so that at a pointit is:
This way, the pixel in the middle is given the largest weight and this weight decreases normally with distance to the pixel in consideration. Look at the docs for the implementation of this filter in OpenCV3.
# a Gaussian filter with kernel 49X49 and and showing result# Note that the third (required) arg is the sigma_x, if 0 means both sigma_x and sigma_y are calculated from the# kernel size. Also note kernel size must be odd (not sure why this constraint)gb = cv2.GaussianBlur(RGB_image, (49, 49), 0)plt.imshow(gb)plt.grid()plt.show();
Each pixel gets replaced with the median of its neighbours (those in a square around it).
Avoids (to a certain extent) smoothing the edges in a picture (all other filters don't avoid that). Considers neighbouring pixels with weight. In a region of pixels similar in intensity, it will replace pixel with the average of neighbourhood, acting similarly to other filters; in a region where there is a boundary of two intensity areas, that is, a region where pixels on one side are sensibly brighter than those on the other side, a bilateral filter yields a value of 1 for pixels on the same side and 0 for the others. See the detailed explanation in the references for a detailed explanation and the OpenCV3 docs for the API.
Note that it's a quite slow algorithm, especially for large diameters of the neighbourhood.
# a bilateral filter with kernel of diameter 15 and sigmas in color space and coordinate spacebb = cv2.bilateralFilter(RGB_image, 15, 2, 2)plt.imshow(bb)plt.grid()plt.show();
Inverting an image means subtracting each pixel value from 255, so that white becomes black and vice versa.
# make the sample image grayscalegray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# invert itinverted = 255 - gray# Plot both gray image and invertedplt.gray()f, (ax1, ax2) = plt.subplots(1, 2, sharey=True)ax1.grid()ax1.imshow(gray)ax2.grid()ax2.imshow(inverted)plt.show();
Thresholding is a way to modify the pixels of an image based on a given threshold in their intensity/colour.
See the API call
cv2.threshold: it needs the grayscale image as first argument, the thresholdas the second argument and the value to assign as the third argument in the case of a binary and binary inverted thresholding.
See the OpenCV docs for an explanation of thresholding with graphics on OpenCV itself.
Applied to grayscale images, it sets the pixel to a new value if it exceeds a given threshold and to another value otherwise. Modes are, calling the pixel,the value to set andthe threshold:
threshold to zero:
threshold to zero inverted:
# binary threshold: put 255 (white) if pixel passes 100 threshold, 0 (black) otherwisedest = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)plt.gray()plt.grid()plt.imshow(dest)plt.show();
The code is the same, what changes is the use of
Code is the same, it uses
Same code, uses
Same code, uses
Applied to grayscale images, the threshold is calculated locally so it is different for each region and this accounts for different conditions like illumination. Modes are binary and binary inverted, as above, with the difference that. The pixel gets set to a specified new value. Methods are:
Adaptive mean:is the average of the neighbourhood of pixel, the neighbourhood being a square of specified size around pixel
Adaptive gaussian:is a weighted sum, with gaussian weights of the neighbourhood of pixel . The standard deviation depends on the block size.
# adaptive mean thresholding with binary method and a neighborhood of 3X3# note that last arg (required) gets subtracted from the mean for computing the thresholddest = cv2.adaptiveThreshold(gray, 100, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 3, 0)plt.gray()plt.grid()plt.imshow(dest)plt.show();
# adaptive gaussian thresholding with binary method and a neighborhood of 3X3# note that last arg (required) gets subtracted from the mean for computing the thresholddest = cv2.adaptiveThreshold(gray, 100, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 3, 0)plt.gray()plt.grid()plt.imshow(dest)plt.show();
This (see the OpenCV docs) is a global thresholding method but the value of the threshold is computed as the mean value in between the two peaks of a bimodal image (see page). For this reason, it is not good on non-bimodal images. It minimises the weighted within-class variance where a class is the set of pixels around a peak.
# Otsu binarisationdest = cv2.threshold(gray, 100, 255, cv2.THRESH_OTSU)plt.gray()plt.grid()plt.imshow(dest)plt.show();
A detailed explanation of the bilateral filter, University of Edinburgh, School of Informatics
The explanation of thresholding on OpenCV itself
N Otsu, A Threshold Selection Method from Gray-Level Histograms, IEEE Transactions on Systems, Man and Cybernetics, 9, 1979.