For a convolution filter, the channel values at each output pixel are a weighted average of the corresponding channel values in a neighborhood of input pixels. We can put the weights in a matrix, called a convolution matrix or kernel . For example, consider the following kernel:
The central element is the weight for the source pixel that has the same indices as of the destination pixel. Other elements represent weights for the rest of the neighborhood of input pixels. Here, we are considering a 3 x 3 neighborhood. However, OpenCV supports kernels with any square and odd-numbered dimensions. This particular kernel is a type of edge-finding filter called a Laplacian filter. For a neighborhood of flat (same) color, it yields a black output pixel. For a neighborhood of high contrast, it yields a bright output pixel.
Let's consider another kernel where the central element is greater by 1:
Imgproc.blur(Mat src, Mat dst, Size ksize)
: It blurs the image by taking a simple average of a neighborhood of size ksize
. For example, if ksize
is new Size(5, 5)
, then the kernel is the following:{{0.04, 0.04, 0.04, 0.04, 0.04}, {0.04, 0.04, 0.04, 0.04, 0.04}, {0.04, 0.04, 0.04, 0.04, 0.04}, {0.04, 0.04, 0.04, 0.04, 0.04}, {0.04, 0.04, 0.04, 0.04, 0.04}}
Laplacian(Mat src, Mat dst, int ddepth, int ksize, double scale, double delta)
: It is a Laplacian edge-finding filter, as described previously. Results are multiplied by a constant (the scale argument) and added to another constant (the delta argument).Let's use a convolution filter as part of a more complex filter that draws heavy, black lines atop edge regions in the image. To achieve this effect, we also rely on two more static methods from OpenCV:
Core.bitwise_not(Mat src, Mat dst)
: This method inverts the image's brightness and colors, such that white becomes black, red becomes cyan, and so on. It is useful to us because our convolution filter will produce white edges on a black field, whereas we want the opposite: black edges on a white field.Core.multiply(Mat src1, Mat src2, Mat dst, double scale)
: This method blends a pair of images by multiplying their values together. The resulting values are scaled by a constant (the scale
argument). For example, scale
can be used to normalize the product to the [0, 255] range. For our purposes, Core.multiply
can serve to superimpose the black edges on the original image.The following is the implementation of the blackened edge effect in StrokeEdgesFilter
:
We will look at some other complex uses of convolution filters in subsequent chapters.
Next, let's add a user interface for enabling and disabling all our filters.