2D Convolution Operation for Image Filtering

Convolution is the most commonly used mathematical operation for filtering in the domain of image processing. In simple words, convolution involves multiplication of two arrays. However, the process is different than conventional matrix multiplication for two reasons:

  • The multiplication of two matrices is an element wise multiplication followed by sum of those products.
  • The two matrices may not be of same size. Usually, one matrix (filter) is very small compare to the other matrix (original Image).

Let us understand this with an example. Consider the input image shown in Figure 1-1. We want to perform a convolution operation of this image with the kernel shown next to it. Now to perform convolution, we place the central pixel of the kernel at every location in the input image and perform linear combination of each pixel. Consider pixel I5 where the center of kernel (a5) is centered. We then calculate the output for this pixel as shown below:

O5 = I1 * a1 + I2 * a2 + I3 * a3 + I4 * a4 + I5 * a5 + I6 * a6 + I7 * a7 + I8 * a8 +I9 * a9

This is an element wise multiplication and the result is written to the same location of the highlight pixel (I5) shown in the output image. This will be repeated for all the pixels in the row wise and then in the column wise direction.

No image
Figure 1-1: An example of performing convolution on an image using a spatial kernel.

In OpenCV the 2D convolution operation is implemented using filter2D() method. The signature of the method is as shown below:

cv2.cv.filter2D( src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]] )

The parameters of the above function are described as below:

Parameter Description

src

The input image which can be grayscale or color image.

ddepth

The depth of the output image. If we set it to -1 the depth of the output image will be the same as the input image.

kernel

A user defined convolution kernel a single-channel floating point matrix.

anchor

It represents the kernel center. By default value is (-1,-1) which means that the anchor is at the kernel center.

delta

If this values is set then it is added to the output pixel.

borderType

The value of the border pixels.

Let us look at an example of how to apply 2D convolution on an image. Code 1-1 shows and example of application of convolution operator.

Code 1-1: 2D Convolution with an averaging kernel
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import cv2
import numpy as np
try:
    path = r'F:\img\lena.jpg'
    img = cv2.imread(path)   
    kernel = np.ones((9,9),np.float32)/91.0
    out = cv2.filter2D(img, ddepth= -1, kernel=kernel)
    cv2.imshow('Original Image',img)
    cv2.imshow('2D Convolution',out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
except Exception as e:
    print(str(e))

Line 1 and 2: We start by importing OpenCV and numpy libraries.
Line 3: This line defines a try block. The exception block (Line 11-12) is associated with this block. If any exception occurs, it throws it and code in exception block is executed.
Line 4: Define path of the image to read.
Line 5: The image is read.
Line 6: We defined a kernel of size 9x9. We also divided this kernel by the total number of elements (9x9). This makes sure that the kernel values are summed to 1.
Line 7: Using OpenCV’s filter2D() function we convolved the input image with the kernel. The first parameter is the input image, the second parameter ddepth=-1 indicates that the depth of the output image will be same as the input image. The last parameter is the kernel provided by the user. Note that we used a kernel that will result in average blurring of the image. Using different kernels we can perform different operations. We will see an example of sharping the image as well later in this section.
Line 8-9: It displays both original and convolved image.
Line 10: waitKey(0) function makes the window wait until user presses any keyboard button.
Line 11: Object of all the windows opened will be destroyed and closed.

The output obtained for the code shown above is shown in Figure 1-2.

No image
Figure 1-2: Original Image (left), 2D filter output using an averaging kernel (right).

Let us look at another example where we used a different kernel. Now instead of averaging we used a derivative operator particularly this kernel is called Laplacian kernel that is used to sharpen images.

Code 1-2: 2D Convolution with an sharpening kernel
 1
 2
 3
 4
 5
 6


 7
 8
 9
10
11
12
13
14
import cv2
import numpy as np
try:
    path = r'F:\img\coins.jpg'
    img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)   
    kernel = np.array([[0, 1, 0],
                       [1, -4, 1],
                       [0, 1, 0]])
    out = cv2.filter2D(img, ddepth= -1, kernel=kernel)
    out = cv2.convertScaleAbs(out)
    cv2.imshow('Original Image',img)
    cv2.imshow('2D Convolution',out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
except Exception as e:
    print(str(e))

The above code is exactly same as shown in Code 1-1 except Line 6. Here we changed the kernel only rest is the same code. The output of the above code is shown in Figure 1-3. Note that the all code is same as above except the kernel.

No image
Figure 1-3: Original Image (left), 2D filter output (right) using a sharpening filter.

To summarize, the filter2D() is a generic function to perform any convolution operation. All we need to do is to use a desired kernel and provide to the function and we will get the result accordingly.

OpenCV Tutorials