Summary
- Read an image file and convert the image from one color space (e.g. BGR to RGB).
- Select the filter (e.g. Gaussian Kernel function or any custom filter) and apply to the image for smoothing effect. The bigger the kernel size, the blurrier an image will be.
- To sharpen the image, get the difference between original and blurred images and add back that difference with sharpened ratio of your choice.
Getting Started with OpenCV
# import libraries
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# mount the google drive to get my image
from google.colab import drive
drive.mount('/content/gdrive')
# Load the image and change color space
def load_img():
img = cv2.imread(F'/content/gdrive/tiles.jpg').astype(np.float32) / 255
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
return img
def load_img_without_color_convert():
img = cv2.imread(F'/content/gdrive/tiles.jpg').astype(np.float32) / 255
return img
Open CV color was formatted in blue-green-red(BGR), so the image is convered to red-green-blue(RGB) scheme to show the image in a way human perceives the color.
# Display one image
def display_img(img):
fig = plt.figure(figsize=(12,10))
ax = fig.add_subplot(111)
ax.imshow(img)
# Display two images side by side
def display_side(img1, img2):
fig = plt.figure(figsize=(12, 10))
ax=fig.add_subplot(121)
ax.imshow(img1)
ax=fig.add_subplot(122)
ax.imshow(img2)
# Call the function and load the image
img = load_img()
How to Blur an Image
Gaussian kernel function is used to smoothe the image. The aspect ratio of the image is H: 2880, W: 2160, and the kernel function was applied to all three color channels.
# Gaussian Kernel
blurred_backyard = cv2.GaussianBlur(img,ksize=(15,15), /
sigmaX=10, sigmaY=10, borderType=4)
display_side(img, blurred_backyard)
As Kernel size increases, the image blurs more. Given the large image size (2160 by 2880), a small sized kernels such as 3 x 3 and 5 x 5 did not effectively blur the image. The kernel size of 31 x 31 delivered a clear blurring effect for this image. The sigma values in the Gaussian filter implies that there are some variation around its mean value. The larger the sigma values in both x and y, the blurrier an image gets.
The left is the original image and the right is the one after smoothing.
For the border, reflective border type was chosen. This is because the image showed my backyard and it was safe to assume similar pattern continues (fence, tree, and nextdoor house) beyond what’s showing on the image.
# other kenel functions
dst_blur = cv2.blur(img, ksize=(15,15), borderType=4)
# median blurring
dst_median = cv2.medianBlur(img,5)
Note that median blurring is highly effective to remove salt-and-pepper noise in an image.
How to Sharpen the Image
Unsharp masking from darkroom photography Sharpening calculates the difference between the original image and blurred image and adds the difference back to the original image. After all, both images are 2D matrices of the same size.
Sharpened image = original + sharpened_force x (original - blurred)
difference = img - blurred_backyard
display_side(img, difference)
The right image shows boundaries between objects. Lines are more obvious where contrasting colors are facing each other, like the light grey air conditioner unit and the brown backyard door. The difference is even clearer when multiplied by sharpenend_force. In this case, I set sharpened_force at x3 to give a striking difference.
# Unsharp masking (sharpening the image)
# sharp_background = original + (original - blurred) * sharpen_force
sharpen_force = 3
sharp_backyard = img + sharpen_force * difference
display_side(img, sharp_backyard)
Or we can use sharpen filter derived from the unsharp masking. The image is convolved with the sharpen filter to make the image more clear.
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
sharp_backyard2 = cv2.filter2D(img, ddepth=-1, kernel=kernel)
display_side(img, sharp_backyard2)