Image Processing: Cartoonify your Image using OpenCV-Python

Turn your image into a cartoon using bilateralFilter() function

Rohit Kumar Thakur

Nowadays playing with images is a hobby of many people. People usually click pictures and add filters or customize the images with different stuff and put it on social media. Cartooning the image is a new trend. People use different apps to transform their images into cartoon images.

But we are programmers, we don’t do what normal people do. We are interested more in the process involved in the transformation of simple RGB images to cartoon images. In this image processing segment, we are going to use OpenCV-Python to cartoonify our image.

Photo by h heyerlein on Unsplash

Well, the conversion of the image to cartoon is more about the detection of edges of the image. If you detect the edge well of an image, then the cartooning effect will be much more effective on that image. There are many algorithms available for this, hence there is more than one way to do this. We will be using the bilateralFilter() function from OpenCV-Python.

I generally write and run code in Google Colab. You can access the full code in Google Colab here.
In this project, we will go through these main steps:

  1. Import the required libraries
  2. Load the image
  3. Initialize the parameters to be used
  4. Use the Gaussian pyramid’s downsampling to reduce the image size
  5. Apply bilateral filters iteratively
  6. Use upsampling to enlarge the image to the original size
  7. Blur the image with the median filter
  8. Detect and enhance the edges
  9. Convert the grayscale edge image back into an RGB color image
  10. Display the image

We have to go through these nine steps to get the desired output. So, let’s start.

Step 1:

import cv2
import numpy as np
import matplotlib.pylab as plt
from google.colab.patches import cv2_imshow
from google.colab import files

Step 2:

def read_file(filename):
image = cv2.imread(filename)
cv2_imshow(image)
return image
uploaded = files.upload()
filename = next(iter(uploaded))
image = read_file(filename)

If you are working on Google Colab then you can write down the above code. But if you are using Jupyter notebook, then simply add the path of the image you want to use. Both are the same thing.

Step 3:

num_down = 2 
num_bilateral = 7
w, h, _ = image.shape

Initialize the parameters we are going to use. num_down represents the number of downsampling steps. num_bilateral represents the number of bilateral filtering steps.

Step 4:

img_color = np.copy(image)
for _ in range(num_down):
img_color = cv2.pyrDown(img_color)

Here we are reducing the size of the image. To reduce the size, we are using the Gaussian pyramid’s downsampling operation. We are reducing the size of the image to make the subsequent operations faster.

Step 5:

for _ in range(num_bilateral):
img_color = cv2.bilateralFilter(img_color, d=9, sigmaColor=0.1, sigmaSpace=0.01)

Here sigmaColor represents the filter sigma in the color and the sigmaSpace represents the coordinate spaces. We are applying bilateral filters iteratively here with a small diameter value. The parameter d represents the diameter of the neighborhood for each pixel.

Step 6:

for _ in range(num_down):
img_color = cv2.pyrUp(img_color)

To enlarge the image to the original size, we are using upsampling here.

Step 7:

img_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
img_blur = cv2.medianBlur(img_gray, 7)

We are converting the output image from step 6 to grayscale and blur the image with a filter called the median.

Step 8:

img_edge = cv2.adaptiveThreshold((255*img_blur).astype(np.uint8), \
255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, \
blockSize=9, C=2)

As we discussed above the cartooning the image is more about detecting the image’s edge. So in this step, we are detecting and enhancing the edges of the image we used.

Step 9:

img_edge = cv2.cvtColor(img_edge, cv2.COLOR_GRAY2RGB)
img_cartoon = cv2.bitwise_and(img_color, img_edge)

Conver the grayscale image back to the RGB image and compute the bitwise AND with the RGB image to get the final output cartoonish image.

Step 10:

fig = plt.figure(figsize=(20,10))
fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05)
plt.subplot(121)
plt.imshow(image)
plt.axis('off')
plt.title('Original Image', size=20)
plt.subplot(122)
plt.imshow(img_cartoon)
plt.axis('off')
plt.title('Cartoonized Image', size=20)
plt.show()

Finally, Display the output.

In the project, first, we have to remove the weak edges of the image, then convert the image into flat textures, and finally enhance the prominent edges of the image. For this, we used bilateralFilter(), medianBlur(), adaptiveThreshold(), and bitwise_and() functions from OpenCV-Python.

To keep the edges fairly sharp and textures smooth, we used the bilateralFilter() function from OpenCV-Python. Change the value of sigmaColor and sigmaSpace and see the change in the output of the image.

Further, the image was downsampled to create an image pyramid.

Next, we used bilateral filters to remove the unimportant details and subsequent upsampling was used to resize the image to its original size.

Finally, to flatten the texture, medianBlur was applied followed by masking the original image with the binary image obtained by adaptive thresholding,

After you execute the above codes successfully, you will see the output image. I tried with the image of Robert Downey Jr. and I got this output image.

Cartoonify image using OpenCV-Python

It’s not cool. It’s super cool.

Thanks for Reading !!, and if this article is helpful for you then Clap until your hands bleed.