Creating a vignette filter

Using all the information we have, let's see if we can create a nice vignette filter. The output will look something like the following:

Creating a vignette filter

Here is the code to achieve this effect:

import cv2
import numpy as np

img = cv2.imread('input.jpg')
rows, cols = img.shape[:2]

# generating vignette mask using Gaussian kernels
kernel_x = cv2.getGaussianKernel(cols,200)
kernel_y = cv2.getGaussianKernel(rows,200)
kernel = kernel_y * kernel_x.T
mask = 255 * kernel / np.linalg.norm(kernel)
output = np.copy(img)

# applying the mask to each channel in the input image
for i in range(3):
    output[:,:,i] = output[:,:,i] * mask

cv2.imshow('Original', img)
cv2.imshow('Vignette', output)
cv2.waitKey(0)

What's happening underneath?

The Vignette filter basically focuses the brightness on a particular part of the image and the other parts look faded. In order to achieve this, we need to filter out each channel in the image using a Gaussian kernel. OpenCV provides a function to do this, which is called getGaussianKernel. We need to build a 2D kernel whose size matches the size of the image. The second parameter of the function, getGaussianKernel, is interesting. It is the standard deviation of the Gaussian and it controls the radius of the bright central region. You can play around with this parameter and see how it affects the output.

Once we build the 2D kernel, we need to build a mask by normalizing this kernel and scaling it up, as shown in the following line:

 mask = 255 * kernel / np.linalg.norm(kernel)

This is an important step because if you don't scale it up, the image will look black. This happens because all the pixel values will be close to 0 after you superimpose the mask on the input image. After this, we iterate through all the color channels and apply the mask to each channel.

How do we move the focus around?

We now know how to create a vignette filter that focuses on the center of the image. Let's say we want to achieve the same vignette effect, but we want to focus on a different region in the image, as shown in the following figure:

How do we move the focus around?

All we need to do is build a bigger Gaussian kernel and make sure that the peak coincides with the region of interest. Following is the code to achieve this:

import cv2
import numpy as np

img = cv2.imread('input.jpg')
rows, cols = img.shape[:2]

# generating vignette mask using Gaussian kernels
kernel_x = cv2.getGaussianKernel(int(1.5*cols),200)
kernel_y = cv2.getGaussianKernel(int(1.5*rows),200)
kernel = kernel_y * kernel_x.T
mask = 255 * kernel / np.linalg.norm(kernel)
mask = mask[int(0.5*rows):, int(0.5*cols):]
output = np.copy(img)

# applying the mask to each channel in the input image
for i in range(3):
    output[:,:,i] = output[:,:,i] * mask

cv2.imshow('Input', img)
cv2.imshow('Vignette with shifted focus', output)

cv2.waitKey(0)
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset