Reference: OpenCV 4 with Python Blueprints - Second Edition - Dr. Menua Gevorgyan, Arsen Mamikonyan, Michael Beyeler
Bilateral filter: reduce the color palette or the numbers of colors that are used in the image. This mimics a cartoon drawing, wherein a cartoonist typically has few colors to work with
Edge detection: to generate bold silhouettes. Note that before doing edge detection, we need to blur the image to suppress small-scale noise and details
Pseudocode:
- First, apply a bilateral filter to reduce the color palette of the image.
- Then, convert the original color image into grayscale.
- After that, apply a median blur to reduce image noise.
- Use adaptive thresholding to detect and emphasize the edges in an edge mask.
- Finally, combine the color image from step 1 with the edge mask from step 4.
import cv2 as cv
import numpy as np
from google.colab.patches import cv2_imshow
def cartoonize(rgb_image, num_pyr_downs=2, num_bilaterals=7):
# STEP 1 -- Apply a bilateral filter to reduce the color palette of
# the image.
downsampled_img = rgb_image
# Downsample the image using multiple pyrDown calls
for _ in range(num_pyr_downs):
downsampled_img = cv.pyrDown(downsampled_img)
# apply multiple bilateral filters
for _ in range(num_bilaterals):
filterd_small_img = cv.bilateralFilter(downsampled_img, 9, 9, 7)
# upsample it to the original size
filtered_normal_img = filterd_small_img
for _ in range(num_pyr_downs):
filtered_normal_img = cv.pyrUp(filtered_normal_img)
# check the result of filtered_normal_img
cv2_imshow(cv.resize(filtered_normal_img, (0, 0), fx=0.5, fy=0.5))
# make sure resulting image has the same dims as original
if filtered_normal_img.shape != rgb_image.shape:
filtered_normal_img = cv.resize(
filtered_normal_img, (rgb_image.shape[1], rgb_image.shape[0]))
# STEP 2 -- Convert the original color image into grayscale.
img_gray = cv.cvtColor(rgb_image, cv.COLOR_RGB2GRAY)
# STEP 3 -- Apply median blur to reduce image noise.
img_blur = cv.medianBlur(img_gray, 7)
# STEP 4 -- Use adaptive thresholding to detect and emphasize the edges
# in an edge mask.
gray_edges = cv.adaptiveThreshold(img_blur, 255,
cv.ADAPTIVE_THRESH_MEAN_C,
cv.THRESH_BINARY, 9, 2)
# STEP 5 -- Combine the color image from step 1 with the edge mask
# from step 4.
rgb_edges = cv.cvtColor(gray_edges, cv.COLOR_GRAY2RGB)
rgb_edges_resized = cv.resize(rgb_edges, (filtered_normal_img.shape[1], filtered_normal_img.shape[0]))
return cv.bitwise_and(filtered_normal_img, rgb_edges_resized)
# change this to your image's relative path
path = '/content/small-dog-owners-1.jpeg'
rgb_img = cv.imread(path, 1)
cv2_imshow(cv.resize(rgb_img, (0, 0), fx=0.5, fy=0.5))
img = cartoonize(rgb_img, num_pyr_downs=2, num_bilaterals=7)
cv2_imshow(cv.resize(img, (0, 0), fx=0.5, fy=0.5))