OpenCV+Python:Part3–Image Gradients

In this post I will explain the application of Gradient or High pass Filters namely Sobel, Scharr and Laplacian

Sobel and Scharr

These perform Gaussian smoothing and differentiation operation and hence provides resistance against noise. The direction of the differentiation can be specified within the function along with the kernel size.

Laplacian

This calculates the laplacian of the image where the derivative at each position is found using the sobel derivatives

The following code snippet describes the use of the above given derivatives and gives an output of np.uint8 type with a kernel size of 5×5 —


import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('image.jpg',0)
laplacian = cv2.Laplacian(img,cv2.CV_64F)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)
plt.subplot(2,2,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,2),plt.imshow(laplacian,cmap = 'gray')
plt.title('Laplacian'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,3),plt.imshow(sobelx,cmap = 'gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,4),plt.imshow(sobely,cmap = 'gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])
plt.show()

The result–
gradient

One important thing to note in the above example is that the data type of the result image is taken as np.uint8 in which all Black to White transitions are considered Positive slopes but all the White to Black transitions are taken as Negative slope and hence are taken as zero in the final result and important edge information is lost. However if you want to keep the edge info intact you can use a higher data type like cv2.CV_16S, cv2.CV_64F etc, take its absolute value and convert it back to cv2.CV_8U.

The following code snippet demonstrates this procedure by applying a horizontal Sobel filter :


import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('image.jpg',0)
# Output dtype = cv2.CV_8U
sobelx8u = cv2.Sobel(img,cv2.CV_8U,1,0,ksize=5)
# Output dtype = cv2.CV_64F. Then take its absolute and convert to cv2.CV_8U
sobelx64f = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
abs_sobel64f = np.absolute(sobelx64f)
sobel_8u = np.uint8(abs_sobel64f)
plt.subplot(1,3,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,2),plt.imshow(sobelx8u,cmap = 'gray')
plt.title('Sobel CV_8U'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,3),plt.imshow(sobel_8u,cmap = 'gray')
plt.title('Sobel abs(CV_64F)'), plt.xticks([]), plt.yticks([])
plt.show()

The result:
gradient1

That’s all in this post…Sayonara!!

OpenCV+Python:Part3–Smoothing Images

In this post I will explain the low pass filters available in OpenCV. A low pass filter or an LPF is basically used in reducing the noise and/or blurring the image.

2D Convolution Filtering

In this method a window of 5×5 is formed around every pixel and the average is calculated of the value of the pixels falling within this window.This is done by using the cv2.filter2D() to convolve a kernel with an image
The following code snippet shows how to carry out the filtering:


import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('image.jpg')
kernel = np.ones((5,5),np.float32)/25
dst = cv2.filter2D(img,-1,kernel)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(dst),plt.title('Averaging')
plt.xticks([]), plt.yticks([])
plt.show()

The result–
2dconvolution

Image Blurring

Image blurring is achieved by applying a LPF. It basically removes the high frequency content basically noise.

1.)Averaging

This method simply takes a window of 3×3 and replaces the central pixel by the average value of this window using the cv2.blur() or cv2.boxFilter() function.

The following example shows how blurring is carried out:


import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('image.jpg')
blur = cv2.blur(img,(5,5))
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()

The result:
blurred

2.)Gaussian Filtering

In this method the height and width of the kernel(window) is passed into the function along with standard deviation along the X and Y directions. The height and width passed must be odd values and the deviations may be passed separately. If only one deviation is passed then both of them are considered equal. If no deviation is given, the function decides them on basis of the window(kernel) size.

Just modifying the above averaging code by replacing the blur statement with
blur = cv2.GaussianBlur(img,(5,5),0) will do the trick.

Result:
gaussian

3.)Median Filtering

In this case the median of the kernel window is decided and this value is assigned to the central pixel. In case of Gaussian filtering a value that does not exist in the original image may also be assigned, however in case of median filtering the value of the central pixel is always replaced by some pixel value from the image.

Just modifying the above averaging code by replacing the blur statement with
blur = cv2.medianBlur(img,5) will do the trick.

Result:
median_blurring

4.)Bilateral Filtering

In every other case the while blurring the edges along with noise also got blurred in the process. However the function cv2.bilateralFilter() is highly effective in removing noise while preserving the edges.
The bilateral filter uses the very same Gaussian technique except that now it also includes one more component. The Gaussian function defines a kernel and carries out the filtering considering only the kernel space, however this new component that applies to bilateral filtering uses intensity difference to define the kernel space thereby including pixels in the same intensity region. Therefore pixels lying at the edges displaying large intensity variations will not be included in the blurring and hence be preserved.

Just modifying the above averaging code by replacing the blur statement with
blur = cv2.bilateralFilter(img,9,75,75) will do the trick.

Result:
Bilateral

That’s all in this post!! Sayonara.